Kotlin中的HTTP请求

Raj*_*r K 32 android kotlin

我对Kotlin完全不熟悉.我想使用POST方法进行登录验证,并使用GET方法获取一些信息.我已经拥有以前项目的URL,服务器用户名和密码.我没有找到任何使用这个东西的正确示例项目.任何人都可以建议我在HTTP请求中使用GET和POST方法的任何工作示例

s1m*_*nw1 27

对于Android,Volley是一个开始的好地方.

但是,您可以使用在Java中使用的标准库.例如HttpURLConnection:

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)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是你可以将简单的HTTP请求发送到服务器的方式.我建议使用Apache HttpComponents或者在复杂任务时使用的任何框架.

  • 确定它可以在Android之外使用.Kotlin最初从未成为Android的目标;-) (5认同)
  • 一些Apache组件在Java Android中被标记为已弃用,最好使用[Volley library](https://developer.android.com/training/volley/index.html)进行HTTP请求 (3认同)
  • lines() 需要 API>=24 (3认同)
  • 好吧,我没有看到android标签,这里的问题只提到了Kotlin (2认同)
  • 不要忘记将 `<uses-permission android:name="android.permission.INTERNET" />` 添加到 AndroidManifest.xml (2认同)

Dev*_*ven 10

使用发送带有参数的HTTP POST / GET请求HttpURLConnection

带参数的POST:

fun sendPostRequest(userName:String, password:String) {

    var reqParam = URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode(userName, "UTF-8")
    reqParam += "&" + URLEncoder.encode("password", "UTF-8") + "=" + URLEncoder.encode(password, "UTF-8")
    val mURL = URL("<Your API Link>")

    with(mURL.openConnection() as HttpURLConnection) {
        // optional default is GET
        requestMethod = "POST"

        val wr = OutputStreamWriter(getOutputStream());
        wr.write(reqParam);
        wr.flush();

        println("URL : $url")
        println("Response Code : $responseCode")

        BufferedReader(InputStreamReader(inputStream)).use {
            val response = StringBuffer()

            var inputLine = it.readLine()
            while (inputLine != null) {
                response.append(inputLine)
                inputLine = it.readLine()
            }
            it.close()
            println("Response : $response")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用参数获取:

fun sendGetRequest(userName:String, password:String) {

        var reqParam = URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode(userName, "UTF-8")
        reqParam += "&" + URLEncoder.encode("password", "UTF-8") + "=" + URLEncoder.encode(password, "UTF-8")

        val mURL = URL("<Yout API Link>?"+reqParam)

        with(mURL.openConnection() as HttpURLConnection) {
            // optional default is GET
            requestMethod = "GET"

            println("URL : $url")
            println("Response Code : $responseCode")

            BufferedReader(InputStreamReader(inputStream)).use {
                val response = StringBuffer()

                var inputLine = it.readLine()
                while (inputLine != null) {
                    response.append(inputLine)
                    inputLine = it.readLine()
                }
                it.close()
                println("Response : $response")
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • BufferedReader 实现了 AutoClosable,所以你不需要显式调用 `it.close`。 (2认同)

小智 9

查看Fuel库,一个示例GET 请求

"https://httpbin.org/get"
  .httpGet()
  .responseString { request, response, result ->
    when (result) {
      is Result.Failure -> {
        val ex = result.getException()
      }
      is Result.Success -> {
        val data = result.get()
      }
    }
  }

// You can also use Fuel.get("https://httpbin.org/get").responseString { ... }
// You can also use FuelManager.instance.get("...").responseString { ... }
Run Code Online (Sandbox Code Playgroud)

一个示例POST 请求

Fuel.post("https://httpbin.org/post")
    .jsonBody("{ \"foo\" : \"bar\" }")
    .also { println(it) }
    .response { result -> }
Run Code Online (Sandbox Code Playgroud)

他们的文档可以在这里找到 ?


fvi*_*oso 7

我认为使用 okhttp 是最简单的解决方案。在这里,您可以看到 POST 方法的示例,发送 json,并使用 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())
Run Code Online (Sandbox Code Playgroud)

请记住将此依赖项添加到您的项目https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp

更新:2019 年 7 月 7 日, 我将使用最新的 Kotlin (1.3.41)、OkHttp (4.0.0) 和 Jackson (2.9.9) 给出两个示例。

更新:2021 年 1 月 25 日 最新版本一切正常。

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.module/jackson-module-kotlin -->
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
            <version>2.12.1</version>
        </dependency>

<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.0</version>
        </dependency>
Run Code Online (Sandbox Code Playgroud)

获取方法

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

POST方法

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() + ".")
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*gin 6

如果您正在使用Kotlin,您最好保持代码尽可能简洁。该run方法将接收器转换为this并返回块的值。 this as HttpURLConnection创建一个聪明的演员。 bufferedReader().readText()避免了一堆样板代码。

return URL(url).run {
        openConnection().run {
            this as HttpURLConnection
            inputStream.bufferedReader().readText()
        }
}
Run Code Online (Sandbox Code Playgroud)

您也可以将其包装到扩展函数中。

fun URL.getText(): String {
    return openConnection().run {
                this as HttpURLConnection
                inputStream.bufferedReader().readText()
            }
}
Run Code Online (Sandbox Code Playgroud)

并这样称呼它

return URL(url).getText()
Run Code Online (Sandbox Code Playgroud)

最后,如果你超级懒惰,你可以扩展这个String类。

fun String.getUrlText(): String {
    return URL(this).run {
            openConnection().run {
                this as HttpURLConnection
                inputStream.bufferedReader().readText()
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

并这样称呼它

return "http://somewhere.com".getUrlText()
Run Code Online (Sandbox Code Playgroud)


0ll*_*lie 5

也许是最简单的GET

对于其他解决其他解决方案的人来说,使用NetworkOnMainThreadException:使用AsyncTask,或者更短的(但仍然是实验性的)Coroutines:

launch {

    val jsonStr = URL("url").readText()

}
Run Code Online (Sandbox Code Playgroud)

如果您需要使用普通的http测试,请不要忘记添加到您的清单: android:usesCleartextTraffic="true"


对于实验协同程序,您必须在10/10/2018之前添加到build.gradle:

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"
    ...
Run Code Online (Sandbox Code Playgroud)


xjc*_*jcl 5

只使用最少代码的标准库

thread {
    val json = try { URL(url).readText() } catch (e: Exception) { return@thread }
    runOnUiThread { displayOrWhatever(json) }
}
Run Code Online (Sandbox Code Playgroud)

这会在新线程上启动 GET 请求,让 UI 线程响应用户输入。但是,我们只能从主/UI 线程修改 UI 元素,因此我们实际上需要一个runOnUiThread块来向我们的用户显示结果。这会将我们的显示代码排入队列,以便很快在 UI 线程上运行。

try / catch语句是有,所以如果你与你的手机的互联网关的请求您的应用程序不会崩溃。根据需要添加您自己的错误处理(例如显示 Toast)。

.readText()不是java.net.URL类的一部分,而是 Kotlin扩展方法,Kotlin 将此方法“粘合”到URL. 这对于普通的 GET 请求来说已经足够了,但是对于更多的控制和 POST 请求,你需要像Fuel库这样的东西。

  • 嘿 Marco,我目前也在使用 _AsyncTask_,但它将在 Android 11 中被 **弃用**。而且我还没有尝试过其他方法,所以我还不太愿意解释它们,我稍后会编辑我的答案。 (2认同)
  • 我现在编辑了我的答案以使用“thread”而不是“AsyncTask”。 (2认同)