Android与Kotlin - 如何使用HttpUrlConnection

时间:2015-04-22 15:33:00

标签: android httpurlconnection kotlin

我正在尝试从m[0].disable_tx(); 内的网址获取数据,但在创建AsyncTask的新实例时出现错误。

Java上的这样的东西

HttpUrlConnection

但我一直收到如下所示的错误。

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();
}
  

无法访问'':'受保护/ 受保护,并且包' /'在'HttpURLConnection'中无法创建抽象类的实例

我错过了什么吗?我试图创建一个扩展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) } } 的类对象并尝试实现HttpUrlConnection方法,但我不能

提前致谢。

3 个答案:

答案 0 :(得分:10)

以下是问题和答案的简化。

为什么这会失败?

val connection = HttpURLConnection()
val data = connection.inputStream.bufferedReader().readText()
// ... do something with "data"

有错误:

  

Kotlin:无法访问'':'HttpURLConnection'中的'受保护/ 受保护并打包 /'

这会失败,因为您正在构建一个不打算直接构造的类。它意味着由工厂创建,该工厂采用URLopenConnection()方法。这也不是原始问题中示例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()扩展功能会打开并关闭阅读器并自动处理错误。

关于disconnect()方法

disconnect的文档说:

  

每个HttpURLConnection实例用于发出单个请求   但是与HTTP服务器的底层网络连接可能是   由其他实例透明共享。调用close()方法   在HttpURLConnection的InputStream或OutputStream上   请求后可以释放与此相关的网络资源   实例但对任何共享持久连接没有影响。   调用disconnect()方法可能会关闭底层套接字   如果此时持久连接处于空闲状态。

所以你决定是否要打电话。以下是调用disconnect的代码版本:

val connection = URL("http://www.android.com/").openConnection() as HttpURLConnection
try {
    val data = connection.inputStream.bufferedReader().readText()
    // ... do something with "data"
} finally {
    connection.disconnect()
}

答案 1 :(得分:2)

使用get进行post HTTPUrlConnection请求的最简单方法是创建一个通用的帮助程序类,该类可以从应用程序中的任何位置调用以调用GET和POST请求方法,而不必一次又一次地编写相同的代码。

下面是辅助类object(单例),您可以将其用于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()
  }
}

使用上述对象类,您可以执行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的内部类或单独的独立类。

现在可以通过NetworkAsyncCall中的AsyncTask onCreate()或要从中调用api的任何函数来调用newtwork调用:

注意::所提到的网址将不起作用,因此您必须用自己的网址替换。

    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作为独立的单独类的优点是,您不必再次编写AsyncTask代码,只需使用来自不同活动/功能的新对象调用同一AsyncTask NetworkAsyncCall,从api获得响应后,必须实现一个onPostExecute()上的回调将需要的侦听器接口,并将响应返回给必须使用该接口执行回调的活动。

答案 2 :(得分:0)

您可以适应您的代码;不要忘记用户可运行线程。

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()