sábado, 8 de marzo de 2014

ActionBarSherlock , otra linda libreria muy popular !

Desde que google lanzó su versión de HoneyComb (API 11) hace unos años, la api de Android cuenta con unos componentes visuales nuevos como el ActionBar. Pero estas mejoras de los componentes UIs y de las interfaces no tienen en cuenta las versiones anteriores del sistema . Este ActionBar ya esta siendo muy usado por muchos desarrolladores en muchos proyectos, y para resolver el tema de compatibilidad con las versiones anteriores a la API 11, Jack Wharton creó una librería, ahora indispensable, que permite agregar el ActionBar a tu proyecto sin la necesidad usar Fragments y de esta forma dar la posibilidad a todas las versiones del sistema operativo de poder beneficiarse de la misma interfaz.

En este post, resumiremos en pocos pasos como se instala el ActionBarSherlock para todos sus proyectos con el SDK de Android.

El primer paso consiste en descargar la librería, la cual se puede hacer desde la pagina http://actionbarsherlock.com/ o también se puede hacer clone del repositorio de github en alguna parte de su desktop.

$ git clone git@github.com:JakeWharton/ActionBarSherlock.git

Una vez que tienes descargado todo el proyecto con los ejemplos, ya podes empezar a importarlo en Eclipse.

Existing Android Code to Workspace

File > import > Existing Android Code To Workspace

Antes de importar el proyecto, se debe activar la opción de copiar el proyecto en su Workspace.

copiar el proyecto en su Workspace

Ahora bien, si nos aparecen muchos errores, no nos alarmemos, vamos directamente a las propiedades del proyecto, y seleccionamos el Compilador Compliance para este proyecto; a saber la versión 1.6.

En las propiedades de la carpeta de ActionBarSherlock hay que fijarse si eclipse importó el proyecto como una Librería. Si no es el caso entonces podemos tildar la opción “Library”.

Libreria

Luego ya podemos crear nuestro proyecto vacío como de costumbre y buscar ActionBarSherlock en la lista de librerías disponibles.

ActionBarSherlock como Libreria

Luego hay que abrir nuestro archivo AndroidManifest.xml y remplazar android:theme=”@style/AppTheme” por android:theme=”@style/Theme.Sherlock”

En nuestro Activity principal, en vez de heredar de la clase Activity del SDK de android, la remplazamos por la Clase SherlockActivity.


public class MainActivity extends SherlockActivity {
 
    protected Context context;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        context = getApplicationContext();
        getSupportActionBar().setTitle(R.string.app_name);
        getSupportActionBar().setLogo(R.drawable.androidda_icon);
        getSupportActionBar().setHomeButtonEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
    }
 
    @Override
    public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
        MenuInflater inflater = getSupportMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }
 
}

Fuente: http://www.androidda.com/

viernes, 7 de marzo de 2014

Picasso, otra importante libreria

Continuamos con las presentaciones de librerias y "cosas utiles" a la hora de programar Aplicaciones robustas, que van mas alla del "Hola Mundo" o pruebas de concepto aisladas.
Ahora, vamos a hablar de una de las librerías para Android, Picasso, que se utiliza para desarrollar  aplicaciones para Android y que, como desarrollador, recomiendo. 
picasso
Picasso © Square Inc.
Si alguna vez has tratado de desarrollar una aplicación para Android, o saber cómo diseñar una, lo más seguro es que tenga imágenes y, sin duda, éstas las descargarás de Internet. 
Tratar con imágenes en Android es muy difícil para un principiante y, especialmente, frustrante si no tienes la suficiente experiencia en informática. Por suerte, la web oficial de Desarrolladores Android ofrece gran cantidad de información y documentación sobre este tema acompañado de proyectos de ejemplo que harán el proceso mucho más fácil. 
Si eres un desarrollador de Android a tiempo completo, estoy seguro de que has desarrollado tu propia versión de AwesomeAsyncImageView.java. ¡Todos lo hacemos!
Puesto que mi intención es que este artículo sea entendido por la mayoría de las personas que utilizan Android y, además, se interesen por algunos técnicos, vamos a empezar por algunos problemas comunes cuando se trata con imágenes. 
En primer lugar, recordemos que la batería es lo que alimenta la CPU. Por tanto, mientras más lo uses, menos batería tendrás.  Algo obvio para todos. Así que, si queremos desarrollar una aplicación que muestre una lista de noticias, puede que sea más conveniente que solo muestre una imagen y el título. 

El problema ANR

anr
Un diálogo ANR (Aplicación No Responde) mostrado al usuario. / © Creative Commons Attribution 2.5
Para empezar, tenemos que ponernos en contacto con el servidor para pedir algunas noticias (el formato en el que el servidor responde no importa ahora). Por ejemplo, nos pueden dar un título y una URL para la imagen. Así, solo tenemos que comenzar a descargar las imágenes una tras otra hasta que nos aparezca el terrible mensaje ANR (Aplicación No Responde). 
El motivo principal es que tu aplicación está tan ocupada descargando imágenes sin parar que no ha tenido tiempo a 'dibujarse' a sí misma en la pantalla, por lo que el Android OS piensa que la aplicación se ha colgado. Por supuesto, el usuario siempre puede pulsar la tecla de 'Esperar' y dejar que la app termine su trabajo, pero esto solo supondría una pésima experiencia de usuario (UX). 

La introducción de 'threads'

La mejora de la UX de nuestra aplicación nos obligará a aprender el concepto de 'threads' (hilos o temas). Los 'threads' son solo unidades de ejecución concurrentes, lo que significa que se ejecutan al mismo tiempo y cada aplicación tiene por lo menos un hilo conductor, generalmente el hilo de interfaz de usuario (UI). Este hilo es responsable de señalar a la aplicación en la pantalla. 
Este problema se resuelve fácilmente mediante la creación de un nuevo 'thrad' que pueda descargar las imágenes en el fondo y así cuando haya terminado puede comunicar al hilo de UI que las imágenes se han descargado para que pueda mostrarlas. De esta forma se evita la aparición del problema ANR. 

El problema de la rotación de pantalla

En el momento que giramos la pantalla de nuestro dispositivo la aplicación tiene que volverse a dibujar, básicamente porque lo más seguro es que tengas un diseño opmitizado del layout y, lamentablemente, hay que descargar las imágenes otra vez. Una pérdida de energía en términos de batería que también se pueden traducir en unos cuantos kilobytes de datos de tu tráfico mensual. 

La solución de la memoria caché

Es el momento en el que te sientas familiarizado con el concepto 'caché'. Simplemente se trata de un componente de la aplicación donde se van a almacenar datos de manera que en futuras solicitudes el servidor pueda ser más rápido. Un caché puede hacer que tu aplicación utilice más memoria, por supuesto, pero la memoria es barata y los beneficios son mucho mayores que el uso de la memoria. 
Con un caché tu aplicación se comporta de la siguiente manera: el 'thread' de UI le comunica al cache que necesita cierta imagen, por ejemplo, 'nexus4.png'. El caché no tiene nada (llamado error de caché), por lo que descarga una imagen y se la da al 'thread' de UI, y de paso la mantiene en la memoria. En el momento de girar la pantalla, el subproceso de UI pide de nuevo la imagen, pero esta vez la memoria caché está preparada (llamado acierto de caché) y no tiene que descargar la imagen de nuevo. Estamos en el 2013, no deberíamos preocuparnos por los kilobytes extra de memoria si conseguimos que la aplicación sea rápida y ahorre energía. 

El problema 'cerra app' 

Nuestro último problema. Seguro que a más de uno le habrá pasado que al pulsar el botón 'Atrás', Android la cierra y tenemos que abrirla otra vez. Por desgracia, tendrás que descargar todo de nuevo. Tengo tu solución, pero una vez más hará que se utilice más memoria, en este caso, interna, pero no debería importarte demasiado porque el espacio en el disco es muy barato. En vez de usar únicamente memoria caché, también se puede almacenar caché en el disco. Tu aplicación se comportará como antes, pero esta vez, después de dar la imagen que el 'thread' de UI haya solicitado, la misma se almacenará en el disco. Así, si la aplicación se cierra inesperadamente no necesitamos descargar la imagen de nuevo. 
picasso debug
Como opción Debug para desarrolladores, Picasso puede mostrar la fuente de donde proviene la foto: servidor, memoria interna o RAM. / © Square Inc.

Conclusión

Para terminar, lo mejor para evitar estos problemas es una herramienta como la librería Picasso, puesto que es capaz en una sola línea de código de encargarse de esto. Así, como desarrollador podrás invertir tu tiempo en cosas más interesantes que la gestión de imágenes. 
Espero que hayas aprendido un poco más sobre el comportamiento de aplicaciones en Android. 

sábado, 1 de marzo de 2014

Framework Volley - Android


Quiero arrancar marzo con TODO! porque es uno de los meses en donde hacemos las planificaciones de nuestras capacitaciones, proyectos, y también en donde nos embarcamos en nuevos aprendizajes. En esta secuencias de post que hoy comienzan, vamos a repasar un par de frameworks y utilidades, dentro del ecosistema Android.

Ya sabemos programar en Android, ya hemos realizado varias aplicaciones, y nos fuimos dando cuenta de que varias veces copiamos y pegamos el mismo codigo de ciertas actividades y clases de utilidades, para realizar tareas que son muy, pero muy parecidas.
Ese es el caso de las Tareas Asyncronicas para comunicarse con un servidor mediante HTTP.
Entonces....algo debe existir, algún framework debe ya existir para evitar repetir ese "copy-paste" de nuestro codigo.

Bueno.... si, existe, y se llama "Framework Volley", y tambien es de la gente de Google. A continuación, repasamos un Kick-Off del framework, y las principales caracteristicas.

¿Que es Volley?

Es una libreria que podremos integrar a nuestro proyecto Android para hacer mas faciles y rapidas las operaciones de red como: Descarga de imagenes, pedidos de datos entre cliente y servidor.

Para una mejor explicacion, tenemos el video oficial de los ingenieros de Google:
http://www.youtube.com/watch?v=yhv8l9F44qo

¿Ventajas de Volley? 


Volley automáticamente programa todas las solicitudes de red. Significa que Volley se hace cargo de toda las solicitudes de red que su aplicación ejecuta para ir a buscar la respuesta o la imagen de la web.
-Volley ofrece disco transparente y el almacenamiento en caché de memoria.
-Volley ofrece una potente API de solicitud de cancelación. Esto significa que se puede cancelar la solicitud o puede establecer bloques o ámbitos de peticiones para cancelar.
-Volley proporciona potentes capacidades de personalización.
-Volley proporciona herramientas de depuración y rastreo. Si, està bueno debugear una libreria.

Kick-Off de Volley


Primero, vamos a clonar el proyecto de Github
Direccion: https://android.googlesource.com/platform/frameworks/volley.

Si no sabes como clonar un proyecto de Github, ya mismo ponete a googlear por un tutorial.
 
Si no quieres clonarla puedes descargarla de este link: 
 https://mega.co.nz/#!Rpd1TZBJ!NsGKxVL3klmXUl-9qX2SVkxI54do1P_-ub3vjqG9kLk


Lo primero, es que dentro de Volley se encuentran dos clases java importantes:
1. Request queue: Es para utilizar a Volley para el envío de solicitudes a la red, puedes hacer una cola de peticiones en demanda si lo deseas, pero por lo general, la libreria las crea desde el principio, en el momento de arranque, y mantenerlo alrededor y utilizarlo como Singleton (instancia única).
2. Request: Contiene todos los detalles necesarios para hacer llamadas de API Web. Por ejemplo: el método a utilizar (GET o POST), datos de la solicitud, listeners (comunes y de errores)

Ahora, vamos al Eclipse, y nos vamos a Importar Volley en nuestro espacio de trabajo de Eclipse.





Creamos un nuevo proyecto del tipo aplicación Android (todo esto ya lo recontra saben)



En la siguiente imagen pueden ver, como el nombre del proyecto es "EjemploVolley"  y al paquete "com.ejemplo.volley" como puedes ver a continuación:

Importamos Volley haciendo clic derecho sobre la carpeta de proyecto luego "propiedades/android/"

Recuerda agregar al Manifest de tu aplicación los permisos de Internet:
<uses-permission android:name="android.permission.INTERNET"/>


En nuestro proyecto veremos como Volley trabaja en el pedido de imagenes, y para ello comenzaremos creando una clase java la cual nos servirá para el tratamiento de la cache.



Luego crearemos una clase llamada ConvertidorJSON que nos servirá para hacer pedidos de url de imagenes via JSON.

package com.ejemplo.volley;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class ConvertidorJSON {
static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";
   public ConvertidorJSON()  {
  
   }
   public JSONObject getJSONFromUrl(String url) {    
        try {          
           DefaultHttpClient httpClient = new DefaultHttpClient();
           HttpPost httpPost = new HttpPost(url);

           HttpResponse httpResponse = httpClient.execute(httpPost);
           HttpEntity httpEntity = httpResponse.getEntity();
           is = httpEntity.getContent();           

       } catch (UnsupportedEncodingException e) {
           e.printStackTrace();
       } catch (ClientProtocolException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
        
       try {
           BufferedReader reader = new BufferedReader(new InputStreamReader(
                   is, "UTF-8"), 8);
           StringBuilder sb = new StringBuilder();
           String line = null;
           while ((line = reader.readLine()) != null) {
               sb.append(line + "\n");
           }
           is.close();
           json = sb.toString();
       } catch (Exception e) {
           Log.e("Buffer Error", "Error converting result " + e.toString());
       }

       // try parse the string to a JSON object
       try {
           jObj = new JSONObject(json);
       } catch (JSONException e) {
           Log.e("JSON Parser", "Error parsing data " + e.toString());
       }

       // return JSON String
       return jObj;

   }
}


Luego creamos el codigo de nuestra vista XML. En el cual tendremos ademas de un control ImageView tradicional uno referente a la libreria Volley que es el NetworkImageView.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="150dp"
        android:layout_height="170dp"
        android:layout_centerHorizontal="true"
        android:src="@drawable/ic_launcher" />

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/networkImageView"
        android:layout_width="150dp"
        android:layout_height="170dp"
        android:layout_below="@+id/imageView1"
        android:layout_centerHorizontal="true"
        android:src="@drawable/ic_launcher" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="vertical" >

      
    </LinearLayout>

</RelativeLayout>

El codigo anterior deberia generarnos la siguiente vista grafica.



La siguiente codificacion corresponde al codigo de la activity en este ejemplo cargaremos dos imagenes una por medio de URL y la otra a traves de la lectura de un JSON generado por un Servicio Web en PHP.

package com.ejemplo.volley;

import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.Volley;
import com.technotalkative.volleyimageloading.R;

public class MainActivity extends Activity {

private RequestQueue mRequestQueue;
private ImageLoader imageLoader;
private String img1, img2;
private ImageView imageView;
private NetworkImageView networkImageView;
String urlimg1, urlimg2;
private static final String IMAGE_URL = "http://developer.android.com/images/gp-device.png";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

networkImageView = (NetworkImageView) findViewById(R.id.networkImageView);
imageView = (ImageView) findViewById(R.id.imageView1);
new MiTarea().execute("http://miweb/ws/webservice.php");
mRequestQueue = Volley.newRequestQueue(this);
imageLoader = new ImageLoader(mRequestQueue, new BitmapLruCache(
BitmapLruCache.getDefaultLruCacheSize()));

}

 

private class MiTarea extends AsyncTask<String, Float, Integer> {
private static final String im1= "nombreimg1";
private static final String im2= "nombreimg2";

protected void onPreExecute() {
// antes de comenzar
}

protected Integer doInBackground(String... params) {

String url = params[0];
try {

try {
ConvertidorJSON jp = new ConvertidorJSON();
JSONObject json = jp.getJSONFromUrl(url);
img1 = json.getJSONArray(im1).getString(0);
img2 = json.getJSONArray(im2).getString(0);

} catch (JSONException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
String urlbase = "http://miweb/ubicaciondeimagenes/";

// urls para imagenes
urlimg1 = urlbase + "directorio/" + img1;// url para imagen 1
urlimg2 = urlbase + "directorio/" + img2; // url para imagen2

return null;

}

protected void onProgressUpdate(Float... valores) {

}

protected void onPostExecute(Integer bytes) {
networkImageView.setImageUrl(urlimg1, imageLoader);
imageLoader.get(urlimg1, ImageLoader.getImageListener(imageView,
R.drawable.ic_launcher, R.drawable.ic_error));
}
}

}


Podras observar que para la descarga de imagenes se hizo en un hilo secundario gracias a la potencia de la clase abstracta Asyntask http://developer.android.com/reference/android/os/AsyncTask.html
de Android, toda accion de descarga de contenido en red es preferible hacerlo en segundo plano a traves de un nuevo hilo de ejecucion.

A continuacion podemos ver la ejecucion de nuestro proyecto y la rapidez con la cual descarga las imágenes inclusive en una conexion a internet no muy rapida, yo uso Genymotion como emulador es un poco mas rápido que los emuladores del SDK de Android. http://www.genymotion.com/

Puedes por ejemplo programar un boton y mediante el descargar las imagenes para que veas como Volley realiza su trabajo a traves del LogCat.

Hasta acà, con la introduccion y resumen de lo que es el Framework Volley, màs adelante sin duda que vamos a ir agregando algun que otro ejemplo màs de este prometedor framework.