Operaciones HTTP en Android con el cliente HttpURLConnection

Enviar y Recibir datos a un servidor desde una Aplicación Android
Este artículo explicará de qué forma se puede enviar y recibir datos hacia un servidor desde una aplicación Android, con el propósito de introducir a los desarrolladores a la creación de servicios en la nube desde fuentes de datos externas. En primera instancia se expondrán conocimientos introductorios sobre el protocolo HTTP, el cual habilita el intercambio de información. Luego verás a través de un ejemplo práctico como leer y postear comentarios en un servidor externo. Y Adicionalmente se integrarán las tareas asíncronas para asegurar el correcto funcionamiento del hilo principal.

Finalmente se concluye con aspectos adicionales del mecanismo usado para la conexión y observaciones que pueden ayudarte en la conexión de las aplicaciones Android.

CONTENIDO

Introducción al funcionamiento del protocolo HTTP

Ejemplo: Aplicación Monstalkers para lectura y posteo de Comentarios

Usar el cliente HttpURLConnection
Comprobar si la conexión a la red es posible

Abrir la conexión hacia el servidor

Obtener datos con el método GET

Postear información con el método POST

Subir un archivo hacia un servidor con el método POST

Establecer peticiones HTTP en segundo plano usando AsyncTask

Otros métodos para peticiones HTTP en Android

Conclusiones y Recomendaciones

Introducción al funcionamiento del protocolo HTTP

Las conexiones que haremos desde nuestras aplicaciones Android hacia los servidores web siguen un estándar internacional llamado Hipertext Transfer Protocol HTTP. Este protocolo consiste en reglas sencillas de transferencia de recursos o archivos entre equipos interconectados a una red.

Al equipo que hace la petición para enviar u obtener datos se le llama Cliente y al que contiene el recurso o el espacio para almacenar es llamado Servidor. La comunicación se establece a través de una petición de envío, la cual contiene los datos del cliente, como el sistema operativo que usa, el navegador web desde donde se hace la petición, la ubicación del archivo solicitado (URL), etc.

Diagrama de una petición y respuesta en el protocolo HTTP
Una petición puede tener múltiples objetivos dependiendo del método que se elija. Los tipos de peticiones más comunes son el Retorno de datos y la Publicación de datos. Técnicamente se les conoce como los métodos GET y POST.

La búsqueda de una página web a través de la URL es un buen ejemplo de una petición GET, donde el cliente especifica la URL y el servidor retorna en la información HTML necesaria para que el navegador realice su respectivo parsing.

El ejemplo más popular del método POST se refleja en el envío de información desde un formulario hacia la base de datos del servidor. Aquí hacemos lo contrario, dictaminamos los datos y el servidor los recibe para almacenarlos y darles persistencia.

Cada vez que entras a hermosa programación desde tu navegador la comunicación HTTP sería similar a esta:

GET /index.html
Host: www.hermosaprogramación.com
User Agent: Mozilla/4.0 (Compatible; MSIE 7.0; Windows NT 6.0)
Accept: *

Dicha petición es recibida por el Servidor, quién arroja la respuesta dependiendo del estado del recurso solicitado, que en este caso es el archivo HTML que representa el Home de Hermosa Programación.

HTTP/1.0 200 OK
Date: Fri, 27 Dec 2014 23:59:59 GMT
Content-Type: text/html
Content-Length: 1467
<html>
<body>
<h1>Hermosa Programación</h1>
(El contenido restante)
.
.
.
</body>
</html>

Como se nota, el estado de respuesta es 200 OK, un código que significa que todo marcha sobre ruedas con este recurso. En seguida se ubican metadatos asociados a la fecha de consulta, el tipo de contenido enviado, su tamaño y al final el contenido HTML. Con esta información, tu navegador web ya puede implementar la lógica necesaria para mostrar la página web.

Ahora veamos el esquema de una petición POST, cuyo objetivo es enviar los datos Nombre y Precio hacia la base de datos del servidor:

POST /data/Insertar-Productos.php HTTP/1.0
From: frog@jmarshall.com
User-Agent: HTTPTool/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
Nombre=Motorola&Precio=2000

En este caso se indica la ruta de ubicación donde se publicaran los resultados, una cuenta de correo como el origen de la petición, el tipo de contenido estándar para los formularios, el tamaño de los datos y finalmente dos pares clave-valor encriptados con UTF-8.

Si deseas que tus aplicaciones tengan acceso total a la conexión de tu dispositivo Android es necesario que incluyas los siguientes permisos en tu archivo AndroidManifiest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Ejemplo: Aplicación Monstalkers para lectura y posteo de Comentarios

Monstalkers es una aplicación de ejemplo creada para mostrar el uso del cliente HttpURLConnection. Su objetivo es mostrar como cargar comentarios almacenados en un servidor externos a través del parsing de un arreglo JSON. Adicionalmente permitirá al usuario crear y enviar su propio comentario al servidor. Puedes descargar el código aquí:

Descargar CódigoEn cuanto a diseño, Monstalkers se compone de dos actividades. La primera es la actividad principal llamada MainActivity, donde se muestra un ListView que despliega todos los comentarios por orden cronólogico.Su Action Bar tiene dos botones de acción, los cuales permiten añadir un nuevo comentario y refrescar la vista respectivamente.

Aplicación Android para Añadir Comentarios a un Servidor
Cuando se presiona el action button para añadir, inmediatamente se despliega la actividad FormActivity, la cual contiene un sencillo campo de edición para digitar el comentario. El usuario decidirá el fin del comentario presionando el botón Enviar o Cancelar.

Actividad Android con un Formulario para añadir Comentarios
Usar el cliente HttpURLConnection

La clase HttpUrlConnection del paquete java.net.* permite a nuestros dispositivos android asumir las características de un cliente HTTP ligero. Su funcionamiento está condicionado a las versiones superiores a Gingerbread. Para versiones anteriores debes usar el cliente HttpClient de Apache. Con esta clase podremos recibir y enviar información a través de la web, lo que potenciará nuestras aplicaciones Android. A continuación se muestran los pasos que se deben realizar para establecer una conexión existosa.

Comprobar si la conexión a la red es posible

Antes de iniciar el cliente Http debes comprobar si la conexión del dispositivo está habilitada, ya que puede ser posible que el Wi-fi no esté disponible o simplemente la conexión de red está fuera del rango. Para comprobar el estado de conexión usaremos los métodos getActiveNetworkInfo() e isConnected():

ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
// Operaciones http
} else {
// Mostrar errores
}

Se ha usado la clase ConnectivityManager para obtener las características actuales de la conexión. Esta información la guardamos en un elemento del tipo NetworkInfo con el método getActiveNetworkInfo(). Luego comprobamos si se retornó algún dato y si además el dispositivo está conectado con isConnected().

Abrir la conexión hacia el servidor

El primer paso para iniciar la comunicación es abrir la conexión hacia el recurso alojado en el servidor. Para ello se usa el método openConnection() de la clase URL. El resultado que se obtenga debe ser casteado a HttpUrlConnection para que el cliente sea instanciado:

URL url = new URL("http://monstalkers.hostoi.com/data/get_all_comments.php");   
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

Obtener datos con el método GET

Si deseas descargar datos desde la URL especificada simplemente usas el método getIntpuStream() para obtener el flujo de datos asociado al recurso que se encuentra en esa dirección:

URL url = new URL("http://monstalkers.hostoi.com/data/get_all_comments.php");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
// Acciones a realizar con el flujo de datos
finally {
urlConnection.disconnect();
}

Es importante que al finalizar tus operaciones de conexión liberes la memoria asociada a la instancia de la conexión realizada. Para ello usa el método disconnect(), el cual pone a disposición de nuevo una futura reconexión.

Recuerda que un tipo InputStream debe ser decodificado para interpretar su contenido, ya sea texto plano, imagen, JSON, audio, etc. Dependiendo del objetivo así mismo debes usar los métodos y técnicas correspondientes.

Postear información con el método POST

Si deseas publicar información en un servidor debes abrir la conexión al igual que con GET. Luego se indica a la conexión que se permite el envío de datos hacia el servidor con el método setDoOutput().

Seguidamente se declaran los datos que se enviarán al destino, para los cuales debes declarar el tamaño que ocuparán para ser transmitidos por el flujo. Si su tamaño es fijo, entonces usa el método setFixedLengthStreamingMode(), quién recibe como parámetro la cantidad de bytes. Si el tamaño es incierto (normalmente esta situación se da en transmisiones Streaming), entonces usa setChunkedStreamingMode().

Reuniendo todas estas características, Monstalkers hace su publicación de comentarios de la siguiente forma:

// Obtener la conexión
HttpURLConnection con = null;
try {
// Construir los datos a enviar
String data = "body=" + URLEncoder.encode(comment,"UTF-8");
con = (HttpURLConnection)url.openConnection();
// Activar método POST
con.setDoOutput(true);
// Tamaño previamente conocido
con.setFixedLengthStreamingMode(data.getBytes().length);
// Establecer application/x-www-form-urlencoded debido a la simplicidad de los datos
con.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
OutputStream out = new BufferedOutputStream(con.getOutputStream());
out.write(data.getBytes());
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(con!=null)
con.disconnect();
}

El código anterior muestra como se envía el cuerpo de un comentario digitado por el usuario en la actividad ActivityForm. En primera instancia se construye una cadena llamada data, donde guardaremos el par clave-valor del comentario con el estándar de formularios "clave= valor". Para ello usamos la clave "body" como representación del cuerpo del comentario como tal, cuyo valor se encuentra almacenado en la variable comment.

Luego se encriptó el parámetro con el método estático encode de la clase URLEncoder. Esta clase permite ajustar la cadena al sistema UTF-8 para que sea compatible con el tipo de contenido application/x-www-form-urlencoded, de acuerdo a los estándares de envío de información para el método POST establecido por la W3C.

Aunque en este ejemplo se usa un solo par clave-valor, a menudo necesitarás enviar múltiples pares. Para ello solo debes concatenarlos con el carácter "&" de acuerdo al estándar.

El siguiente paso fue declarar el envío de datos con setDoOutput(), seguido se estableció el valor en bytes de nuestros datos y además se añadió el tipo de contenido con setRequestProperty(). Este método te permite añadir cabeceras a la petición que envíes.

Finalmente se obtiene acceso al sistema de archivos del servidor con getOutputStream(), el cual retorna en un flujo de datos en donde escribirás los datos de los comentarios a través de los métodos flush() y write().

Subir un archivo hacia un servidor con el método POST

En la sección anterior se usó el tipo de contenido application/x-www-form-urlencoded para enviar datos atómicos hacia el servidor, pero...¿que hacer para subir un archivo?

Una de las formas es usar el tipo de contenido multipart/form-data del estandar W3C para enviar datos binarios de gran tamaño. Pero la verdad me resulta complicado preparar todas las sentencias de texto requeridas para dirigir el flujo de información. En su lugar puedes publicar el archivo directamente como bytes puros a través de getOutputStream() de la siguiente forma:

File file = new File("ruta_del_archivo");
URL url = new URL("http://www.tuservidor.com/");
HttpURLConnection con = null;
try{
con = (HttpURLConnection)url.openConnection();
// Activar método POST
con.setDoOutput(true);
// Tamaño desconocido
con.setFixedLengthStreamingMode(0);
OutputStream out = con.getOutputStream();
// Usas tu método ingeniado para convertir el archivo a bytes
out.write(convertfileToBytes(file));
out.flush();
out.close();
}finally{
if(con!=null)
con.disconnect();
}

Establecer peticiones HTTP en segundo plano usando AsyncTask

El tiempo que tarda la transmisión de datos en la red depende de muchos factores, como el tamaño de la información a intercambiar, los tiempos de latencia, la congestión del servidor o incluso la ejecución de múltiples tareas distintas en el sistema operativo. Cualquiera de estas situaciones puede prolongar el tiempo de una petición indefinidamente.

Pero como tú ya sabes, las tareas asíncronas nos auxilian en estas situaciones. Solo debemos crear una nueva instancia de la clase AsyncTask e incluir la petición al servidor en el método doInBackground() y luego actualizar los resultados visuales en onPostExecute().

Lee también Uso de Hilos y tareas asíncronas (AsyncTask) en Android

Por ejemplo, la obtención de todos los comentarios que se han guardado en el servidor de monstalker ha sido encapsulada en una clase llamada GetCommentsTask:

public class GetCommentsTask extends AsyncTask<URL, Void, List<String>> {
@Override
protected List doInBackground(URL... urls) {
List comments = null;
try {
// Establecer la conexión
con = (HttpURLConnection)urls[0].openConnection();
// Obtener el estado del recurso
int statusCode = con.getResponseCode();
if(statusCode!=200) {
comments = new ArrayList<>();
comments.add("El recurso no está disponible");
return comments;
}
else{

Parsear el flujo con formato JSON a una lista de Strings
que permitan crean un adaptador

InputStream in = new BufferedInputStream(con.getInputStream());
JSONCommentsParser parser = new JSONCommentsParser();
comments = parser.readJsonStream(in);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
con.disconnect();
}
return comments;
}
@Override
protected void onPostExecute(List s) {
Se crea un adaptador con el el resultado del parsing
que se realizó al arreglo JSON

ArrayAdapter adapter = new ArrayAdapter(
getBaseContext(),
android.R.layout.simple_list_item_1,
s);
// Relacionar adaptador a la lista
comments.setAdapter(adapter);
}
}

La secuencia de la tarea tendría la siguiente estructura:

Abrir la conexión hacia la URL en doInBackground().

Obtener el estado del recurso con getResponseCode(). Si la respuesta no es 200 OK, entonces preparar un valor de retorno que indique el error sucedido.

En caso de éxito, entonces se obtiene el flujo de datos con getInputStream()

Parsear o formatear dependiendo del flujo. En este caso particular la información viene como un arreglo de objetos JSON. Para traducirlo en información legible se ha implementado la clase JSONCommentsParser, la cual usa la clase android.util.JsonReader para leer los bytes y recorrer la estructura, de tal forma que al final se retornen los datos que interesan (una lista de comentarios).

Finalmente se realizan las acciones necesarias en onPostExecute(). MonsTalkers implementa crea un adaptador nuevo basado en el parámetro recibido y luego lo asocia al ListView.Si deseas formatear un flujo a Bitmap puedes usar el método estático decodeStream() de la clase BitmapFactory, el cual recibe como parámetro un tipo InputStream. Si en lugar de un bitmap, tienes texto plano, entonces puedes usar un objeto InputStreamReader, el cual puede convertir bytes a caracteres (char) y finalmente convertir a String.

Otros métodos para peticiones HTTP en Android

El método por defecto asociado a un objeto HttpURLConnection es GET. Cuando abres la conexión es sencillo obtener el flujo asociado a la URL con tan solo usar getInputStream(). El método POST tampoco es complicado de emplear, ya que solo se activa con setDoOutput() para estructurar los datos a enviar y escribir sobre el flujo de salida.

Pero en el caso de otros métodos como OPTIONS, HEAD, PUT, DELETE o TRACE debes usar el método setRequestMethod() para hacer efectiva la petición. No obstante este también se puede usar para especificar los métodos GET y POST.

con.setRequestMethod("GET");

Otra característica adicional de la clase HttpURLConnection es la capacidad de establecer los tiempos de caducidad de conexión y tiempos de caducidad de lectura a través de los métodos setConnectTimeout() y setReadTimeout():

// Expirar a los 10 segundos si la conexión no se establece
con.setConnecTimeout(10000)
// Esperar solo 15 segundos para que finalice la lectura
con.setReadTimeout(15000)

Conclusiones y Recomendaciones

El cliente HttpURLConnection nos permite usar métodos de petición de forma eficaz y amigable. Solo se indica la ubicación del recurso a través de una URL, luego defines tu propósito. Si el objetivo es obtener información, entonces asegúrate de crear un método que parsee la información con el formato correcto.

Por el contrario si se enviarán datos, entonces procura constituir pares clave-valor siguiendo el estándar. Adicionalmente recuerda usar tareas asíncronas ejecutar tus peticiones, de lo contrario el framework de Android te arrojará una excepción perteneciente al modo restringido, donde se te explica que no es permitido ejecutar peticiones en el hilo principal.

Aunque este cliente es una alternativa congruente, Google recomienda usar la librería HTTP Volley. Esta herramienta permite transmitir datos a través de la red en un alto nivel, debido a que establece una capa superior para evitar manejar el flujo de datos directamente, relaciona la fase de parsing con facilidad y optimiza el rendimiento de las operaciones. Pero este será un tema para otro artículo.

James Revelo Urrea - Desarrollador independiente http://www.hermosaprogramacion.com

Fuente: este post proviene de Hermosa Programación, donde puedes consultar el contenido original.
¿Vulnera este post tus derechos? Pincha aquí.
Creado:
¿Qué te ha parecido esta idea?

Esta idea proviene de:

Y estas son sus últimas ideas publicadas:

Recomendamos

Relacionado

informática desarrollo android

Volley es una librería desarrollada por Google para optimizar el envío de peticiones Http desde las aplicaciones Android hacia servidores externos. Este componente actúa como una interfaz de alto nivel, liberando al programador de la administración de hilos y procesos tediosos de parsing, para permitir publicar fácilmente resultados en el hilo principal. En este artículo veremos la guía co ...

informática json desarrollo android

¿Quieres saber cómo leer datos JSON alojados en un servidor desde tu aplicación Android? ¿Te gustaría aprender formas rápidas y comprensibles para convertir objetos JSON en objetos Java? ¿Además de todo quieres ubicar tus datos en un ListView?...Si te quedas y sigues leyendo hasta el final, tus preguntas serán respondidas a través de varios ejemplos prácticos. CONTENIDO ¿Qué es JSON? ...

informática desarrollo android

¿Andas buscando como parsear un archivo RSS con formato XML, para incluir contenidos de un sitio web en tu aplicación Android? ¿Necesitas ideas para crear una app lectora de Rss como Feedly, Flipboard o Flyne? Pues bien, en este tutorial verás cómo alimentar una lista de elementos con las noticias del sitio web forbes.com desde su feed con formato RSS a través de las tecnologías Volley y Simple Fr ...

Seguridad en Internet Servidor Seguro Tecnologia

Un servidor seguro es un servidor de paginas html (Servicio de tipo World Wide Web ) que establece una conexión con el cliente. De manera que la información circula a través de Internet encriptada mediante algoritmos. Estos que aseguran que sea inteligible solo para el servidor y el visualizador que accede al web. Un servidor seguro es la plataforma necesaria que permite establecer sobre servicio ...

Linux

No hay escasez de aplicaciones de control remoto en el mercado Android. Estas aplicaciones de control remoto le permiten enviar/recibir SMS en su navegador, recibir notificaciones de Android en su escritorio , controlar Windows 7 , o incluso transmisión de medios desde/hacia sus dispositivos . Con Remote Web Desktop , ahora puede controlar su teléfono Android desde el navegador de su escritorio. A ...

Actualidad SEO Error ...

Un error 404 leve o soft 404 se produce cuando un servidor web da un código de estado 200 (petición correcta) y sin embargo, el navegador nos muestra una página de error 404. Vamos por pasos: Códigos de estado HTTP Un código de estado HTTP es la respuesta que un servidor web da cuando se le hace una petición. Normalmente, cuando se hace una petición que es aceptada y procesada con éxito, el navega ...

amino Android apk ...

Un servidor es un ordenador u otro tipo de equipo informático encargado de suministrar información a una serie de clientes, que pueden ser tanto personas como otros dispositivos conectados a él. La información que puede transmitir es múltiple y variada: desde archivos de texto, imagen o vídeo y hasta programas informáticos, bases de datos, etc wikipedia Cada vez nuestro android son más potentes y ...

documentos evento node ...

Aprenderemos un poco de node.js lo básico tratare de hacer mas blog hacia para los principiantes. En este ejemplo, crearemos un servidor HTTP que escucha en el puerto 1337, que envía Hello, World! al navegador. NodeJS: es un entorno que ha dado de qué hablar en los últimos años dado su gran potencial. Se utiliza principalmente en la ejecución de código JavaScript, es asíncrono y está orientado a ...

informática android studio desarrollo android ...

¿Te has preguntado como iniciar una actividad desde otra actividad en Android? ó ¿Como iniciar una aplicación desde nuestras actividades?,si es así, este artículo te va a interesar mucho, ya que estudiaremos las entidades encargadas de comunicar los componentes de una aplicación con su entorno. Estos componentes a los que me refiero se le denominan Intents (intenciones, intentos). Si leíste el ar ...

general conversación gmail ...

Sois muchos los que en los foros de ayuda de Gmail habéis preguntado sobre la posibilidad de quitar o desactivar el modo conversación en la aplicación Gmail del móvil. Como ya sabemos en ajustes no se ofrece esa posibilidad pero un usuario (Gracias, Jonathan García) nos ha comunicado una opción que sí lo permite. Resumen para los AnsiaViva Quita la cuenta > Añádela en Gmail +5.0 como IMAP > ...