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 get
post
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.