Android 使用 Kotlin - 如何使用 HttpUrlConnection
Android with Kotlin - How to use HttpUrlConnection
我正在尝试从 AsyncTask
中的 url 获取数据,但在创建 HttpUrlConnection
的新实例时出现错误。
Java
上有类似的内容
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
但我不断收到如下所示的错误。
class GetWeatherTask : AsyncTast<Void, Void, Void>() {
override fun doInBackground(vararg params: Void?): Void? {
val httpClient = HttpURLConnection();
return null
}
override fun onPreExecute() {
super.onPreExecute()
}
override fun onPostExecute(result: Void?) {
super.onPostExecute(result)
}
}
Cannot access '': it is 'protected/protected and package/' in 'HttpURLConnection' Cannot create an instance of an abstract class
我错过了什么吗?我尝试创建一个扩展 HttpUrlConnection
的 class 对象并尝试实现 init
方法但我不能
提前致谢。
这里是问题和答案的简化。
为什么会失败?
val connection = HttpURLConnection()
val data = connection.inputStream.bufferedReader().readText()
// ... do something with "data"
有错误:
Kotlin: Cannot access '': it is 'protected/protected and package/' in 'HttpURLConnection'
这会失败,因为您正在构建一个不打算直接构建的 class。它是由工厂创建的,工厂位于 URL
class openConnection()
方法中。这也不是原始问题中示例 Java 代码的直接端口。
在 Kotlin 中打开此连接并将内容作为字符串读取的最惯用的方法是:
val connection = URL("http://www.android.com/").openConnection() as HttpURLConnection
val data = connection.inputStream.bufferedReader().readText()
阅读完文本或出现异常时,此表单将自动关闭所有内容。如果您想进行自定义阅读:
val connection = URL("http://www.android.com/").openConnection() as HttpURLConnection
connection.inputStream.bufferedReader().use { reader ->
// ... do something with the reader
}
注意: use()
扩展功能将打开和关闭 reader并自动处理关闭错误。
关于disconnect()
方法
disconnect
的文档说:
Each HttpURLConnection instance is used to make a single request
but the underlying network connection to the HTTP server may be
transparently shared by other instances. Calling the close() methods
on the InputStream or OutputStream of an HttpURLConnection
after a request may free network resources associated with this
instance but has no effect on any shared persistent connection.
Calling the disconnect() method may close the underlying socket
if a persistent connection is otherwise idle at that time.
所以你决定是否要调用它。这是调用断开连接的代码版本:
val connection = URL("http://www.android.com/").openConnection() as HttpURLConnection
try {
val data = connection.inputStream.bufferedReader().use { it.readText() }
// ... do something with "data"
} finally {
connection.disconnect()
}
您可以修改您的代码;不要忘记用户可运行线程。
Thread(Runnable {
try {
val url = URL("www.android.com")
val con = url.openConnection() as HttpURLConnection
val datas = con.inputStream.bufferedReader().readText()
val json = JSONObject(datas)
val blockList = json.getJSONObject("blockList")
val warning = json.get("warnMessage").toString()
val keys = blockList.keys()
var permission = HashMap<String, Array<String?>>()
while (keys.hasNext()) {
val key = keys.next()
val kods = blockList.getJSONArray(key)
val permissonArray = arrayOfNulls<String>(kods.length())
for (i in permissonArray.indices) {
permissonArray[i] = kods.getString(i)
}
permission[key] = permissonArray;
}
} catch (ex: Exception) {
Log.d("Exception", ex.toString())
}
}).start()
使用 HTTPUrlConnection
执行 get
post
请求的最简单方法是创建一个通用助手 class,可以从应用程序中的任何位置调用它来调用GET 和 POST 请求方法,无需一次又一次地编写相同的代码。
下面是帮助程序 object
(单例)class,您可以将其用于 GET 和 POST 请求的网络调用。
package com.dewari.ajay.androidnetworkcommunication.network
import org.json.JSONObject
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStream
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
import javax.net.ssl.HttpsURLConnection
object RequestHandler {
const val GET : String = "GET"
const val POST : String = "POST"
@Throws(IOException::class)
fun requestPOST(r_url: String?, postDataParams: JSONObject): String? {
val url = URL(r_url)
val conn: HttpURLConnection = url.openConnection() as HttpURLConnection
conn.readTimeout = 3000
conn.connectTimeout = 3000
conn.requestMethod = POST
conn.doInput = true
conn.doOutput = true
val os: OutputStream = conn.outputStream
val writer = BufferedWriter(OutputStreamWriter(os, "UTF-8"))
writer.write(encodeParams(postDataParams))
writer.flush()
writer.close()
os.close()
val responseCode: Int = conn.responseCode // To Check for 200
if (responseCode == HttpsURLConnection.HTTP_OK) {
val `in` = BufferedReader(InputStreamReader(conn.inputStream))
val sb = StringBuffer("")
var line: String? = ""
while (`in`.readLine().also { line = it } != null) {
sb.append(line)
break
}
`in`.close()
return sb.toString()
}
return null
}
@Throws(IOException::class)
fun requestGET(url: String?): String? {
val obj = URL(url)
val con = obj.openConnection() as HttpURLConnection
con.requestMethod = GET
val responseCode = con.responseCode
println("Response Code :: $responseCode")
return if (responseCode == HttpURLConnection.HTTP_OK) { // connection ok
val `in` =
BufferedReader(InputStreamReader(con.inputStream))
var inputLine: String?
val response = StringBuffer()
while (`in`.readLine().also { inputLine = it } != null) {
response.append(inputLine)
}
`in`.close()
response.toString()
} else {
""
}
}
@Throws(IOException::class)
private fun encodeParams(params: JSONObject): String? {
val result = StringBuilder()
var first = true
val itr = params.keys()
while (itr.hasNext()) {
val key = itr.next()
val value = params[key]
if (first) first = false else result.append("&")
result.append(URLEncoder.encode(key, "UTF-8"))
result.append("=")
result.append(URLEncoder.encode(value.toString(), "UTF-8"))
}
return result.toString()
}
}
使用上述对象 class 您可以执行 GET 和 POST 请求,如下所示:
//As this is network call it should be done in a separate thread
Thread(Runnable {
RequestHandler.requestGET(url)
RequestHandler.requestPOST(url, postJSONObject)
}).start()
除了使用线程,您还可以使用 AsyncTask,如下所示:
class NetworkAsyncCall(private val context: Context, private val url: String, private val requestType:
String, private val postJSONObject: JSONObject = JSONObject()
) : AsyncTask<String?, String?, String?>() {
override fun doInBackground(vararg p0: String?): String? {
return when (requestType) {
RequestHandler.GET -> RequestHandler.requestGET(url)
RequestHandler.GET -> RequestHandler.requestPOST(url, postJSONObject)
else -> ""
}
}
override fun onPostExecute(s: String?) {
if (s != null) {
Toast.makeText(context, s, Toast.LENGTH_LONG).show()
}
}
}
您可以将 asyncTask 创建为 Activity 的内部 class 或单独的独立 class.
现在要通过你的 onCreate()
中的 AsyncTask NetworkAsyncCall
调用 newtwork 调用,或者你想调用 api 的任何函数,你可以这样写:
注意:上面提到的url是行不通的,你得换成你自己的。
override fun onCreate(savedInstanceState: Bundle?) {
setContentView(R.layout.activity_main)
// Change the url with your own GET URL request
val urlGET = "http://my-json-feed"
//GET Request
NetworkAsyncCall(this@MainActivity, urlGET, RequestHandler.GET).execute();
// POST Request
// doPost()
}
对于POST请求您可以拨打:
private fun doPost() {
// Change the url with your own POST URL request
val urlPOST = "http://my-json-feed"
val postDataParams = JSONObject()
postDataParams.put("name", "Ajay")
postDataParams.put("email", "aj****ri@gmail.com")
postDataParams.put("phone", "+91 78******25")
NetworkAsyncCall(this@MainActivity, urlPOST, RequestHandler.POST, postDataParams).execute()
}
您可以在github here中查看完整代码。
为了更好的解释,你可以查看这个 link.
将 NetworkAsyncCall 用作独立的 class 的优点是您不必再次编写 AsyncTask 代码,只需使用来自不同 [=] 的新对象调用相同的 AsyncTask NetworkAsyncCall
47=],但是有了这个,你必须实现一个监听器接口,你需要在从 api 获得响应后在 onPostExecute()
上进行回调,并将响应返回给 return activity 您必须使用该接口执行回调。
我正在尝试从 AsyncTask
中的 url 获取数据,但在创建 HttpUrlConnection
的新实例时出现错误。
Java
上有类似的内容URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
但我不断收到如下所示的错误。
class GetWeatherTask : AsyncTast<Void, Void, Void>() {
override fun doInBackground(vararg params: Void?): Void? {
val httpClient = HttpURLConnection();
return null
}
override fun onPreExecute() {
super.onPreExecute()
}
override fun onPostExecute(result: Void?) {
super.onPostExecute(result)
}
}
Cannot access '': it is 'protected/protected and package/' in 'HttpURLConnection' Cannot create an instance of an abstract class
我错过了什么吗?我尝试创建一个扩展 HttpUrlConnection
的 class 对象并尝试实现 init
方法但我不能
提前致谢。
这里是问题和答案的简化。
为什么会失败?
val connection = HttpURLConnection()
val data = connection.inputStream.bufferedReader().readText()
// ... do something with "data"
有错误:
Kotlin: Cannot access '': it is 'protected/protected and package/' in 'HttpURLConnection'
这会失败,因为您正在构建一个不打算直接构建的 class。它是由工厂创建的,工厂位于 URL
class openConnection()
方法中。这也不是原始问题中示例 Java 代码的直接端口。
在 Kotlin 中打开此连接并将内容作为字符串读取的最惯用的方法是:
val connection = URL("http://www.android.com/").openConnection() as HttpURLConnection
val data = connection.inputStream.bufferedReader().readText()
阅读完文本或出现异常时,此表单将自动关闭所有内容。如果您想进行自定义阅读:
val connection = URL("http://www.android.com/").openConnection() as HttpURLConnection
connection.inputStream.bufferedReader().use { reader ->
// ... do something with the reader
}
注意: use()
扩展功能将打开和关闭 reader并自动处理关闭错误。
关于disconnect()
方法
disconnect
的文档说:
Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances. Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.
所以你决定是否要调用它。这是调用断开连接的代码版本:
val connection = URL("http://www.android.com/").openConnection() as HttpURLConnection
try {
val data = connection.inputStream.bufferedReader().use { it.readText() }
// ... do something with "data"
} finally {
connection.disconnect()
}
您可以修改您的代码;不要忘记用户可运行线程。
Thread(Runnable {
try {
val url = URL("www.android.com")
val con = url.openConnection() as HttpURLConnection
val datas = con.inputStream.bufferedReader().readText()
val json = JSONObject(datas)
val blockList = json.getJSONObject("blockList")
val warning = json.get("warnMessage").toString()
val keys = blockList.keys()
var permission = HashMap<String, Array<String?>>()
while (keys.hasNext()) {
val key = keys.next()
val kods = blockList.getJSONArray(key)
val permissonArray = arrayOfNulls<String>(kods.length())
for (i in permissonArray.indices) {
permissonArray[i] = kods.getString(i)
}
permission[key] = permissonArray;
}
} catch (ex: Exception) {
Log.d("Exception", ex.toString())
}
}).start()
使用 HTTPUrlConnection
执行 get
post
请求的最简单方法是创建一个通用助手 class,可以从应用程序中的任何位置调用它来调用GET 和 POST 请求方法,无需一次又一次地编写相同的代码。
下面是帮助程序 object
(单例)class,您可以将其用于 GET 和 POST 请求的网络调用。
package com.dewari.ajay.androidnetworkcommunication.network
import org.json.JSONObject
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.IOException
import java.io.InputStreamReader
import java.io.OutputStream
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
import javax.net.ssl.HttpsURLConnection
object RequestHandler {
const val GET : String = "GET"
const val POST : String = "POST"
@Throws(IOException::class)
fun requestPOST(r_url: String?, postDataParams: JSONObject): String? {
val url = URL(r_url)
val conn: HttpURLConnection = url.openConnection() as HttpURLConnection
conn.readTimeout = 3000
conn.connectTimeout = 3000
conn.requestMethod = POST
conn.doInput = true
conn.doOutput = true
val os: OutputStream = conn.outputStream
val writer = BufferedWriter(OutputStreamWriter(os, "UTF-8"))
writer.write(encodeParams(postDataParams))
writer.flush()
writer.close()
os.close()
val responseCode: Int = conn.responseCode // To Check for 200
if (responseCode == HttpsURLConnection.HTTP_OK) {
val `in` = BufferedReader(InputStreamReader(conn.inputStream))
val sb = StringBuffer("")
var line: String? = ""
while (`in`.readLine().also { line = it } != null) {
sb.append(line)
break
}
`in`.close()
return sb.toString()
}
return null
}
@Throws(IOException::class)
fun requestGET(url: String?): String? {
val obj = URL(url)
val con = obj.openConnection() as HttpURLConnection
con.requestMethod = GET
val responseCode = con.responseCode
println("Response Code :: $responseCode")
return if (responseCode == HttpURLConnection.HTTP_OK) { // connection ok
val `in` =
BufferedReader(InputStreamReader(con.inputStream))
var inputLine: String?
val response = StringBuffer()
while (`in`.readLine().also { inputLine = it } != null) {
response.append(inputLine)
}
`in`.close()
response.toString()
} else {
""
}
}
@Throws(IOException::class)
private fun encodeParams(params: JSONObject): String? {
val result = StringBuilder()
var first = true
val itr = params.keys()
while (itr.hasNext()) {
val key = itr.next()
val value = params[key]
if (first) first = false else result.append("&")
result.append(URLEncoder.encode(key, "UTF-8"))
result.append("=")
result.append(URLEncoder.encode(value.toString(), "UTF-8"))
}
return result.toString()
}
}
使用上述对象 class 您可以执行 GET 和 POST 请求,如下所示:
//As this is network call it should be done in a separate thread
Thread(Runnable {
RequestHandler.requestGET(url)
RequestHandler.requestPOST(url, postJSONObject)
}).start()
除了使用线程,您还可以使用 AsyncTask,如下所示:
class NetworkAsyncCall(private val context: Context, private val url: String, private val requestType:
String, private val postJSONObject: JSONObject = JSONObject()
) : AsyncTask<String?, String?, String?>() {
override fun doInBackground(vararg p0: String?): String? {
return when (requestType) {
RequestHandler.GET -> RequestHandler.requestGET(url)
RequestHandler.GET -> RequestHandler.requestPOST(url, postJSONObject)
else -> ""
}
}
override fun onPostExecute(s: String?) {
if (s != null) {
Toast.makeText(context, s, Toast.LENGTH_LONG).show()
}
}
}
您可以将 asyncTask 创建为 Activity 的内部 class 或单独的独立 class.
现在要通过你的 onCreate()
中的 AsyncTask NetworkAsyncCall
调用 newtwork 调用,或者你想调用 api 的任何函数,你可以这样写:
注意:上面提到的url是行不通的,你得换成你自己的。
override fun onCreate(savedInstanceState: Bundle?) {
setContentView(R.layout.activity_main)
// Change the url with your own GET URL request
val urlGET = "http://my-json-feed"
//GET Request
NetworkAsyncCall(this@MainActivity, urlGET, RequestHandler.GET).execute();
// POST Request
// doPost()
}
对于POST请求您可以拨打:
private fun doPost() {
// Change the url with your own POST URL request
val urlPOST = "http://my-json-feed"
val postDataParams = JSONObject()
postDataParams.put("name", "Ajay")
postDataParams.put("email", "aj****ri@gmail.com")
postDataParams.put("phone", "+91 78******25")
NetworkAsyncCall(this@MainActivity, urlPOST, RequestHandler.POST, postDataParams).execute()
}
您可以在github here中查看完整代码。 为了更好的解释,你可以查看这个 link.
将 NetworkAsyncCall 用作独立的 class 的优点是您不必再次编写 AsyncTask 代码,只需使用来自不同 [=] 的新对象调用相同的 AsyncTask NetworkAsyncCall
47=],但是有了这个,你必须实现一个监听器接口,你需要在从 api 获得响应后在 onPostExecute()
上进行回调,并将响应返回给 return activity 您必须使用该接口执行回调。