Saltar al contenido

Android con Kotlin: cómo usar HttpUrlConnection

Pudiera darse el caso de que encuentres alguna incompatibilidad en tu código o trabajo, recuerda probar siempre en un entorno de testing antes añadir el código al proyecto final.

Aquí hay una simplificación de la pregunta y la respuesta.

¿Por qué falla esto?

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

con error:

Kotlin: No se puede acceder a ”: está ‘protegido /protegido y empaquetado/ ‘en’ HttpURLConnection ‘

Esto falla porque está construyendo una clase que no está destinada a construirse directamente. Está destinado a ser creado por una fábrica, que se encuentra en el URL clase openConnection() método. Este tampoco es un puerto directo del código Java de muestra en la pregunta original.

La forma más idiomática en Kotlin de abrir esta conexión y leer el contenido como un string sería:

val connection = URL("http://www.android.com/").openConnection() as HttpURLConnection
val data = connection.inputStream.bufferedReader().readText()

Este formulario cerrará automáticamente todo cuando termine de leer el texto o en una excepción. Si desea realizar una lectura personalizada:

val connection = URL("http://www.android.com/").openConnection() as HttpURLConnection
connection.inputStream.bufferedReader().use  reader ->
    // ... do something with the reader

NOTA:los use() La función de extensión abrirá y cerrará el lector y manejará el cierre en caso de errores automáticamente.

Acerca de disconnect() método

Los documentos para disconnect decir:

Cada instancia de HttpURLConnection se utiliza para realizar una sola solicitud, pero la conexión de red subyacente al servidor HTTP puede ser compartida de forma transparente por otras instancias. Llamar a los métodos close () en InputStream o OutputStream de una HttpURLConnection después de una solicitud puede liberar recursos de red asociados con esta instancia, pero no tiene ningún efecto en ninguna conexión persistente compartida. Llamar al método desconectar () puede cerrar el socket subyacente si una conexión persistente está inactiva en ese momento.

Así que decides si quieres llamarlo o no. Aquí hay una versión del código que llama a desconectar:

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

La forma más sencilla de hacer un getpost solicitud usando HTTPUrlConnection es crear una clase auxiliar común a la que se pueda llamar desde cualquier lugar de la aplicación para llamar a los métodos de solicitud GET y POST, sin escribir el mismo código una y otra vez.

A continuación se muestra el ayudante object (Singleton) clase que puede usar para la llamada de red para solicitudes GET y 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()
  

Usando la clase de objeto anterior, puede realizar sus solicitudes GET y POST como se muestra a continuación:

//As this is network call it should be done in a separate thread
                Thread(Runnable 
                RequestHandler.requestGET(url)
                RequestHandler.requestPOST(url, postJSONObject)
            ).start()

En lugar de usar hilo, también puede usar AsyncTask de la siguiente manera:

    class NetworkAsyncCall(private val context: Context, private val url: String, private val requestType:
String, private val postJSONObject: JSONObject = JSONObject()
) : AsyncTask() 

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

Puede crear asyncTask como una clase interna de Actividad o una clase independiente separada.

Ahora para llamar a la llamada de newtwork a través de AsyncTask NetworkAsyncCall en tus onCreate() o cualquier función desde la que desee llamar a la api puede escribir:

NOTA: La URL mencionada no funcionará, así que debes reemplazarla por la tuya.

    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([email protected], urlGET, RequestHandler.GET).execute();

   //       POST Request
   //        doPost()

Para solicitud POST puede llamar a:

    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****[email protected]")
    postDataParams.put("phone", "+91 78******25")
    NetworkAsyncCall([email protected], urlPOST, RequestHandler.POST, postDataParams).execute()

puedes consultar el código completo en github aquí. Para una buena explicación, puede consultar este enlace.

la ventaja de usar NetworkAsyncCall como clase independiente separada es que no tiene que escribir el código AsyncTask nuevamente, simplemente llame al mismo AsyncTask NetworkAsyncCall con un nuevo objeto de diferentes actividades / funciones, sin embargo, con esto debe implementar una interfaz de escucha que necesitará para la devolución de llamada en onPostExecute() después de obtener la respuesta de la API y para devolver la respuesta a la actividad, debe realizar la devolución de llamada utilizando esa interfaz.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags :

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *