How to make POST, GET, PUT and DELETE requests with HttpURLConnection using Kotlin

Last updated on: May 27, 2023

HttpURLConnection is a built-in class that provides support for HTTP connections.

If your URL starts with http:// you need to use HttpURLConnection, and if it starts with https:// you can use HttpURLConnection and HttpsURLConnection.

HttpsURLConnection extends HttpURLConnection, and provides some functionality to manage SSL.

Adding the libraries

Go to your app-level build.gradle file and add the following dependencies:

// ...

dependencies {

    // Coroutines to make the HTTP requests asynchronous(In the background thread)
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'

    // Gson to convert raw JSON to pretty JSON
    implementation 'com.google.code.gson:gson:2.8.6'

    // ...
}Code language: Kotlin (kotlin)

Adding Permissions

Go to the AndroidManifest.xml file and add the following permission to allow internet connection:

<uses-permission android:name="android.permission.INTERNET" />Code language: HTML, XML (xml)

Sending data using POST method

To send data to the server, you need to use the HTTP request method POST.

Before you upload the data, you have to define what type of data you are uploading (e.g., raw JSON, media, e.t.c). To do that, you need to set the MIME type.

  • application/json for raw JSON data
  • multipart/form-data for files, like images, pdfs, texts e.t.c
  • application/x-www-form-urlencoded for passing the paramers encoded in the URL

Uploading JSON data (application/json)

In this example, we’re going to POST the following data as raw JSON data in the URL: http://dummy.restapiexample.com/api/v1/create

  • name: Jack
  • salary: 3540
  • age: 23
fun rawJSON() {

    // Create JSON using JSONObject
    val jsonObject = JSONObject()
    jsonObject.put("name", "Jack")
    jsonObject.put("salary", "3540")
    jsonObject.put("age", "23")

    // Convert JSONObject to String
    val jsonObjectString = jsonObject.toString()

    GlobalScope.launch(Dispatchers.IO) {
        val url = URL("http://dummy.restapiexample.com/api/v1/create")
        val httpURLConnection = url.openConnection() as HttpURLConnection
        httpURLConnection.requestMethod = "POST"
        httpURLConnection.setRequestProperty("Content-Type", "application/json") // The format of the content we're sending to the server
        httpURLConnection.setRequestProperty("Accept", "application/json") // The format of response we want to get from the server
        httpURLConnection.doInput = true
        httpURLConnection.doOutput = true

        // Send the JSON we created
        val outputStreamWriter = OutputStreamWriter(httpURLConnection.outputStream)
        outputStreamWriter.write(jsonObjectString)
        outputStreamWriter.flush()

        // Check if the connection is successful
        val responseCode = httpURLConnection.responseCode
        if (responseCode == HttpURLConnection.HTTP_OK) {
            val response = httpURLConnection.inputStream.bufferedReader()
                    .use { it.readText() }  // defaults to UTF-8
            withContext(Dispatchers.Main) {

                // Convert raw JSON to pretty JSON using GSON library
                val gson = GsonBuilder().setPrettyPrinting().create()
                val prettyJson = gson.toJson(JsonParser.parseString(response))
                Log.d("Pretty Printed JSON :", prettyJson)

            }
        } else {
            Log.e("HTTPURLCONNECTION_ERROR", responseCode.toString())
        }
    }
}Code language: Kotlin (kotlin)

Uploading Files (multipart/form-data)

In the following example, we POST an email address and a text file.

It contains two body parts belonging to two different MIME types

First, we set the email and the name of the text file, and then we send the content of the .txt file.

The text file is called lorem_ipsum.txt and is inside the project’s assets folder.

We’re using the method getFileFromAssets to get the file.

fun formData() {

    // List of all MIME Types you can upload: https://www.freeformatter.com/mime-types-list.html

    // Get file from assets folder
    val file = getFileFromAssets(this@MainActivity, "lorem_ipsum.txt")

    GlobalScope.launch(Dispatchers.IO) {
        val url = URL("https://httpbin.org/post")

        val boundary = "Boundary-${System.currentTimeMillis()}"

        val httpsURLConnection = url.openConnection() as HttpsURLConnection
        httpsURLConnection.addRequestProperty(
                "Content-Type",
                "multipart/form-data; boundary=$boundary"
        )
        httpsURLConnection.requestMethod = "POST"
        httpsURLConnection.doInput = true
        httpsURLConnection.doOutput = true

        val outputStreamToRequestBody = httpsURLConnection.outputStream
        val httpRequestBodyWriter = BufferedWriter(OutputStreamWriter(outputStreamToRequestBody))

        // Add the email in the post data
        httpRequestBodyWriter.write("\n\n--$boundary\n")
        httpRequestBodyWriter.write("Content-Disposition: form-data; name=\"email\"")
        httpRequestBodyWriter.write("\n\n")
        httpRequestBodyWriter.write("jack@email.com")


        // Add the part to describe the file
        httpRequestBodyWriter.write("\n--$boundary\n")
        httpRequestBodyWriter.write("Content-Disposition: form-data;"
                + "name=\"upload_file.txt\";"
                + "filename=\"" + file.name + "\""
                + "\nContent-Type: text/plain\n\n")
        httpRequestBodyWriter.flush()

        // Write the file
        val inputStreamToFile = FileInputStream(file)
        var bytesRead: Int
        val dataBuffer = ByteArray(1024)
        while (inputStreamToFile.read(dataBuffer).also { bytesRead = it } != -1) {
            outputStreamToRequestBody.write(dataBuffer, 0, bytesRead)
        }
        outputStreamToRequestBody.flush()

        // End of the multipart request
        httpRequestBodyWriter.write("\n--$boundary--\n")
        httpRequestBodyWriter.flush()

        // Close the streams
        outputStreamToRequestBody.close()
        httpRequestBodyWriter.close()

        // Check if the connection is successful
        val responseCode = httpsURLConnection.responseCode
        if (responseCode == HttpURLConnection.HTTP_OK) {
            val response = httpsURLConnection.inputStream.bufferedReader()
                    .use { it.readText() }  // defaults to UTF-8
            withContext(Dispatchers.Main) {

                // Convert raw JSON to pretty JSON using GSON library
                val gson = GsonBuilder().setPrettyPrinting().create()
                val prettyJson = gson.toJson(JsonParser.parseString(response))
                Log.d("Pretty Printed JSON :", prettyJson)
                
            }
        } else {
            Log.e("HTTPURLCONNECTION_ERROR", responseCode.toString())
        }
    }
}

fun getFileFromAssets(context: Context, fileName: String): File = File(context.cacheDir, fileName).also {
    if (!it.exists()) {
        it.outputStream().use { cache ->
            context.assets.open(fileName).use { inputStream ->
                inputStream.copyTo(cache)
            }
        }
    }
}Code language: Kotlin (kotlin)

Uploading with parameters encoded in the URL (application/x-www-form-urlencoded)

To upload data with URL parameters, you need to create the string of parameters that has the form param1=value1&param2=value2&param3=value3 using the Uri Builder, and then convert it to byteArray and add them in the DataOutputStream.

fun urlEncoded() {

    // Add URL parameters
    val uriBuilder = Uri.Builder()
            .appendQueryParameter("name", "Jack")
            .appendQueryParameter("salary", "8054")
            .appendQueryParameter("age", "45")
            .build()

    val params = uriBuilder.toString().replace("?", "")  // Remove the "?" from the beginning of the parameters ?name=Jack&salary=8054&age=45
    val postData = params.toByteArray(StandardCharsets.UTF_8)

    GlobalScope.launch(Dispatchers.IO) {
        val url = URL("https://postman-echo.com/post")
        val httpsURLConnection = url.openConnection() as HttpsURLConnection
        httpsURLConnection.requestMethod = "POST"
        httpsURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded") // The format of the content we're sending to the server
        httpsURLConnection.setRequestProperty("Accept", "application/json") // The format of response we want to get from the server
        httpsURLConnection.doInput = true
        httpsURLConnection.doOutput = true
        val dataOutputStream = DataOutputStream(httpsURLConnection.outputStream)
        dataOutputStream.write(postData)

        // Check if the connection is successful
        val responseCode = httpsURLConnection.responseCode
        if (responseCode == HttpURLConnection.HTTP_OK) {
            val response = httpsURLConnection.inputStream.bufferedReader()
                    .use { it.readText() }  // defaults to UTF-8
            withContext(Dispatchers.Main) {

                // Convert raw JSON to pretty JSON using GSON library
                val gson = GsonBuilder().setPrettyPrinting().create()
                val prettyJson = gson.toJson(JsonParser.parseString(response))
                Log.d("Pretty Printed JSON :", prettyJson)

            }
        } else {
            Log.e("HTTPURLCONNECTION_ERROR", responseCode.toString())
        }
    }
}Code language: Kotlin (kotlin)

Retrieving data using GET method

To retrieve the data from the server, you need to use the HTTP request method GET.

In this example, we’re getting a list of employees from the URL: http://dummy.restapiexample.com/api/v1/employees

fun getMethod() {
    GlobalScope.launch(Dispatchers.IO) {
        val url = URL("http://dummy.restapiexample.com/api/v1/employees")
        val httpURLConnection = url.openConnection() as HttpURLConnection
        httpURLConnection.setRequestProperty("Accept", "application/json") // The format of response we want to get from the server
        httpURLConnection.requestMethod = "GET"
        httpURLConnection.doInput = true
        httpURLConnection.doOutput = false
        // Check if the connection is successful
        val responseCode = httpURLConnection.responseCode
        if (responseCode == HttpURLConnection.HTTP_OK) {
            val response = httpURLConnection.inputStream.bufferedReader()
                    .use { it.readText() }  // defaults to UTF-8
            withContext(Dispatchers.Main) {

                // Convert raw JSON to pretty JSON using GSON library
                val gson = GsonBuilder().setPrettyPrinting().create()
                val prettyJson = gson.toJson(JsonParser.parseString(response))
                Log.d("Pretty Printed JSON :", prettyJson)

            }
        } else {
            Log.e("HTTPURLCONNECTION_ERROR", responseCode.toString())
        }
    }
}Code language: Kotlin (kotlin)

Updating data using PUT method

To update the data, you need to use the HTTP request method PUT, which is almost the same as the POST method.

fun putMethod() {
    // Create JSON using JSONObject
    val jsonObject = JSONObject()
    jsonObject.put("name", "John")
    jsonObject.put("job", "Android Developer")

    // Convert JSONObject to String
    val jsonObjectString = jsonObject.toString()

    GlobalScope.launch(Dispatchers.IO) {
        val url = URL("https://reqres.in/api/users/2")
        val httpsURLConnection = url.openConnection() as HttpsURLConnection
        httpsURLConnection.requestMethod = "PUT"
        httpsURLConnection.setRequestProperty("Content-Type", "application/json") // The format of the content we're sending to the server
        httpsURLConnection.setRequestProperty("Accept", "application/json") // The format of response we want to get from the server
        httpsURLConnection.doInput = true
        httpsURLConnection.doOutput = false
        val outputStreamWriter = OutputStreamWriter(httpsURLConnection.outputStream)
        outputStreamWriter.write(jsonObjectString)
        outputStreamWriter.flush()

        // Check if the connection is successful
        val responseCode = httpsURLConnection.responseCode
        if (responseCode == HttpURLConnection.HTTP_OK) {
            val response = httpsURLConnection.inputStream.bufferedReader()
                    .use { it.readText() }  // defaults to UTF-8
            withContext(Dispatchers.Main) {

                // Convert raw JSON to pretty JSON using GSON library
                val gson = GsonBuilder().setPrettyPrinting().create()
                val prettyJson = gson.toJson(JsonParser.parseString(response))
                Log.d("Pretty Printed JSON :", prettyJson)
                
            }
        } else {
            Log.e("HTTPURLCONNECTION_ERROR", responseCode.toString())
        }
    }
}Code language: Kotlin (kotlin)

Removing data using DELETE method

To delete the data from the server, you need to use the HTTP request method DELETE.

fun deleteMethod() {
    GlobalScope.launch(Dispatchers.IO) {
        val url = URL("https://my-json-server.typicode.com/typicode/demo/posts/1")
        val httpsURLConnection = url.openConnection() as HttpsURLConnection
        httpsURLConnection.requestMethod = "DELETE"
        httpsURLConnection.doInput = true
        httpsURLConnection.doOutput = false

        // Check if the connection is successful
        val responseCode = httpsURLConnection.responseCode
        if (responseCode == HttpURLConnection.HTTP_OK) {
            val response = httpsURLConnection.inputStream.bufferedReader()
                    .use { it.readText() }  // defaults to UTF-8
            withContext(Dispatchers.Main) {

                // Convert raw JSON to pretty JSON using GSON library
                val gson = GsonBuilder().setPrettyPrinting().create()
                val prettyJson = gson.toJson(JsonParser.parseString(response))
                Log.d("Pretty Printed JSON :", prettyJson)
                
            }
        } else {
            Log.e("HTTPURLCONNECTION_ERROR", responseCode.toString())
        }
    }
}Code language: Kotlin (kotlin)

In this example, the URL I’m using for the DELETE method doesn’t return any response after deleting the item. That’s why the results are empty.

You can find the final project here

If you have any questionsplease feel free to leave a comment below

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments