HTTP Request in Kotlin

后端 未结 11 2434
不知归路
不知归路 2020-11-28 06:59

I\'m completely new to Kotlin. I want to do a login validation using POST method and to get some information using GET method. I\'ve URL, server Username and Password alread

相关标签:
11条回答
  • 2020-11-28 07:14

    For Android, Volley is a good place to get started. For all platforms, you might also want to check out ktor client or http4k which are both good libraries.

    However, you can also use standard Java libraries like java.net.HttpURLConnection which is part of the Java SDK:

    fun sendGet() {
        val url = URL("http://www.google.com/")
    
        with(url.openConnection() as HttpURLConnection) {
            requestMethod = "GET"  // optional default is GET
    
            println("\nSent 'GET' request to URL : $url; Response Code : $responseCode")
    
            inputStream.bufferedReader().use {
                it.lines().forEach { line ->
                    println(line)
                }
            }
        }
    }
    

    Or simpler:

    URL("https://google.com").readText()
    
    0 讨论(0)
  • 2020-11-28 07:16

    Using only the standard library with minimal code!

    thread {
        val jsonStr = try { URL(url).readText() } catch (ex: Exception) { return@thread }
        runOnUiThread { displayOrWhatever(jsonStr) }
    }
    

    This starts a GET request on a new thread, leaving the UI thread to respond to user input. However, we can only modify UI elements from the main/UI thread, so we actually need a runOnUiThread block to show the result to our user. This enqueues our display code to be run on the UI thread soon.

    The try/catch is there so your app won't crash if you make a request with your phone's internet off. Add your own error handling (e.g. showing a Toast) as you please.

    .readText() is not part of the java.net.URL class but a Kotlin extension method, Kotlin "glues" this method onto URL. This is enough for plain GET requests, but for more control and POST requests you need something like the Fuel library.

    0 讨论(0)
  • 2020-11-28 07:19

    I think using okhttp is the easiest solution. Here you can see an example for POST method, sending a json, and with auth.

    val url = "https://example.com/endpoint"
    
    val client = OkHttpClient()
    
    val JSON = MediaType.get("application/json; charset=utf-8")
    val body = RequestBody.create(JSON, "{\"data\":\"$data\"}")
    val request = Request.Builder()
            .addHeader("Authorization", "Bearer $token")
            .url(url)
            .post(body)
            .build()
    
    val  response = client . newCall (request).execute()
    
    println(response.request())
    println(response.body()!!.string())
    

    Remember to add this dependency to your project https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp

    UPDATE: July 7th, 2019 I'm gonna give two examples using latest Kotlin (1.3.41), OkHttp (4.0.0) and Jackson (2.9.9).

    Get Method

    fun get() {
        val client = OkHttpClient()
        val url = URL("https://reqres.in/api/users?page=2")
    
        val request = Request.Builder()
                .url(url)
                .get()
                .build()
    
        val response = client.newCall(request).execute()
    
        val responseBody = response.body!!.string()
    
        //Response
        println("Response Body: " + responseBody)
    
        //we could use jackson if we got a JSON
        val mapperAll = ObjectMapper()
        val objData = mapperAll.readTree(responseBody)
    
        objData.get("data").forEachIndexed { index, jsonNode ->
            println("$index $jsonNode")
        }
    }
    

    POST Method

    fun post() {
        val client = OkHttpClient()
        val url = URL("https://reqres.in/api/users")
    
        //just a string
        var jsonString = "{\"name\": \"Rolando\", \"job\": \"Fakeador\"}"
    
        //or using jackson
        val mapperAll = ObjectMapper()
        val jacksonObj = mapperAll.createObjectNode()
        jacksonObj.put("name", "Rolando")
        jacksonObj.put("job", "Fakeador")
        val jacksonString = jacksonObj.toString()
    
        val mediaType = "application/json; charset=utf-8".toMediaType()
        val body = jacksonString.toRequestBody(mediaType)
    
        val request = Request.Builder()
                .url(url)
                .post(body)
                .build()
    
        val response = client.newCall(request).execute()
    
        val responseBody = response.body!!.string()
    
        //Response
        println("Response Body: " + responseBody)
    
        //we could use jackson if we got a JSON
        val objData = mapperAll.readTree(responseBody)
    
        println("My name is " + objData.get("name").textValue() + ", and I'm a " + objData.get("job").textValue() + ".")
    }
    
    0 讨论(0)
  • 2020-11-28 07:22

    GET and POST using OkHttp

    private const val CONNECT_TIMEOUT = 15L
    private const val READ_TIMEOUT = 15L
    private const val WRITE_TIMEOUT = 15L
    
    private fun performPostOperation(urlString: String, jsonString: String, token: String): String? {
        return try {
            val client = OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                .build()
    
            val body = jsonString.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
    
            val request = Request.Builder()
                .url(URL(urlString))
                .header("Authorization", token)
                .post(body)
                .build()
    
            val response = client.newCall(request).execute()
            response.body?.string()
        }
        catch (e: IOException) {
            e.printStackTrace()
            null
        }
    }
    
    private fun performGetOperation(urlString: String, token: String): String? {
        return try {
            val client = OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
                .build()
    
            val request = Request.Builder()
                .url(URL(urlString))
                .header("Authorization", token)
                .get()
                .build()
    
            val response = client.newCall(request).execute()
            response.body?.string()
        }
        catch (e: IOException) {
            e.printStackTrace()
            null
        }
    }
    

    Object serialization and deserialization

    @Throws(JsonProcessingException::class)
    fun objectToJson(obj: Any): String {
        return ObjectMapper().writeValueAsString(obj)
    }
    
    @Throws(IOException::class)
    fun jsonToAgentObject(json: String?): MyObject? {
        return if (json == null) { null } else {
            ObjectMapper().readValue<MyObject>(json, MyObject::class.java)
        }
    }
    

    Dependencies

    Put the following lines in your gradle (app) file. Jackson is optional. You can use it for object serialization and deserialization.

    implementation 'com.squareup.okhttp3:okhttp:4.3.1'
    implementation 'com.fasterxml.jackson.core:jackson-core:2.9.8'
    implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.8'
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
    
    0 讨论(0)
  • 2020-11-28 07:29

    Without adding additional dependencies, this works. You don't need Volley for this. This works using the current version of Kotlin as of Dec 2018: Kotlin 1.3.10

    If using Android Studio, you'll need to add this declaration in your AndroidManifest.xml:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    

    You should manually declare imports here. The auto-import tool caused me many conflicts.:

    import android.os.AsyncTask
    import java.io.BufferedReader
    import java.io.InputStreamReader
    import java.io.OutputStream
    import java.io.OutputStreamWriter
    import java.net.URL
    import java.net.URLEncoder
    import javax.net.ssl.HttpsURLConnection
    

    You can't perform network requests on a background thread. You must subclass AsyncTask.

    To call the method:

    NetworkTask().execute(requestURL, queryString)
    

    Declaration:

    private class NetworkTask : AsyncTask<String, Int, Long>() {
        override fun doInBackground(vararg parts: String): Long? {
            val requestURL = parts.first()
            val queryString = parts.last()
    
            // Set up request
            val connection: HttpsURLConnection = URL(requestURL).openConnection() as HttpsURLConnection
            // Default is GET so you must override this for post
            connection.requestMethod = "POST"
            // To send a post body, output must be true
            connection.doOutput = true
            // Create the stream
            val outputStream: OutputStream = connection.outputStream
            // Create a writer container to pass the output over the stream
            val outputWriter = OutputStreamWriter(outputStream)
            // Add the string to the writer container
            outputWriter.write(queryString)
            // Send the data
            outputWriter.flush()
    
            // Create an input stream to read the response
            val inputStream = BufferedReader(InputStreamReader(connection.inputStream)).use {
                // Container for input stream data
                val response = StringBuffer()
                var inputLine = it.readLine()
                // Add each line to the response container
                while (inputLine != null) {
                    response.append(inputLine)
                    inputLine = it.readLine()
                }
                it.close()
                // TODO: Add main thread callback to parse response
                println(">>>> Response: $response")
            }
            connection.disconnect()
    
            return 0
        }
    
        protected fun onProgressUpdate(vararg progress: Int) {
        }
    
        override fun onPostExecute(result: Long?) {
        }
    }
    
    0 讨论(0)
  • 2020-11-28 07:30

    Maybe the simplest GET

    For everybody stuck with NetworkOnMainThreadException for the other solutions: use AsyncTask or, even shorter, (yet still experimental) Coroutines:

    launch {
    
        val jsonStr = URL("url").readText()
    
    }
    

    If you need to test with plain http don't forget to add to your manifest: android:usesCleartextTraffic="true"


    For the experimental Coroutines you have to add to build.gradle as of 10/10/2018:

    kotlin {
        experimental {
            coroutines 'enable'
        }
    }
    dependencies {
        implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.24.0"
        implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.24.0"
        ...
    
    0 讨论(0)
提交回复
热议问题