我想使用POST方法进行登录验证,并使用GET方法获取一些信息。
我已经拥有了我的上一个项目的URL、服务器用户名和密码。
对于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" />
权限。 - Josh Correia使用 HttpURLConnection
发送带参数的 HTTP POST/GET 请求:
带参数的 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")
}
}
}
带参数的GET请求:
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
变量在哪里定义?此代码不完整。 - jungledevit.close
。 - kwmt只使用标准库和最少的代码!
thread {
val json = try { URL(url).readText() } catch (e: Exception) { return@thread }
runOnUiThread { displayOrWhatever(json) }
}
这会在一个新线程上开始GET请求,让UI线程来响应用户输入。然而,我们只能从主/UI线程修改UI元素,因此我们实际上需要一个runOnUiThread
块来向用户显示结果。这样可以将我们的显示代码排队在UI线程上很快运行。
try/catch存在是为了防止您在手机没有联网时进行请求导致应用程序崩溃。您可以根据需要添加自己的错误处理(例如,显示Toast)。
.readText()
不是java.net.URL
类的一部分,而是Kotlin 扩展方法,Kotlin“粘合”了这个方法到URL
上。这对于简单的GET请求已经足够了,但是对于更多的控制和POST请求,您需要像Fuel
库这样的东西。
thread
而不是 AsyncTask
。 - xjcl"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 { ... }
Fuel.post("https://httpbin.org/post")
.jsonBody("{ \"foo\" : \"bar\" }")
.also { println(it) }
.response { result -> }
他们的文档可以在这里找到。
对于那些被其他解决方案困扰着NetworkOnMainThreadException的人来说:可以使用AsyncTask,甚至更短的(但仍处于实验阶段)协程:
launch {
val jsonStr = URL("url").readText()
}
如果您需要使用普通的http进行测试,请不要忘记在manifest中添加以下内容:android:usesCleartextTraffic="true"
对于实验性的协程,您需要在build.gradle中添加以下内容,截至2018年10月10日: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
而不是线程可以吗? - xjcl我认为使用OkHttp是最简单的解决方案。这里您可以看到一个使用POST方法发送JSON和带有授权的示例。
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)分别给出两个示例。
更新时间: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>
获取方法
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方法
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() + ".")
}
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()}
。 - Abhijit SarkarhttpGet
扩展函数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"
}
}
implementation 'io.github.rybalkinsd:kohttp:0.12.0'
fun httpGet(client: Call.Factory = defaultHttpClient, init: HttpGetContext.() -> Unit): Response
,因此它可以使用与您的项目需求和性能问题特定配置的调用工厂。 - Sergei Rybalkin不需要添加额外的依赖,这个方法可行。 你不需要使用 Volley。这个方法是在Kotlin 1.3.10版本下测试通过的,时间为2018年12月。
如果要在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) 文件中。Jackson 是可选的,您可以将其用于对象序列化和反序列化。
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'