Tip Android #08: conexiones HTTP (networking)


VERSIONES

  1. 06/02/2013 (Primera publicación)
  2. 28/06/2015: Reescrito desde cero eliminado el código para Apache HttpClient

  3. android tip

    En Android SDK disponemos de dos APIs para interactuar con servidores HTTP/HTTPS:

    • URLConnection:basada en la API estándar de Java
    • Apache HttpClient: Android incluye una versión de esta API, más abstracta y fácil de utilizar que la anterior sobre todo si se utiliza para consumir servicios web REST. Lamentablemente esta versión es bastante antigüa y Google sólo mantiene URLConnection. Es más, en Android 5.1 (Api Level 22) ha sido marcada como obsoleta por lo que en este tip sólo veremos el uso básico de URLConnection

    Antes de ver el código, un par de observaciones:

    • Necesitamos definir en el Manifest el permiso correspondiente para acceder a Internet:

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

      También es una buena práctica comprobar que la conexión está disponible, ver el tip #1.

    • Por seguridad Android no permite realizar operaciones de “networking” en el hilo principal para evitar que la app quede bloqueda mientras se realiza la operación (se lanza la excepción NetworkOnMainThreadException). Debemos utilizar un hilo (ver tips #2 y #3).

    Plantilla para el uso de URLConnection

    A continuación se exponen las operaciones que generalmente deberemos realizar para el envío y recepción de datos a través de HTTP. El código es válido tanto para Android como para Java, si hubiera alguna diferencia se indicará.

    1. Crear la conexión para la url (para HTTPS usaríamos HttpsURLConnection)
      URL url = new URL("http://url.com");
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      //método http (GET, POST, PUT...)
      connection.setRequestMethod("POST");
      

      Si utilizando HTTPS obtenemos la excepción SSLHandshakeException consultar el tip 35: HTTPS y certificados

    2. Definir los timeout de conexión y lectura (opcionales)
      connection.setConnectTimeout(5000);
      connection.setReadTimeout(10000);
      
    3. Establecer los parámetros a incluir en el header, incluyendo autenticación BASIC si fuera necesario
      connection.setRequestProperty("Content-Type", "application/json");
      connection.setRequestProperty("User-Agent","cliente Android 1.0");
      //autenticación BASIC
      connection.setRequestProperty("Authorization","Basic " + Base64.encodeToString((usuario + ":" + password).getBytes(), Base64.NO_WRAP));
      

      Si estamos trabajando con Java en lugar de Android la autenticación BASIC se haría así:

      String basic = new String(Base64.encodeBase64((usuario + ":" + password).getBytes()));
      connection.setRequestProperty("Authorization","Basic " + basic);
      

      La clase Base64 pertenece a Apache Commons Codec.

    4. Incluir el documento que se enviará en el body si fuera necesario, por ejemplo el JSON o XML para un servicio REST.
      connection.setDoOutput(true);
      DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
      dataOutputStream.write(json.getBytes(StandardCharsets.UTF_8));
      dataOutputStream.flush();
      dataOutputStream.close();
      
    5. Si estamos enviando un formulario añadimos los campos del mismo
      connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
      OutputStreamWriter request = new OutputStreamWriter(connection.getOutputStream());
      request.write("campo1=danielme&campo2=android");
      request.flush();
      request.close(); 
      
    6. Realizar la petición y comprobar el código de estado devuelto por el servidor web para actuar en consecuencia. Podemos utilizar las constantes públicas definidas en la clase HttpUrlConnection
    7. if(connection.getResponseCode() == HttpURLConnection.HTTP_OK)	
      
    8. Obtener la respuesta para procesarla.
    9. InputStream inputStreamResponse = connection.getInputStream();
      

      Por ejemplo, si la respuesta es un documento de texto plano (html, XML, JSON…) la convertimos en una cadena.

      String linea = null;	
      StringBuilder respuestaCadena = new StringBuilder();
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStreamResponse, "UTF-8"));
      while((linea = bufferedReader.readLine()) != null){
      	respuestaCadena.append(linea);
      }
      

      Si es una imagen se puede utilizar la clase BitmapFactory

      Bitmap bmp = BitmapFactory.decodeStream(inputStreamResponse);
      
    10. Cerrar siempre el InputStream de respuesta en un finally. Generalmente no es necesario realizar un connection.disconnect(), la liberación o reutilización del socket será realizada por el sistema

      if (inputStreamResponse != null){
         try{
           inputStreamResponse.close();
         }
         catch(IOException ex){
           Log.d(this.getClass().toString(), "Error cerrando InputStream", ex);
         }
      }
      
      1. Frameworks

        Aunque no es excesivamente complicada de utilizar, URLConnection exige escribir bastante código para realizar operaciones básicas con servidores HTTP lo que nos obligará a implementar métodos genéricos, Wrappers, etc, que nos permitan abstraer y reutilizar todo el código que sea posible. Afortunadamente tenemos a nuestra disposición frameworks Open Source ampliamente utilizados que facilitan enormemente el trabajo para interactuar con servidores HTTP especialmente la hora de implementar clientes REST:

        • Volley. Creada por Google, permite crear clientes REST/HTTP mediante anotaciones de forma rápida y sencilla. Es muy configurable y potente e incluso permite configurar el reescalado de las imágenes obtenidas.
        • Retrofit. También se basa en anotaciones pero es menos configurable y carece de algunas características avanzadas de Volley como el tratamiento de imágenes. Como contrapartida, es algo más sencilla de utilizar y realiza automáticamente la conversión entre objetos y JSON al estar integrada de serie con Gson.
        • Picasso: solución específica para la descarga de imágenes y su reescalado y “cacheo” tanto en memoria como en disco. Es realmente potente pero muy fácil de utilizar.
        • Android Glide: alternativa a Picassa menos conocida pero más potente.

        << TIPS ANDROID

2 Responses to Tip Android #08: conexiones HTTP (networking)

  1. Noe dice:

    que tal, buen dia te platico, tengo algunos dias investigando sobre como pasar parametros de android a php a un web service , sin embargo a pesar de que tengo todo exactamente como bien lo mencionas no consigo lograrlo, parece que todo va bien con android sin embargo en php no sucede nada no muestra si se definen las variables, ojala me pudieras echar la mano, saludos y felicidades por tu post…

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: