Vous êtes sur la page 1sur 32

SALVADOR GMEZ OLIVER

WWW.SGOLIVER.NET

DOCUMENTO DE MUESTRA
Este documento es tan slo un fragmento de muestra del Curso completo de Programacin en Android de sgoliver.net, al que podis acceder de forma gratuita desde la siguiente URL:

http://www.sgoliver.net/blog/?p=1313

Versin 2.0 // Noviembre 2011

Este documento y todo el cdigo fuente suministrado, al igual que todos los contenidos publicados en el blog sgoliver.net, se publica bajo licencia Creative Commons Reconocimiento NoComercial - SinObraDerivada 3.0 Espaa (CC BY-NC-ND 3.0). Siga el enlace anterior para obtener informacin detallada sobre los trminos de la licencia indicada.

NDICE

DE

CONTENIDOS

PRLOGO ................................................................................................................................ 5 A QUIN VA DIRIGIDO ESTE LIBRO? .....................................................................................6 LICENCIA .................................................................................................................................6 Conceptos Bsicos .................................................................................................................. 7 Entorno de desarrollo Android .....................................................................................8 Estructura de un proyecto Android ............................................................................ 12 Componentes de una aplicacin Android ................................................................... 15 Desarrollando una aplicacin Android sencilla ........................................................... 17 Interfaz de Usuario ................................................................................................................24 Layouts ...................................................................................................................... 25 Botones......................................................................................................................29 Imgenes, etiquetas y cuadros de texto ..................................................................... 32 Checkboxes y RadioButtons ....................................................................................... 36 Listas Desplegables .................................................................................................... 38 Listas..........................................................................................................................42 Optimizacin de listas ................................................................................................ 47 Grids .......................................................................................................................... 50 Pestaas .................................................................................................................... 52 Controles personalizados: Extender controles ........................................................... 56 Controles personalizados: Combinar controles .......................................................... 59 Controles personalizados: Diseo completo .............................................................. 67 Widgets de Escritorio ............................................................................................................ 74 Widgets bsicos ......................................................................................................... 75 Widgets avanzados .................................................................................................... 79 Mens ....................................................................................................................................88 Mens y Submens bsicos ........................................................................................89 Mens Contextuales...................................................................................................94 Opciones avanzadas de men ....................................................................................98 Tratamiento de XML ........................................................................................................... 105 Tratamiento de XML con SAX .................................................................................. 106 Tratamiento de XML con SAX Simplificado.............................................................. 112 Tratamiento de XML con DOM ................................................................................ 115

Tratamiento de XML con XmlPull............................................................................. 120 Bases de Datos .................................................................................................................... 123 Primeros pasos con SQLite ...................................................................................... 124 Insertar/Actualizar/Eliminar ..................................................................................... 129 Consultar/Recuperar registros .................................................................................. 131 Preferencias......................................................................................................................... 134 Preferencias Compartidas ........................................................................................ 135 Pantallas de Preferencias ......................................................................................... 137 Localizacin Geogrfica ...................................................................................................... 145 Localizacin Geogrfica Bsica ................................................................................ 146 Profundizando en la Localizacin Geogrfica ........................................................... 152 Mapas .................................................................................................................................. 159 Preparativos y ejemplo bsico .................................................................................. 160 Control MapView ..................................................................................................... 167 Overlays (Capas) ...................................................................................................... 172 Ficheros ............................................................................................................................... 178 Ficheros en Memoria Interna.................................................................................... 179 Ficheros en Memoria Externa (Tarjeta SD) ............................................................... 182 Content Providers ............................................................................................................... 187 Construccin de Content Providers .......................................................................... 188 Utilizacin de Content Providers .............................................................................. 197 Notificaciones ..................................................................................................................... 203 Notificaciones Toast ................................................................................................ 204 Notificaciones de la Barra de Estado ........................................................................ 205 Cuadros de Dilogo .................................................................................................. 213 Depuracin de aplicaciones ................................................................................................ 219 Logging en Android..................................................................................................220

PRLOGO
Hay proyectos que se comienzan sin saber muy bien el rumbo exacto que se tomar, ni el destino que se pretende alcanzar. Proyectos cuyo nico impulso es el da a da, sin planes, sin reglas, tan solo con el entusiasmo de seguir adelante, a veces con ganas, a veces sin fuerzas, pero siempre con la intuicin de que va a salir bien. El papel bajo estas lneas es uno de esos proyectos. Naci casi de la casualidad all por 2010. Hoy estamos viendo como acaba el 2011 y sigue ms vivo que nunca. A pesar de llevar metido en el desarrollo para Android casi desde sus inicios, en mi blog [sgoliver.net] nunca haba tratado estos temas, pretenda mantenerme fiel a su temtica original: el desarrollo bajo las plataformas Java y .NET. Surgieron en algn momento algunos escarceos con otros lenguajes, pero siempre con un ojo puesto en los dos primeros. Mi formacin en Android fue en ingls. No haba alternativa, era el nico idioma en el que, por aquel entonces, exista buena documentacin sobre la plataforma. Desde el primer concepto hasta el ltimo tuve que aprenderlo en el idioma de Shakespeare. A da de hoy esto no ha cambiado mucho, la buena documentacin sobre Android, la buena de verdad, sigue y seguir an durante algn tiempo estando en ingls, pero afortunadamente son ya muchas las personas de habla hispana las que se estn ocupando de ir equilibrando poco a poco esta balanza de idiomas. Y con ese afn de aportar un pequeo granito de arena a la comunidad hispanohablante es como acab decidiendo dar un giro, quien sabe si temporal o permanente, a mi blog y comenzar a escribir sobre desarrollo para la plataforma Android. No saba hasta dnde iba a llegar, no saba la aceptacin que tendra, pero lo que s saba es que me apeteca ayudar un poco a los que como yo les costaba encontrar informacin bsica sobre Android disponible en su idioma. Hoy, gracias a todo vuestro apoyo, vuestra colaboracin, vuestras propuestas, y vuestras crticas (de todo se aprende) ste es un proyecto con ms de un ao ya de vida. Ms de 250 pginas, ms de 40 artculos, y sobre todo cientos de comentarios de nimo recibidos. Y este documento no es un final, es slo un punto y seguido. Este libro es tan solo la mejor forma que he encontrado de mirar atrs, ordenar ideas, y pensar en el siguiente camino a tomar, que espero sea largo. Espero que muchos de vosotros me acompais en parte de ese camino igual que lo habis hecho en el recorrido hasta ahora. Muchas gracias, y que comience el espectculo.

A QUIN VA DIRIGIDO ESTE LIBRO?


Este manual va dirigido a todas aquellas personas interesadas en un tema tan en auge como la programacin de aplicaciones mviles para la plataforma Android. Se tratarn temas dedicados a la construccin de aplicaciones nativas de la plataforma, dejando a un lado por el momento las aplicaciones web. Es por ello por lo que el nico requisito indispensable a la hora de utilizar este manual es tener conocimientos bien asentados sobre el lenguaje de programacin Java y ciertas nociones sobre aspectos bsicos del desarrollo actual como la orientacin a objetos.

LICENCIA
Este documento y todo el cdigo fuente suministrado, al igual que todos los contenidos publicados en el blog sgoliver.net, se publica bajo licencia Creative Commons Reconocimiento NoComercial - SinObraDerivada 3.0 Espaa (CC BY-NC-ND 3.0). Siga el enlace anterior para obtener informacin detallada sobre los trminos de la licencia indicada.

DOCUMENTO DE MUESTRA
Este documento es tan slo un fragmento de muestra del Curso completo de Programacin en Android de sgoliver.net, al que podis acceder de forma gratuita desde la siguiente URL:

http://www.sgoliver.net/blog/?p=1313

III. Widgets
Widgets bsicos
En los dos prximos apartados del curso vamos a describir detalladamente cmo crear un widget de escritorio (home screen widget). En esta primera parte construiremos un widget esttico (no ser interactivo, ni contendr datos actualizables, ni responder a eventos) muy bsico para entender claramente la estructura interna de un componente de este tipo, y en el siguiente apartado completaremos el ejercicio aadiendo una ventana de configuracin inicial para el widget, aadiremos algn dato que podamos actualizar peridicamente, y haremos que responda a pulsaciones del usuario. Como hemos dicho, en esta primera parte vamos a crear un widget muy bsico, consistente en un simple marco rectangular negro con un mensaje de texto predeterminado (Mi Primer Widget). La sencillez del ejemplo nos permitir centrarnos en los pasos principales de la construccin de un widget Android y olvidarnos de otros detalles que nada tienen que ver con el tema que nos ocupa (grficos, datos, ). Para que os hagis una idea, ste ser el aspecto final de nuestro widget de ejemplo:

Los pasos principales para la creacin de un widget Android son los siguientes: 1. Definicin de su interfaz grfica (layout). 2. Configuracin XML del widget (AppWidgetProviderInfo). 3. Implementacin de la funcionalidad del widget (AppWidgetProvider) , especialmente su evento de actualizacin. 4. Declaracin del widget en el Android Manifest de la aplicacin. En el primer paso no nos vamos a detener mucho ya que es anlogo a cualquier definicin de layout de las que hemos visto hasta ahora en el curso. En esta ocasin, la interfaz del widget estar compuesta nicamente por un par de frames (FrameLayout), uno negro exterior y uno blanco interior algo ms pequeo para simular el marco, y una etiqueta de texto (TextView) que albergar el mensaje a mostrar. Veamos cmo queda el layout xml, que para este ejemplo llamaremos miwidget.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dip"> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#000000" android:padding="10dip" > <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#FFFFFF" android:padding="5dip" > <TextView android:id="@+id/txtMensaje" android:layout_width="fill_parent" android:layout_height="fill_parent" android:textColor="#000000" android:text="Mi Primer Widget" /> </FrameLayout> </FrameLayout> </LinearLayout>

Cabe destacar aqu que, debido a que el layout de los widgets de Android est basado en un tipo especial de componentes llamados RemoteViews, no es posible utilizar en su interfaz todos los contenedores y controles que hemos visto en artculos anteriores sino unos pocos bsicos que se indican a continuacin: Contenedores: FrameLayout, LinearLayout y RelativeLayout Controles: Button, ImageButton, ImageView, TextView, ProgressBar, Chronometer y AnalogClock. Aunque la lista de controles soportados no deja de ser curiosa (al menos en mi humilde opinin), debera ser suficiente para crear todo tipo de widgets.

Como segundo paso del proceso de construccin vamos a crear un nuevo fichero XML donde definiremos un conjunto de propiedades del widget, como por ejemplo su tamao en pantalla o su frecuencia de actualizacin. Este XML se deber crear en la carpeta \res\xml de nuestro proyecto. En nuestro caso de ejemplo lo llamaremos miwidget_wprovider.xml y tendr la siguiente estructura:
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/miwidget" android:minWidth="146dip" android:minHeight="72dip" android:label="Mi Primer Widget" android:updatePeriodMillis="3600000" />

Para nuestro widget estamos definiendo las siguientes propiedades: initialLayout: referencia al layout XML que hemos creado en el paso anterior. minWidth: ancho mnimo del widget en pantalla, en dp (density-independent pixels). minHeight: alto mnimo del widget en pantalla, en dp (density-independent pixels). label: nombre del widget que se mostrar en el men de seleccin de Android. updatePeriodMillis: frecuencia de actualizacin del widget, en milisegundos.

Existen varias propiedades ms que se pueden definir. En el siguiente artculo utilizaremos alguna de ellas, el resto se pueden consultar en la documentacin oficial de la clase AppWidgetProviderInfo. Como sabemos, la pantalla inicial de Android se divide en 44 celdas donde se pueden colocar aplicaciones, accesos directos y widgets. Teniendo en cuenta las diferentes dimensiones de estas celdas segn la orientacin de la pantalla, existe una frmula sencilla para ajustar las dimensiones de nuestro widget para que ocupe un nmero determinado de celdas sea cual sea la orientacin: ancho_mnimo = (num_celdas * 74) 2 alto_mnimo = (num_celdas * 74) 2 Atendiendo a esta frmula, si queremos que nuestro widget ocupe un tamao mnimo de 2 celdas de ancho por 1 celda de alto, deberemos indicar unas dimensiones de 146dp x 72dp. Vamos ahora con el tercer paso. ste consiste en implementar la funcionalidad de nuestro widget en su clase java asociada. Esta clase deber heredar de AppWidgetProvider, que a su vez no es ms que una clase auxiliar derivada de BroadcastReceiver, ya que los widgets de Android no son ms que un caso particular de este tipo de componentes.

En esta clase deberemos implementar los mensajes a los que vamos a responder desde nuestro widget, entre los que destacan: onEnabled(): lanzado cuando se aade al escritorio la primera instancia de un widget. onUpdate(): lanzado peridicamente cada vez que se debe actualizar un widget. onDeleted(): lanzado cuando se elimina del escritorio una instancia de un widget. onDisabled(): lanzado cuando se elimina del escritorio la ltima instancia de un widget. En la mayora de los casos, tendremos que implementar como mnimo el evento onUpdate(). El resto de mtodos dependern de la funcionalidad de nuestro widget. En nuestro caso particular no nos har falta ninguno de ellos ya que el widget que estamos creando no contiene ningn dato actualizable, por lo que crearemos la clase, llamada MiWidget, pero dejaremos vaco por el momento el mtodo onUpdate(). En el siguiente apartado veremos qu cosas podemos hacer dentro de estos mtodos.
package net.sgoliver.android; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; public class MiWidget extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { //Actualizar el widget //... } }

El ltimo paso del proceso ser declarar el widget dentro del manifest de nuestra aplicacin. Para ello, editaremos el fichero AndroidManifest.xml para incluir la siguiente declaracin dentro del elemento <application>:
<application> ... <receiver android:name=".MiWidget" android:label="Mi Primer Widget"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/miwidget_wprovider" /> </receiver> </application>

El widget se declarar como un elemento <receiver> y deberemos aportar la siguiente informacin: Atributo name: Referencia a la clase java de nuestro widget, creada en el paso anterior. Elemento <intent-filter>, donde indicaremos los eventos a los que responder nuestro widget, normalmente aadiremos el evento APPWIDGET_UPDATE, para detectar la accin de actualizacin. Elemento <meta-data>, donde haremos referencia con su atributo resource al XML de configuracin que creamos en el segundo paso del proceso. Con esto habramos terminado de escribir los distintos elementos necesarios para hacer funcionar nuestro widget bsico de ejemplo. Para probarlo, podemos ejecutar el proyecto de Eclipse en el emulador de Android, esperar a que se ejecute la aplicacin principal (que estar vaca, ya que no hemos incluido ninguna funcionalidad para ella), ir a la pantalla principal del emulador y aadir nuestro widget al escritorio tal cmo lo haramos en nuestro telfono (pulsacin larga sobre el escritorio o tecla Men, seleccionar la opcin Widgets, y por ltimo seleccionar nuestro Widget). Os dejo una demostracin en video (Nota: se trata de un enlace a YouTube, se necesita conexin a internet para poder visualizarlo). Como podis ver en el video, ya hemos conseguido la funcionalidad bsica de un widget, es posible aadir varias instancias al escritorio, desplazarlos por la pantalla y eliminarlos envindolos a la papelera. En el prximo artculo veremos cmo podemos mejorar este widget aadiendo una pantalla de configuracin inicial, mostraremos algn dato que se actualice peridicamente, y aadiremos la posibilidad de capturar eventos de pulsacin sobre el widget.

El cdigo fuente completo de este artculo est disponible entre los ejemplos suministrados con el manual. Fichero: /Codigo/android-widgets-1.zip

Widgets avanzados
Hemos visto ya cmo construir un widget bsico para Android, y prometimos que dedicaramos un artculo adicional a comentar algunas caractersticas ms avanzadas de este tipo de componentes. Pues bien, en este segundo apartado sobre el tema vamos a ver cmo podemos aadir los siguientes elementos y funcionalidades al widget bsico que ya construimos: Pantalla de configuracin inicial. Datos actualizables de forma peridica. Eventos de usuario. Como sabis, intento simplificar al mximo todos los ejemplos que utilizo en este curso para que podamos centrar nuestra atencin en los aspectos realmente importantes. En esta ocasin utilizar el mismo criterio y las nicas caractersticas (aunque suficientes para demostrar los tres conceptos anteriores) que aadiremos a nuestro widget sern las siguientes: 1. Aadiremos una pantalla de configuracin inicial del widget, que aparecer cada vez que se aada una nueva instancia del widget a nuestro escritorio. En esta pantalla podr configurarse nicamente el mensaje de texto a mostrar en el widget. 2. Aadiremos un nuevo elemento de texto al widget que muestre la hora actual. Esto nos servir para comprobar que el widget se actualiza peridicamente. 3. Aadiremos un botn al widget, que al ser pulsado forzar la actualizacin inmediata del mismo. Empecemos por el primer punto, la pantalla de configuracin inicial del widget. Y procederemos igual que para el diseo de cualquier otra actividad Android, definiendo su layout xml. En nuestro caso ser muy sencilla, un cuadro de texto para introducir el mensaje a personalizar y dos botones, uno para aceptar la configuracin y otro para cancelar (en cuyo caso el widget no se aade al escritorio). En esta ocasin llamaremos a este layout widget_config.xml. Veamos cmo queda:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:id="@+id/LblMensaje" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Mensaje personalizado:" /> <EditText android:id="@+id/TxtMensaje" android:layout_height="wrap_content" android:layout_width="fill_parent" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" >

<Button android:id="@+id/BtnAceptar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Aceptar" /> <Button android:id="@+id/BtnCancelar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Cancelar" /> </LinearLayout> </LinearLayout>

Una vez diseada la interfaz de nuestra actividad de configuracin tendremos que implementar su funcionalidad en java. Llamaremos a la clase WidgetConfig, su estructura ser anloga a la de cualquier actividad de Android, y las acciones a realizar sern las comentadas a continuacin. En primer lugar nos har falta el identificador de la instancia concreta del widget que se configurar con esta actividad. Este ID nos llega como parmetro del intent que ha lanzado la actividad. Como ya vimos en un artculo anterior del curso, este intent se puede recuperar mediante el mtodo getIntent() y sus parmetros mediante el mtodo getExtras(). Conseguida la lista de parmetros del intent, obtendremos el valor del ID del widget accediendo a la clave AppWidgetManager.EXTRA_APPWIDGET_ID. Veamos el cdigo hasta este momento:
public class WidgetConfig extends Activity { private int widgetId = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.widget_config); //Obtenemos el Intent que ha lanzado esta ventana //y recuperamos sus parmetros Intent intentOrigen = getIntent(); Bundle params = intentOrigen.getExtras(); //Obtenemos el ID del widget que se est configurando widgetId = params.getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); //Establecemos el resultado por defecto (si se pulsa el botn 'Atrs' //del telfono ser ste el resultado devuelto). setResult(RESULT_CANCELED); //... } }

En el cdigo tambin podemos ver como aprovechamos este momento para establecer el resultado por defecto a devolver por la actividad de configuracin mediante el mtodo setResult(). Esto es importante porque las actividades de configuracin de widgets deben devolver siempre un resultado (RESULT_OK en caso de aceptarse la configuracin, o RESULT_CANCELED en caso de salir de la configuracin sin aceptar los cambios).

Estableciendo aqu ya un resultado RESULT_CANCELED por defecto nos aseguramos de que si el usuario sale de la configuracin pulsando el botn Atrs del telfono no aadiremos el widget al escritorio, mismo resultado que si pulsramos el botn Cancelar de nuestra actividad. Como siguiente paso recuperamos las referencias a cada uno de los controles de la actividad de configuracin:
//Obtenemos la referencia a los controles de la pantalla final Button btnAceptar = (Button)findViewById(R.id.BtnAceptar); final Button btnCancelar = (Button)findViewById(R.id.BtnCancelar); final EditText txtMensaje = (EditText)findViewById(R.id.TxtMensaje);

Por ltimo, implementaremos las acciones de los botones Aceptar y Cancelar. En principio, el botn Cancelar no tendra por qu hacer nada, tan slo finalizar la actividad mediante una llamada al mtodo finish() ya que el resultado CANCELED ya se ha establecido por defecto anteriormente:
//Implementacin del botn "Cancelar" btnCancelar.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { //Devolvemos como resultado: CANCELAR (RESULT_CANCELED) finish(); } });

En el caso del botn Aceptar tendremos que hacer ms cosas: 1. Guardar de alguna forma el mensaje que ha introducido el usuario. 2. Actualizar manualmente la interfaz del widget segn la configuracin establecida. 3. Devolver el resultado RESULT_OK aportando adems el ID del widget. Para el primer punto nos ayudaremos de la API de Preferencias que describimos en el artculo anterior. En nuestro caso, guardaremos una sola preferencia cuya clave seguir el patrn msg_IdWidget, esto nos permitir distinguir el mensaje configurado para cada instancia del widget que aadamos a nuestro escritorio de Android. El segundo paso indicado es necesario debido a que si definimos una actividad de configuracin para un widget, ser sta la que tenga la responsabilidad de realizar la primera actualizacin del mismo en caso de ser necesario. Es decir, tras salir de la actividad de configuracin no se lanzar automticamente el evento onUpdate() del widget (s se lanzar posteriormente y de forma peridica segn la configuracin del parmetro updatePeriodMillis del provider que veremos ms adelante), sino que tendr que ser la propia actividad quien fuerce la primera actualizacin. Para ello, simplemente obtendremos una referencia al widget manager de nuestro contexto mediente el mtodo AppWidgetManager.getInstance() y con esta referencia llamaremos al mtodo esttico de actualizacin del widget MiWidget.actualizarWidget(), que actualizar los datos de todos los controles del widget (lo veremos un poco ms adelante).

Por ltimo, al resultado a devolver (RESULT_OK) deberemos aadir informacin sobre el ID de nuestro widget. Esto lo conseguimos creando un nuevo Intent que contenga como parmetro el ID del widget que recuperamos antes y establecindolo como resultado de la actividad mediante el mtodo setResult(resultado, intent). Por ltimo llamaremos al mtodo finish() para finalizar la actividad. Con estas indicaciones, veamos cmo quedara el cdigo del botn Aceptar:
//Implementacin del botn "Aceptar" btnAceptar.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { //Guardamos el mensaje personalizado en las preferencias SharedPreferences prefs = getSharedPreferences("WidgetPrefs", Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putString("msg_" + widgetId, txtMensaje.getText().toString()); editor.commit(); //Actualizamos el widget tras la configuracin AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(WidgetConfig.this); MiWidget.actualizarWidget(WidgetConfig.this, appWidgetManager, widgetId); //Devolvemos como resultado: ACEPTAR (RESULT_OK) Intent resultado = new Intent(); resultado.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); setResult(RESULT_OK, resultado); finish(); } });

Ya hemos terminado de implementar nuestra actividad de configuracin. Pero para su correcto funcionamiento an nos quedan dos detalles ms por modificar. En primer lugar tendremos que declarar esta actividad en nuestro fichero AndroidManifest.xml, indicando que debe responder a los mensajes de tipo APPWIDGET_CONFIGURE:
<activity android:name=".WidgetConfig"> <intent-filter> <action android:name="android.apwidget.action.APPWIDGET_CONFIGURE"/> </intent-filter> </activity>

Por ltimo, debemos indicar en el XML de configuracin de nuestro widget (xml\miwidget_wprovider.xml) que al aadir una instancia de este widget debe mostrarse la actividad de configuracin que hemos creado. Esto se consigue estableciendo el atributo android:configure del provider. Aprovecharemos adems este paso para establecer el tiempo de actualizacin automtica del widget al mnimo permitido por este parmetro (30 minutos) y el tamao del widget a 22 celdas. Veamos cmo quedara finalmente:

<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/miwidget" android:minWidth="146dip" android:minHeight="146dip" android:label="Mi Primer Widget" android:updatePeriodMillis="1800000" android:configure="net.sgoliver.android.WidgetConfig" />

Con esto, ya tenemos todo listo para que al aadir nuestro widget al escritorio se muestre automticamente la pantalla de configuracin que hemos construido. Podemos ejecutar el proyecto en este punto y comprobar que todo funciona correctamente. Como siguiente paso vamos a modificar el layout del widget que ya construimos en el artculo anterior para aadir una nueva etiqueta de texto donde mostraremos la hora actual, y un botn que nos servir para forzar la actualizacin de los datos del widget:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dip"> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#000000" android:padding="10dip" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#FFFFFF" android:padding="5dip" android:orientation="vertical"> <TextView android:id="@+id/LblMensaje" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#000000" android:text="mensaje" /> <TextView android:id="@+id/LblHora" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#000000" android:text="hora_actual" /> <Button android:id="@+id/BtnActualizar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Actualizar" /> </LinearLayout> </FrameLayout> </LinearLayout>

Hecho esto, tendremos que modificar la implementacin de nuestro provider (MiWidget.java) para que en cada actualizacin del widget se actualicen sus controles con los datos correctos (recordemos que en el artculo anterior dejamos este evento de actualizacin vaco ya que no mostrbamos datos actualizables en el widget). Esto lo haremos dentro del evento onUpdate() de nuestro provider. Como ya dijimos, los componentes de un widget se basan en un tipo especial de vistas que llamamos Remote Views. Pues bien, para acceder a la lista de estos componentes que constituyen la interfaz del widget construiremos un nuevo objeto RemoteViews a partir del ID del layout de cada widget. Obtenida la lista de componentes, tendremos disponibles una serie de mtodos set (uno para cada tipo de datos bsicos) para establecer las propiedades de cada control del widget. Estos mtodos reciben como parmetros el ID del control, el nombre del mtodo que queremos ejecutar sobre el control, y el valor a establecer. Adems de estos mtodos, contamos adicionalmente con una serie de mtodos ms especficos para establecer directamente el texto y otras propiedades sencillas de los controles TextView, ImageView, ProgressBar y Chronometer, como por ejemplo setTextViewText(idControl, valor) para establecer el texto de un control TextView. Pueden consultarse todos los mtodos disponibles en la documentacin oficial de la clase RemoteViews. De esta forma, si por ejemplo queremos establecer el texto del control cuyo id es LblMensaje haramos lo siguiente:
RemoteViews controles = new RemoteViews(context.getPackageName(), R.layout.miwidget); controles.setTextViewText(R.id.LblMensaje, "Mensaje de prueba");

El proceso de actualizacin habr que realizarlo por supuesto para todas las instancias del widget que se hayan aadido al escritorio. Recordemos aqu que el evento onUpdate() recibe como parmetro la lista de widgets que hay que actualizar. Dicho esto, creo que ya podemos mostrar cmo quedara el cdigo de actualizacin de nuestro widget:
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { //Iteramos la lista de widgets en ejecucin for (int i = 0; i < appWidgetIds.length; i++) { //ID del widget actual int widgetId = appWidgetIds[i]; //Actualizamos el widget actual actualizarWidget(context, appWidgetManager, widgetId); } } public static void actualizarWidget(Context context, AppWidgetManager appWidgetManager, int widgetId) { //Recuperamos el mensaje personalizado para el widget actual SharedPreferences prefs =

context.getSharedPreferences("WidgetPrefs", Context.MODE_PRIVATE); String mensaje = prefs.getString("msg_" + widgetId, "Hora actual:"); //Obtenemos la lista de controles del widget actual RemoteViews controles = new RemoteViews(context.getPackageName(), R.layout.miwidget); //Actualizamos el mensaje en el control del widget controles.setTextViewText(R.id.LblMsg, mensaje); //Obtenemos la hora actual Calendar calendario = new GregorianCalendar(); String hora = calendario.getTime().toLocaleString(); //Actualizamos la hora en el control del widget controles.setTextViewText(R.id.LblHora, hora); //Notificamos al manager de la actualizacin del widget actual appWidgetManager.updateAppWidget(widgetId, controles); }

Como vemos, todo el trabajo de actualizacin para un widget lo hemos extrado a un mtodo esttico independiente, de forma que tambin podamos llamarlo desde otras partes de la aplicacin (como hacemos por ejemplo desde la actividad de configuracin para forzar la primera actualizacin del widget). Adems quiero destacar la ltima lnea del cdigo, donde llamamos al mtodo updateAppWidget() del widget manager. Esto es importante y necesario, ya que de no hacerlo la actualizacin de los controles no se reflejar correctamente en la interfaz del widget. Tras esto, ya slo nos queda implementar la funcionalidad del nuevo botn que hemos incluido en el widget para poder forzar la actualizacin del mismo. A los controles utilizados en los widgets de Android, que ya sabemos que son del tipo RemoteView, no podemos asociar eventos de la forma tradicional que hemos visto en mltiples ocasiones durante el curso. Sin embargo, en su lugar, tenemos la posibilidad de asociar a un evento (por ejemplo, el click sobre un botn) un determinado mensaje (Pending Intent) de tipo broadcast que ser lanzado cada vez que se produzca dicho evento. Adems, podremos configurar el widget (que como ya indicamos no es ms que un componente de tipo broadcast receiver) para que capture esos mensajes, e implementar en el evento onReceive() del widget las acciones necesarias a ejecutar tras capturar el mensaje. Con estas tres acciones simularemos la captura de eventos sobre controles de un widget. Vamos por partes. En primer lugar hagamos que se lance un intent broadcast cada vez que se pulse el botn del widget. Para ello, en el mtodo actualizarWidget() construiremos un nuevo Intent asocindole una accin personalizada, que en nuestro caso llamaremos por ejemplo net.sgoliver.ACTUALIZAR_WIDGET. Como parmetro del nuevo Intent insertaremos mediante putExtra() el ID del widget actual de forma que ms tarde podamos saber el widget concreto que ha lanzado el mensaje. Por ltimo crearemos el PendingIntent mediante el mtodo getBroadcast() y lo asociaremos al evento onClick del control llamando a setOnClickPendingIntent() pasndole el ID del control, en nuestro caso el botn de Actualizar. Veamos cmo queda todo esto:

//Asociamos los 'eventos' al widget Intent intent = new Intent("net.sgoliver.ACTUALIZAR_WIDGET"); intent.putExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, widgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT); controles.setOnClickPendingIntent(R.id.BtnActualizar, pendingIntent);

Ahora vamos a declarar en el Android Manifest este mensaje personalizado, de forma que el widget sea capaz de capturarlo. Para ello, aadiremos simplemente un nuevo elemento <intent-filter> con nuestro nombre de accin personalizado:
<intent-filter> <action android:name="net.sgoliver.ACTUALIZAR_WIDGET"/> </intent-filter>

Por ltimo, vamos a implementar el evento onReceive() del widget para actuar en caso de recibir nuestro mensaje de actualizacin personalizado. Dentro de este evento comprobaremos si la accin del mensaje recibido es la nuestra, y en ese caso recuperaremos el ID del widget que lo ha lanzado, obtendremos una referencia al widget manager, y por ltimo llamaremos nuestro mtodo esttico de actualizacin pasndole estos datos.
@Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("net.sgoliver.ACTUALIZAR_WIDGET")) { //Obtenemos el ID del widget a actualizar int widgetId = intent.getIntExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); //Obtenemos el widget manager de nuestro contexto AppWidgetManager widgetManager = AppWidgetManager.getInstance(context); //Actualizamos el widget if (widgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { actualizarWidget(context, widgetManager, widgetId); } }

Con esto, por fin, hemos ya finalizado la construccin de nuestro widget android y podemos ejecutar el proyecto de Eclipse para comprobar que todo funciona correctamente, tanto para una sola instancia como para varias instancias simultaneas. Un comentario final, la actualizacin automtica del widget se ha establecido a la frecuencia mnima que permite el atributo updatePeriodMillis del widget provider, que son 30 minutos. Por tanto es difcil y aburrido esperar para verla en funcionamiento mientras probamos el widget en el emulador. Pero funciona, os lo aseguro. De cualquier forma, esos 30 minutos pueden ser un periodo demasiado largo de tiempo segn la funcionalidad que queramos dar a nuestro widget, que puede requerir tiempos de actualizacin mucho ms cortos (ojo con el rendimiento y el gasto de batera). Ms adelante, cuando hablemos de Alarmas, veremos una tcnica que nos permitir actualizar los widgets sin esa limitacin de 30

minutos. Hasta entonces, espero que el tema os sea de utilidad y que os haya parecido interesante.

El cdigo fuente completo de este artculo est disponible entre los ejemplos suministrados con el manual. Fichero: /Codigo/android-widgets-2.zip

DOCUMENTO DE MUESTRA
Este documento es tan slo un fragmento de muestra del Curso completo de Programacin en Android de sgoliver.net, al que podis acceder de forma gratuita desde la siguiente URL:

http://www.sgoliver.net/blog/?p=1313

VII. Preferencias en Android


Preferencias Compartidas
En este apartado vamos hablar de un tema que nos ser de ayuda ms adelante para la construccin de cualquier tipo de aplicacin Android. Este tema es la administracin de preferencias. Las preferencias no son ms que datos que una aplicacin debe guardar para personalizar la experiencia del usuario, por ejemplo informacin personal, opciones de presentacin, etc. En artculos anteriores vimos ya uno de los mtodos disponibles en la plataforma Android para almacenar datos, como son las bases de datos SQLite. Las preferencias de una aplicacin se podran almacenar por su puesto utilizando este mtodo, y no tendra nada de malo, pero Android proporciona otro mtodo alternativo diseado especficamente para administrar este tipo de datos: las preferencias compartidas o shared preferences. Cada preferencia se almacenar en forma de clave-valor, es decir, cada una de ellas estar compuesta por un identificador nico (p.e. email) y un valor asociado a dicho identificador (p.e. prueba@email.com). Adems, y a diferencia de SQLite, los datos no se guardan en un fichero de binario de base de datos, sino en ficheros XML como veremos al final de este artculo. La API para el manejo de estas preferencias es muy sencilla. Toda la gestin se centraliza en la clase SharedPrefences, que representar a una coleccin de preferencias. Una aplicacin Android puede gestionar varias colecciones de preferencias, que se diferenciarn mediante un identificador nico. Para obtener una referencia a una coleccin determinada utilizaremos el mtodo getSharedPrefences() al que pasaremos el identificador de la coleccin y un modo de acceso. El modo de acceso indicar qu aplicaciones tendrn acceso a la coleccin de preferencias y qu operaciones tendrn permitido realizar sobre ellas. As, tendremos tres posibilidades principales: MODE_PRIVATE. Slo nuestra aplicacin tiene acceso a estas preferencias. MODE_WORLD_READABLE. Todas las aplicaciones pueden leer estas preferencias, pero slo la nuestra modificarlas. MODE_WORLD_WRITABLE. Todas las aplicaciones pueden leer y modificar estas preferencias. Teniendo todo esto en cuenta, para obtener una referencia a una coleccin de preferencias llamada por ejemplo MisPreferencias y como modo de acceso exclusivo para nuestra aplicacin haramos lo siguiente:
SharedPreferences prefs = getSharedPreferences("MisPreferencias",Context.MODE_PRIVATE);

Una vez hemos obtenido una referencia a nuestra coleccin de preferencias, ya podemos obtener, insertar o modificar preferencias utilizando los mtodos get o put correspondientes al tipo de dato de cada preferencia. As, por ejemplo, para obtener el valor de una preferencia llamada email de tipo String escribiramos lo siguiente:
SharedPreferences prefs = getSharedPreferences("MisPreferencias",Context.MODE_PRIVATE); String correo = prefs.getString("email", "por_defecto@email.com");

Como vemos, al mtodo getString() le pasamos el nombre de la preferencia que queremos recuperar y un segundo parmetro con un valor por defecto. Este valor por defecto ser el devuelto por el mtodo getString() si la preferencia solicitada no existe en la coleccin. Adems del mtodo getString(), existen por supuesto mtodos anlogos para el resto de tipos de datos bsicos, por ejemplo getInt(), getLong(), getFloat(), getBoolean(), Para actualizar o insertar nuevas preferencias el proceso ser igual de sencillo, con la nica diferencia de que la actualizacin o insercin no la haremos directamente sobre el objeto SharedPreferences, sino sobre su objeto de edicin SharedPreferences.Editor. A este ltimo objeto accedemos mediante el mtodo edit() de la clase SharedPreferences. Una vez obtenida la referencia al editor, utilizaremos los mtodos put correspondientes al tipo de datos de cada preferencia para actualizar/insertar su valor, por ejemplo putString(clave, valor), para actualizar una preferencia de tipo String. De forma anloga a los mtodos get que ya hemos visto, tendremos disponibles mtodos put para todos los tipos de datos bsicos: putInt(), putFloat(), putBoolean(), etc. Finalmente, una vez actualizados/insertados todos los datos necesarios llamaremos al mtodo commit() para confirmar los cambios. Veamos un ejemplo sencillo:
SharedPreferences prefs = getSharedPreferences("MisPreferencias",Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putString("email", "modificado@email.com"); editor.putString("nombre", "Prueba"); editor.commit();

Dnde se almacenan estas preferencias compartidas? Como dijimos al comienzo del artculo, las preferencias no se almacenan en ficheros binarios como las bases de datos SQLite, sino en ficheros XML. Estos ficheros XML se almacenan en una ruta con el siguiente patrn: /data/data/paquetejava/shared_prefs/nombre_coleccion.xml As, por ejemplo, en nuestro caso encontraramos nuestro fichero de preferencias en la ruta: /data/data/net.sgoliver.android/shared_prefs/MisPreferencias.xml

Si descargamos este fichero desde el DDMS y lo abrimos con cualquier editor de texto veremos un contenido como el siguiente:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="nombre">prueba</string> <string name="email">modificado@email.com</string> </map>

En este XML podemos observar cmo se han almacenado las dos preferencias de ejemplo que insertamos anteriormente, con sus claves y valores correspondientes. Y nada ms, as de fcil y prctico. Con esto hemos aprendido una forma sencilla de almacenar determinadas opciones de nuestra aplicacin sin tener que recurrir para ello a definir bases de datos SQLite, que aunque tampoco aaden mucha dificultad s que requieren algo ms de trabajo por nuestra parte. En una segunda parte de este tema dedicado a las preferencias veremos cmo Android nos ofrece otra forma de gestionar estos datos, que se integra adems fcilmente con la interfaz grfica necesaria para solicitar los datos al usuario.

Pantallas de Preferencias
Hemos dedicado el apartado anterior a las preferencias compartidas (shared preferences), un mecanismo que nos permite gestionar fcilmente las opciones de una aplicacin permitindonos guardarlas en XML de una forma transparente para el programador. Sin embargo, slo hemos visto cmo hacer uso de ellas mediante cdigo, es decir, creando nosotros mismos los objetos necesarios (SharedPreferences) y aadiendo, modificando y/o recuperando a mano los valores de las opciones a travs de los mtodos correspondientes (getString(), putString(), ). Pero ya avisamos de que Android ofrece una forma alternativa de definir mediante XML un conjunto de opciones para una aplicacin y crear por nosotros las pantallas necesarias para permitir al usuario modificarlas a su antojo. A esto dedicaremos este segundo apartado sobre preferencias. Si nos fijamos en cualquier pantalla de preferencias estndar de Android veremos que todas comparten una interfaz comn, similar por ejemplo a la que se muestra en la imagen siguiente (correspondiente a la pantalla de opciones de la galera de imgenes de Android).

Si observamos la imagen anterior vemos cmo las diferentes opciones se organizan dentro de la pantalla de opciones en varias categoras (General Settings y Slideshow Settings). Dentro de cada categora pueden aparecer varias opciones de diversos tipos, como por ejemplo de tipo checkbox (Confirm deletions) o de tipo lista de seleccin (Display size). He resaltado las palabras pantalla de opciones, categoras, y tipos de opcin porque sern estos los tres elementos principales con los que vamos a definir el conjunto de opciones o preferencias de nuestra aplicacin. Empecemos. Como hemos indicado, nuestra pantalla de opciones la vamos a definir mediante un XML, de forma similar a como definimos cualquier layout, aunque en este caso deberemos colocarlo en la carpeta /res/xml. El contenedor principal de nuestra pantalla de preferencias ser el elemento <PreferenceScreen>. Este elemento representar a la pantalla de opciones en s, dentro de la cual incluiremos el resto de elementos. Dentro de ste podremos incluir nuestra lista de opciones organizadas por categoras, que se representar mediante el elemento <PreferenceCategory> al que daremos un texto descriptivo utilizando su atributo android:title.

Dentro de cada categora podremos aadir cualquier nmero de opciones, las cuales pueden ser de distintos tipos, entre los que destacan: Tipo CheckBoxPreference EditTextPreference ListPreference MultiSelectListPreference Descripcin Marca seleccionable. Cadena simple de texto. Lista de valores seleccionables (exclusiva). Lista de valores seleccionables (mltiple).

Cada uno de estos tipos de preferencia requiere la definicin de diferentes atributos, que iremos viendo en los siguientes apartados. CheckBoxPreference Representa un tipo de opcin que slo puede tomar dos valores distintos: activada o desactivada. Es el equivalente a un control de tipo checkbox. En este caso tan slo tendremos que especificar los atributos: nombre interno de la opcin (android:key), texto a mostrar (android:title) y descripcin de la opcin (android:summary). Veamos un ejemplo:
<CheckBoxPreference android:key="opcion1" android:title="Preferencia 1" android:summary="Descripcin de la preferencia 1" />

EditTextPreference Representa un tipo de opcin que puede contener como valor una cadena de texto. Al pulsar sobre una opcin de este tipo se mostrar un cuadro de dilogo sencillo que solicitar al usuario el texto a almacenar. Para este tipo, adems de los tres atributos comunes a todas las opciones (key, title y summary) tambin tendremos que indicar el texto a mostrar en el cuadro de dilogo, mediante el atributo android:dialogTitle. Un ejemplo sera el siguiente:
<EditTextPreference android:key="opcion2" android:title="Preferencia 2" android:summary="Descripcin de la preferencia 2" android:dialogTitle="Introduce valor" />

ListPreference Representa un tipo de opcin que puede tomar como valor un elemento, y slo uno, seleccionado por el usuario entre una lista de valores predefinida. Al pulsar sobre una opcin de este tipo se mostrar la lista de valores posibles y el usuario podr seleccionar uno de ellos. Y en este caso seguimos aadiendo atributos. Adems de los cuatro ya comentados (key, title, summary y dialogTitle) tendremos que aadir dos ms, uno de ellos indicando la lista de valores a visualizar en la lista y el otro indicando los valores internos que

utilizaremos para cada uno de los valores de la lista anterior (Ejemplo: al usuario podemos mostrar una lista con los valores Espaol y Francs, pero internamente almacenarlos como ESP y FRA). Estas listas de valores las definiremos tambin como ficheros XML dentro de la carpeta /res/xml. Definiremos para ello los recursos de tipos <string-array> necesarios, en este caso dos, uno para la lista de valores visibles y otro para la lista de valores internos, cada uno de ellos con su ID nico correspondiente. Veamos cmo quedaran dos listas de ejemplo, en un fichero llamado codigospaises.xml:
<?xml version="1.0" encoding="utf-8" ?> <resources> <string-array name="pais"> <item>Espaa</item> <item>Francia</item> <item>Alemania</item> </string-array> <string-array name="codigopais"> <item>ESP</item> <item>FRA</item> <item>ALE</item> </string-array> </resources>

En la preferencia utilizaremos los atributos android:entries y android:entryValues para hacer referencia a estas listas, como vemos en el ejemplo siguiente:
<ListPreference android:key="opcion3" android:title="Preferencia 3" android:summary="Descripcin de la preferencia 3" android:dialogTitle="Indicar Pais" android:entries="@array/pais" android:entryValues="@array/codigopais" />

MultiSelectListPreference [A partir de Android 3.0.x / Honeycomb] Las opciones de este tipo son muy similares a las ListPreference, con la diferencia de que el usuario puede seleccionar varias de las opciones de la lista de posibles valores. Los atributos a asignar son por tanto los mismos que para el tipo anterior.
<MultiSelectListPreference android:key="opcion4" android:title="Preferencia 4" android:summary="Descripcin de la preferencia 4" android:dialogTitle="Indicar Pais" android:entries="@array/pais" android:entryValues="@array/codigopais" />

Como ejemplo completo, veamos cmo quedara definida una pantalla de opciones con las 3 primeras opciones comentadas (ya que probar con Android 2.2), divididas en 2 categoras

llamadas por simplicidad Categora 1 y Categora 2. Llamaremos al fichero opciones.xml.


<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="Categora 1"> <CheckBoxPreference android:key="opcion1" android:title="Preferencia 1" android:summary="Descripcin de la preferencia 1" /> <EditTextPreference android:key="opcion2" android:title="Preferencia 2" android:summary="Descripcin de la preferencia 2" android:dialogTitle="Introduce valor" /> </PreferenceCategory> <PreferenceCategory android:title="Categora 2"> <ListPreference android:key="opcion3" android:title="Preferencia 3" android:summary="Descripcin de la preferencia 3" android:dialogTitle="Indicar Pais" android:entries="@array/pais" android:entryValues="@array/codigopais" /> </PreferenceCategory> </PreferenceScreen>

Ya tenemos definida la estructura de nuestra pantalla de opciones, pero an nos queda un paso ms para poder hacer uso de ella desde nuestra aplicacin. Adems de la definicin XML de la lista de opciones, debemos implementar una nueva actividad, que ser a la que hagamos referencia cuando queramos mostrar nuestra pantalla de opciones y la que se encargar internamente de gestionar todas las opciones, guardarlas, modificarlas, etc, a partir de nuestra definicin XML. Android nos facilita las cosas ofrecindonos una clase de la que podemos derivar fcilmente la nuestra propia y que hace todo el trabajo por nosotros. Esta clase se llama PreferenceActivity. Tan slo deberemos crear una nueva actividad (yo la he llamado PantallaOpciones) que extienda a esta clase e implementar su evento onCreate() para aadir una llamada al mtodo addPreferencesFromResource(), mediante el que indicaremos el fichero XML en el que hemos definido la pantalla de opciones. Lo vemos mejor directamente en el cdigo:
public class PantallaOpciones extends PreferenceActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.opciones); } }

As de sencillo, nuestra nueva actividad, al extender a PreferenceActivity, se encargar por nosotros de crear la interfaz grfica de nuestra lista de opciones segn la hemos definido en el XML y se preocupar por nosotros de mostrar, modificar y guardar las opciones cuando sea necesario tras la accin del usuario.

Por supuesto, tendremos que aadir esta actividad al fichero AndroidManifest.xml, al igual que cualquier otra actividad que utilicemos en la aplicacin.
<activity android:name=".PantallaOpciones" android:label="@string/app_name"> </activity>

Ya slo nos queda aadir a nuestra aplicacin algn mecanismo para mostrar la pantalla de preferencias. Esta opcin suele estar en un men, pero por simplificar el ejemplo vamos a aadir simplemente un botn (btnPreferencias) que llame a la ventana de preferencias. Al pulsar este botn llamaremos a la ventana de preferencias mediante el mtodo startActivity(), como ya hemos visto en alguna ocasin, al que pasaremos como parmetros el contexto de la aplicacin (nos vale con nuestra actividad principal) y la clase de la ventana de preferencias (PantallaOpciones.class).
btnPreferencias = (Button)findViewById(R.id.BtnPreferencias); btnPreferencias.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(AndroidPrefScreensActivity.this, PantallaOpciones.class)); } });

Y esto es todo, ya slo nos queda ejecutar la aplicacin en el emulador y pulsar el botn de preferencias para mostrar nuestra nueva pantalla de opciones. Debe quedar como muestra la imagen siguiente:

La primera opcin podemos marcarla o desmarcarla directamente pulsando sobre la check de su derecha. La segunda, de tipo texto, nos mostrar al pulsarla un pequeo formulario para solicitar el valor de la opcin.

Por ltimo, la opcin 3 de tipo lista, nos mostrar una ventana emergente con la lista de valores posibles, donde podremos seleccionar slo uno de ellos.

Una vez establecidos los valores de las preferencias podemos salir de la ventana de opciones simplemente pulsando el botn Atrs del dispositivo o del emulador. Nuestra actividad PantallaOpciones se habr ocupado por nosotros de guardar correctamente los valores de las opciones haciendo uso de la API de preferencias compartidas (Shared Preferences). Y para comprobarlo vamos a aadir otro botn (btnObtenerOpciones) a la aplicacin de ejemplo que recupere el valor actual de las 3 preferencias y los escriba al log de la aplicacin. La forma de acceder a las preferencias compartidas de la aplicacin ya la vimos en el artculo anterior sobre este tema. Obtenemos la lista de preferencias mediante el mtodo getDefaultSharedPreferences() y posteriormente utilizamos los distintos mtodos get() para recuperar el valor de cada opcin dependiendo de su tipo.
btnObtenerPreferencias.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences( AndroidPrefScreensActivity.this); Log.i("", "Opcin 1: " + pref.getBoolean("opcion1", false)); Log.i("", "Opcin 2: " + pref.getString("opcion2", "")); Log.i("", "Opcin 3: " + pref.getString("opcion3", "")); } });

Si ejecutamos ahora la aplicacin, establecemos las preferencias y pulsamos el nuevo botn de consulta que hemos creado veremos cmo en el log de la aplicacin aparecen los valores correctos de cada preferencia. Se mostrara algo como lo siguiente:
10-08 09:27:09.681: INFO/(1162): Opcin 1: true 10-08 09:27:09.681: INFO/(1162): Opcin 2: prueba 10-08 09:27:09.693: INFO/(1162): Opcin 3: FRA

Y hasta aqu hemos llegado con el tema de las preferencias, un tema muy interesante de controlar ya que casi ninguna aplicacin se libra de hacer uso de ellas.

El cdigo fuente completo de este artculo est disponible entre los ejemplos suministrados con el manual. Fichero: /Codigo/android-pref-activity.zip

DOCUMENTO DE MUESTRA
Este documento es tan slo un fragmento de muestra del Curso completo de Programacin en Android de sgoliver.net, al que podis acceder de forma gratuita desde la siguiente URL:

http://www.sgoliver.net/blog/?p=1313

Vous aimerez peut-être aussi