Fuente: http://www.maestrosdelweb.com Autor: Adrian Catalán
Bienvenidos al primer capítulo del curso sobre Android daremos inicio con el funcionamiento de la arquitectura de esta plataforma móvil y los bloques básicos de una aplicación.
En la base tenemos el kernel 2.6 de Linux, Android lo utiliza por su robustez demostrada y por la implementación de funciones básicas para cualquier sistema operativo, por ejemplo: seguridad, administración de memoria y procesos, implementación de conectividad de red (network stack) y varios interpretes (drivers) para comunicación con los dispositivos físicos(hardware).
Android utiliza como base el kernel de Linux pero los dos sistemas no son lo mismo, Android no cuenta con un sistema nativo de ventanas de Linux ni tiene soporte para glibc (libería estándar de C) ni tampoco es posible utilizar la mayoría de aplicaciones de GNU de Linux.
Además de todo lo ya implementado en el kernel de Linux, Android agrega algunas cosas específicas para plataformas móviles como la comunicación entre procesos (lograda a través del binder), la forma de manejar la memoria compartida (ashmem) y la administración de energía (con wakelocks). De las características únicas del kernel utilizado por Android encuentran más información en Android Kernel Features.
Sobre el kernel, tenemos un conjunto de librerías de C y C++ utilizadas por el sistema para varios fines como el manejo de la pantalla (surface manager), mapas de bits y tipos de letra (Free Type), gráficas en 2D y 3D (SGL y OpenGL), manejo de multimedia (Media Framework), almacenamiento de datos (SQLite) y un motor para las vistas web y el navegador (WebKit).
Junto a estas librerías, encontramos lo necesario para la ejecución de las aplicaciones a través de la máquina virtual Dalvik. Cada aplicación utiliza una instancia de la máquina virtual ejecutando un archivo DEX (Dalvik Executable) y el sistema está optimizado para que se ejecuten múltiples instancias de la máquina virtual. Se desarrolla en java pero no se utiliza una máquina virtual de Sun para su ejecución ni tampoco archivos CLASS.
Sobre las librerías encontramos una estructura que nos brinda un contexto para desarrollar, este framework permite a los desarrolladores aprovechar un sistema de vistas ya construido, administrar notificaciones y acessar datos a través de proveedores de contenido entre otras cosas.
Las aplicaciones centrales que incluye el sistema por defecto son: teléfono, navegador, manejo de contactos, etc. En esta capa de la arquitectura es donde trabajaremos desarrollando aplicaciones.
Una vez vista la arquitectura, empezaremos con lo fundamental para desarrollar una aplicación. Los componentes básicos de una aplicación son: activities, intents, views, services, content providers y broadcast receivers. Si dominan bien estos términos pueden saltar directo al código.
AndroidManifest.xml es donde se configura la aplicación, se agregan actividades, se asignan permisos, etc.La aplicación que realizaremos es un lector para el feed de Maestros del Web, queremos que al finalizar se vea de la siguiente forma:
Arrancamos importando el código que pueden descargar en hacia un proyecto nuevo. En mi caso, el código descargado lo tengo en el folder “/Users/ykro/Desktop/LectorFeedMDWBase”:
En este código encontrarás algunas cosas de ayuda para el desarrollo del proyecto. Si quisieran iniciar desde cero, con un proyecto nuevo, lo mínimo que deberían hacer para tenerlo listo es:
Para hacer esto, vamos al archivo AndroidManifest.xml y justo antes de la etiqueta que cierra manifest colocamos:
Para lograr esto, en el archivo /res/layout/main.xml es necesario tener:
En el código de demo se provee la clase src/com/android/mdw/demo/XMLParser.java.
No vamos a repasar el código de cómo se hace el reconocimiento de XML, este parser tiene un funcionamiento general sin embargo para los fines de esta aplicación nos interesa que devuelva una lista simplemente encadenada (LinkedList de Java) y en cada posición un diccionario (HashMap de Java) porque de esa forma vamos a almacenar los datos. Esto se logra a través de un método llamado parse() y adicional a esto, en el constructor el XMLParser debe recibir la dirección del feed que reconocerá.
Trabajaremos con los siguientes views para lograr el objetivo.
Vamos a colocar primero un LinearLayout con arreglo vertical y dentro de él dos cosas:
Nuestro archivo /res/layout/main.xml quedaría entonces de la siguiente forma:
Es importante notar los identificadores que colocamos, ya que los utilizaremos más adelante.
Luego de terminado el diseño podemos enfocarnos en el código que nos permitirá poblar el ListView con los elementos del feed que vamos a leer. Trabajemos ahora en el archivo src/com/android/mdw/demo/Main.java. Inicialmente encontramos 2 constantes que utilizaremos para guardar la información en un HashMap.
static final String DATA_TITLE = "T";
static final String DATA_LINK = "L";
Agregamos una estructura de datos estática para guardar la información del feed una vez la fuimos a traer y reconocimos.
static LinkedList
En una aplicación real esto no debería hacerse nunca, todo campo estático (variable de clase) debería ser final y en este caso no lo es porque lo asignaremos luego de que el parser devuelva la data. La forma correcta de realizar este almacenamiento volátil es utilizando clases de aplicación, algo que veremos en próximos capítulos y si se quisiera almacenamiento no volátil se tiene acceso a base de datos a través de SQLite.
Haremos también una función auxiliar que recibe una lista de mapas, y utilizando esta data crea un adaptador para poblar al ListView del diseño.
private void setData(LinkedList
Nuestro objetivo final es tomar una vista (ListView) creada en el diseño y poblarla de datos a través de un adaptador. La información que representaremos por cada fila del listado es el título del artículo y el link del mismo. Para nuestro caso vamos a utilizar el adaptador simple (SimpleAdapter) que recibe 5 parámetros.
getApplicationContext()android.R.layout.two_line_list_item este nos permite tener elementos con información en 2 líneas.Con esta configuración, el adaptador nos dará elementos de 2 líneas mostrando en la primera el título del artículo y en la segunda el link del artículo. Esta configuración resulta muy útil porque todo está hecho, sin embargo no es personalizable, si queremos cambiar algunas cosas (fondo, color, letra, etc) de cada elemento sería necesario agregar otro layout para cada fila y si deseamos mostrar más información o no utilizar una lista de mapas entonces sería necesario hacer nuestro propio adaptador (esto lo haremos en próximos capítulos).
La carga de datos nos tomará cierto tiempo, vamos a mostrarle un aviso de que los datos se están cargando. Queremos que el aviso se muestre y como tarea de fondo cargue los datos (esto NO es un servicio) vamos a necesitar de un hilo de ejecución que haga esta tarea.
Android nos presenta la restricciones que no podemos alterar, los elementos de interfaz gráfica en un hilo de ejecución que no sea el principal por lo que es necesario utilizar un manejador para enviar un mensaje de un hilo a otro cuando la carga de datos haya terminado. Agregaremos entonces una variable para el diálogo de progreso es necesaria una variable global porque iniciamos el diálogo en una función y lo ocultamos en otra
private ProgressDialog progressDialog;
Otra para el manejador de mensajes entre hilos de ejecución:
private final Handler progressHandler = new Handler() {
@SuppressWarnings("unchecked")
public void handleMessage(Message msg) {
if (msg.obj != null) {
data = (LinkedList
Para el manejador, haremos una clase interna y anónima este tipo de clases las verán seguido para agregar funcionalidades que requieren de clases pero su tarea es tan pequeña que no vale la pena darle un nombre (y luego terminar con muchos nombres que se utilizan una sola vez).
Dentro de la clase Handler hemos agregado la anotación @SuppressWarnings("unchecked") para evitar una advertencia por la conversión de tipo (type casting) de objeto hacia lista realizada adelante. Es necesario implementar el método handleMessage(Message msg) y es aquí donde revisamos si viene un mensaje, lo convertimos a lista, llamamos al método setData previamente definido y cerramos el diálogo de progreso.
Por último, vamos a hacer una función auxiliar que inicia la carga de datos, muestra al usuario un diálogo de que se están cargando los datos y levanta un thread para lograr la carga.
private void loadData() {
ProgressDialog progressDialog = ProgressDialog.show(
Main.this,
"",
"Por favor espere mientras se cargan los datos...",
true);
new Thread(new Runnable(){
@Override
public void run() {
XMLParser parser = new XMLParser(feedUrl);
Message msg = progressHandler.obtainMessage();
msg.obj = parser.parse();
progressHandler.sendMessage(msg);
}}).start();
}
Para el diálogo de progreso, le enviamos 4 argumentos:
Luego tenemos un Thread a partir de otra clase interna y anónima que es una instancia de Runnable y definimos el método run donde se especifica lo que hará el hilo de ejecución y llamamos al método start para iniciarlo. En el método run instanciamos un parser nuevo de XML construimos un mensaje a partir del manejador y se lo enviamos con la data obtenida del parser.
Trabajemos dentro de la función onCreate la cual se llama cuando la actividad es creada, primero le ponemos un bonito título a la ventana.
setTitle("Lector de feed Maestros del Web");
El siguiente paso es asociarle una acción al botón para que cargue los datos, primero obtenemos el botón haciendo uso de la función findViewById con el identificador colocado en el diseño para posteriormente colocarle las acciones a realizar cuando se presione a través del método setOnClickListener. Este método recibe una instancia de la clase OnClickListener, de nuevo vamos a hacer una clase anónima y sobrecargaremos el método onClick.
Button btn = (Button) findViewById(R.id.btnLoad);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
Dentro de la función onClick validaremos si el ListView ya tiene datos, si no los tiene los cargamos con una llamada a loadData pero si ya los tiene vamos a mostrarle un diálogo de alerta al usuario preguntando si está seguro que desea hacerlo.
ListView lv = (ListView) findViewById(R.id.lstData);
if (lv.getAdapter() != null) {
AlertDialog.Builder builder = new AlertDialog.Builder(Main.this);
builder.setMessage("ya ha cargado datos, ¿Está seguro de hacerlo de nuevo?")
.setCancelable(false)
.setPositiveButton("Si", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
loadData();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.create()
.show();
} else {
loadData();
}
Para crear el diálogo de alerta, encadenamos llamadas a partir de un constructor AlertDialog.Builder que recibe un contexto y de nuevo utilizamos Main.this.
Estas llamadas encadenadas nos permiten:
Las más complicadas son las llamadas para colocar acciones ante una respuesta positiva o negativa. Ambas requieren de un Listener que se disparara cuando el usuario presione el botón. Dentro del método onClick de otra clase anónima más, cuando es positivo llamamos a loadData y cuando es negativo ocultamos el diálogo.
Luego de todo, el código completo queda de esta forma:
Button btn = (Button) findViewById(R.id.btnLoad);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ListView lv = (ListView) findViewById(R.id.lstData);
if (lv.getAdapter() != null) {
AlertDialog.Builder builder = new AlertDialog.Builder(Main.this);
builder.setMessage("ya ha cargado datos, ¿Está seguro de hacerlo de nuevo?")
.setCancelable(false)
.setPositiveButton("Si", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
loadData();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.create()
.show();
} else {
loadData();
}
}
});
Para terminar, queremos aprovechar que contamos con el link de cada artículo y que cuando el usuario presione algún elemento en nuestra aplicación pueda visitarse el artículo vía el navegador.
ListView lv = (ListView) findViewById(R.id.lstData);
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView av, View v, int position, long id) {
HashMap
Esto lo conseguimos modificando el evento de click sobre los ítems de la lista (setOnItemClickListener) primero obteniendo el elemento que ha sido presionado y luego con un intent de ACTION_VIEW este intent predefinido realiza la acción más obvia para mostrar datos al usuario, en nuestro caso se le envía un URI lo que permite visualizarlo con el navegador.
Descarga: el código completo utilizado en este capítulo.
En esta guía hemos visto varias cosas:
Las imágenes fueron tomadas de http://developer.android.com
Comparte:
Tu Comentario| Nombre | |
| Localidad | |
| País | |
| Comentario |
|
Divum.es | Licencia de Uso | Enlaces de Interés

Esta obra está bajo una licencia de Creative Commons.