我是Kotlin的新手。我想使用POST方法进行登录验证,并使用GET方法获取一些信息。我已经有上一个项目的URL,服务器用户名和密码。我没有找到任何适当的示例项目使用此东西。任何人都可以向我建议任何可以在HTTP请求中使用GET和POST方法的工作示例
Answers:
对于Android,Volley是入门的好地方。对于所有平台,您可能还希望检出ktor客户端或http4k都是不错的库。
但是,您也可以使用标准Java库,例如java.net.HttpURLConnection
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)
}
}
}
}
或更简单:
URL("https://google.com").readText()
<uses-permission android:name="android.permission.INTERNET" />
到AndroidManifest.xml
使用发送带有参数的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()
}
println("Response : $response")
}
}
}
使用参数获取:
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")
}
}
}
url
和inputStream
var在哪里定义?该代码不完整。
it.close
。
对于其他对NetworkOnMainThreadException棘手的人来说,请使用AsyncTask或更短的(但仍处于实验阶段)协程:
launch {
val jsonStr = URL("url").readText()
}
如果您需要使用简单的http测试,请不要忘记添加到清单中:
android:usesCleartextTraffic="true"
从2018年10月10日起,您必须为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"
...
readText
-readText
与协程而不是线程一起使用可以吗?
如果使用Kotlin
,则最好使代码尽可能简洁。该run
方法将接收器变成this
并返回该块的值。
this as HttpURLConnection
创建一个聪明的演员表。 bufferedReader().readText()
避免一堆样板代码。
return URL(url).run {
openConnection().run {
this as HttpURLConnection
inputStream.bufferedReader().readText()
}
}
您也可以将其包装到扩展功能中。
fun URL.getText(): String {
return openConnection().run {
this as HttpURLConnection
inputStream.bufferedReader().readText()
}
}
并这样称呼它
return URL(url).getText()
最后,如果您超级懒惰,则可以扩展String
该类。
fun String.getUrlText(): String {
return URL(this).run {
openConnection().run {
this as HttpURLConnection
inputStream.bufferedReader().readText()
}
}
}
并这样称呼它
return "http://somewhere.com".getUrlText()
InputStream
,例如inputStream.bufferedReader().use {readText()}
看一下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 { ... }
样本POST请求
Fuel.post("https://httpbin.org/post")
.jsonBody("{ \"foo\" : \"bar\" }")
.also { println(it) }
.response { result -> }
他们的文档,可以发现这里
我认为使用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())
请记住将此依赖项添加到您的项目中https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
更新:2019年7月7日, 我将使用最新的Kotlin(1.3.41),OkHttp(4.0.0)和Jackson(2.9.9)给出两个示例。
获取方法
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")
}
}
开机自检方法
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() + ".")
}
您可以使用kohttp库。这是Kotlin DSL HTTP客户端。它支持square.okhttp的功能,并为其提供清晰的DSL。KoHttp异步调用由协程驱动。
httpGet
扩展功能
val response: Response = "https://google.com/search?q=iphone".httpGet()
您还可以对协程使用异步调用
val response: Deferred<Response> = "https://google.com/search?q=iphone".asyncHttpGet()
或DSL功能处理更复杂的请求
val response: Response = httpGet {
host = "google.com"
path = "/search"
param {
"q" to "iphone"
"safe" to "off"
}
}
您可以在文档中找到更多详细信息
要使用gradle来获得它
implementation 'io.github.rybalkinsd:kohttp:0.12.0'
fun httpGet(client: Call.Factory = defaultHttpClient, init: HttpGetContext.() -> Unit): Response
因此可以将call factory与特定于您的项目需求和性能问题的配置一起使用。
仅使用最少的代码使用标准库!
thread {
val jsonStr = try { URL(url).readText() } catch (ex: Exception) { return@thread }
runOnUiThread { displayOrWhatever(jsonStr) }
}
这将在新线程上启动GET请求,而UI线程将响应用户输入。但是,我们只能从main / UI线程修改UI元素,因此实际上我们需要一个runOnUiThread
块来向用户显示结果。这使我们的显示代码排队不久就可以在UI线程上运行。
该try / catch语句是有,所以如果你与你的手机的互联网关的请求您的应用程序不会崩溃。您可以根据需要添加自己的错误处理(例如显示Toast)。
.readText()
不是java.net.URL
类的一部分,而是Kotlin扩展方法,Kotlin将此方法“粘合”到上URL
。这对于普通的GET请求就足够了,但是对于更多的控制和POST请求,您需要类似Fuel
库的内容。
import java.io.IOException
import java.net.URL
fun main(vararg args: String) {
val response = try {
URL("http://seznam.cz")
.openStream()
.bufferedReader()
.use { it.readText() }
} catch (e: IOException) {
"Error with ${e.message}."
}
println(response)
}
在不添加其他依赖项的情况下,此方法可行。 您不需要排球。可以使用截至2018年12月的当前Kotlin版本:Kotlin 1.3.10
如果使用Android Studio,则需要在AndroidManifest.xml中添加以下声明:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
您应该在此处手动声明导入。自动导入工具引起了我很多冲突。
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
您不能在后台线程上执行网络请求。您必须继承AsyncTask
。
调用方法:
NetworkTask().execute(requestURL, queryString)
宣言:
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?) {
}
}
使用OkHttp进行GET和POST
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
}
}
对象序列化和反序列化
@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)
}
}
依存关系
将以下行放入gradle(app)文件中。杰克逊是可选的。您可以将其用于对象序列化和反序列化。
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'