All Articles

HTTP requests on Android using Ktor

Ktor logo

Ktor is a new framework for building asynchronous servers and clients. It’s 100% Kotlin and runs on Coroutines. It supports multiplatform projects which means you can use it for any project targeting Android, iOS or Javascript. In this blog, we will explore using the Ktor client to make HTTP requests in an Android App.

Building the client

Ktor client provides you with an interface to make HTTP requests, however, it relies on an engine to perform its duties. For Android, you can work with one of the following engines:

  • CIO (Coroutine-based I/O) which has no additional dependencies and uses the power of coroutines to execute requests asynchronously. It’s also the only engine compatible with Ktor WebSockets . Note: HTTP/2 is not supported.
// in build.gradle add
implementation "io.ktor:ktor-client-cio:$ktor_version"

// in your code, create the client
HttpClient(CIO)
  • Android which uses the usual HttpURLConnection and ThreadPool to execute requests.
// in build.gradle add
implementation "io.ktor:ktor-client-android:$ktor_version"

// in your code, create the client
HttpClient(Android)
  • OkHttp which depends on Square’s OkHttp client.
// in build.gradle add
implementation "io.ktor:ktor-client-okhttp:$ktor_version"

// in your code, create the client
HttpClient(Okhttp)

Configuring the client

Configuring Ktor client is super simple. It relies on what’s called Features. All you need is to install the Feature you want.

For example to add json serialization/de-serialization capabilities using Gson. It becomes as easy as

// You can replace CIO with your engine of choice
HttpClient(CIO) {
    install(JsonFeature) {
        serializer = GsonSerializer()
    }
}

Note: You will need to include the following dependency

implementation "io.ktor:ktor-client-gson:$ktor_version"

Configuring All outbound requests

Ktor HTTP client allows you to set some default configurations for all outbound requests. For example, adding a header to every request is as easy as

// You can replace CIO with your engine of choice
HttpClient(CIO) {
    install(DefaultRequest) {
        headers.append("Accept","application/xml;q=0.9")
        headers.append("Authorization","Bearer abc123")
    }
}

Making Requests

Finally, to make a request you can do

val client = HttpClient(CIO)
client.get<String>("https://eample.com")

Here is a full example which call Github API to get a list of public repositories names

data class Repo(
    @SerializedName("full_name") val name: String
)
CoroutineScope(Dispatchers.IO).launch {
    val client = HttpClient(CIO) {
		install(DefaultRequest) {
			headers.append("Accept", "application/vnd.github.v3+json")
		}

		install(JsonFeature) {
			serializer = GsonSerializer()
		}
    }
    client.get<List<Repo>>("https://api.github.com/repositories").forEach {
        repo -> Log.v("Ktor-Test", repo.name)
	}
	client.close()
}