You are on page 1of 269

1

1. Informacin ... ... ... ... ... 4

2. Prlogo ... ... ... ... ... 5


2.1 Introduccin ... ... ... ... 6
2.2 A quin se dirige este libro? ... ... ... 7
2.3 Conocimientos previos necesarios para abordar este libro ... 8
2.4 Objetivos a alcanzar... ... ... ... 9
2.5 Descarga ... ... ... ... 10
2.6 Informacin complementaria ... ... ... 11
2.7 Recursos ... ... ... ... 12

3. El universo Android ... ... ... ... 13


3.1 Introduccin ... ... ... ... 14
3.2 Presentacin de Android ... ... ... 15
3.3 Entorno de desarrollo ... ... ... 20

4. Primeros pasos ... ... ... ... 37


4.1 Primer proyecto Android ... ... ... 38
4.2 Estructura de un proyecto Android ... ... ... 52

5. Descubrir la interfaz de usuario ... ... ... 58


5.1 Introduccin ... ... ... ... 59
5.2 Pantallas ... ... ... ... 60
5.3 Modo programtico y modo declarativo ... ... 63
5.4 Vistas ... ... ... ... 65
5.5 Layouts ... ... ... ... 67
5.6 Widgets ... ... ... ... 71

6. Los fundamentos ... ... ... ... 76


6.1 Introduccin ... ... ... ... 77
6.2 Intencin ... ... ... ... 78
6.3 Actividad ... ... ... ... 84

7. Completar la interfaz de usuario ... ... ... 94


7.1 Introduccin ... ... ... ... 95
7.2 Estilos y temas ... ... ... ... 96
7.3 Mens ... ... ... ... 97
7.4 Barra de accin ... ... ... ... 103
7.5 Notificaciones ... ... ... ... 105
7.6 Internacionalizacin ... ... ... 113

8. Componentes principales de la aplicacin ... ... ... 115


8.1 Introduccin ... ... ... ... 116
8.2 Fragmento ... ... ... ... 117
8.3 Servicio ... ... ... ... 124
8.4 Receptor de eventos ... ... ... 129
8.5 Lista ... ... ... ... 132

2
9. La persistencia de los datos ... ... ... ... 134
9.1 Introduccin ... ... ... ... 135
9.2 Archivos de preferencias ... ... ... 136
9.3 Archivos ... ... ... ... 140
9.4 Bases de datos SQLite ... ... ... 146
9.5 Proveedor de contenidos ... ... ... 149
9.6 Copia de seguridad en la nube ... ... ... 153

10. Concurrencia, seguridad y red ... ... ... 160


10.1 Introduccin ... ... ... ... 161
10.2 Procesos ... ... ... ... 162
10.3 Programacin concurrente ... ... ... 165
10.4 Seguridad y permisos ... ... ... 170
10.5 Red ... ... ... ... 173

11. Trazas, depuracin y pruebas ... ... ... 178


11.1 Introduccin ... ... ... ... 179
11.2 Registro de eventos ... ... ... 180
11.3 Depuracin ... ... ... ... 184
11.4 Pruebas unitarias y funcionales ... ... ... 194
11.5 Pruebas del mono ... ... ... ... 205

12. Publicar una aplicacin ... ... ... ... 207


12.1 Introduccin ... ... ... ... 208
12.2 Preliminares ... ... ... ... 209
12.3 Firma digital de la aplicacin ... ... ... 213
12.4 Publicacin de la aplicacin en el Android Market ... ... 219

13. Mapas y localizacin geogrfica ... ... ... 232


13.1 Introduccin ... ... ... ... 233
13.2 Localizacin geogrfica ... ... ... 234
13.3 Google Maps ... ... ... ... 240

14. Funcionalidades avanzadas ... ... ... ... 248


14.1 Introduccin ... ... ... ... 249
14.2 App Widget ... ... ... ... 250
14.3 Proteger las aplicaciones de pago ... ... ... 258

3
Android
Gua de desarrollo de aplicaciones para Smartphones y Tabletas

Verdadera gua de aprendizaje, este libro se propone dirigir al lector en el desarrollo


de aplicaciones Android para Smartphones y Tabletas tctiles. Est dirigido a aquellos
desarrolladores que cuenten con un mnimo de conocimientos sobre programacin orientada a
objetos, el lenguaje Java y el entorno de desarrollo integrado Eclipse y cubre todas las versiones
de Android, incluida la 3.

El libro presenta el proceso completo de creacin de aplicaciones, desde lapreparacin del


entorno de desarrollo hasta la publicacin de la aplicacin, y describe una gran seleccin de
funcionalidades provistas por el sistema Android.

A lo largo de este libro descubrir, en primer lugar, la plataforma Android, instalar el entorno de
desarrollo y crear, sin esperar ms, su primera aplicacin Android. Estudiar, a continuacin,
cmo construir la interfaz de usuario y conocer los componentes fundamentales de la
aplicacin como el Fragmento. A continuacin, se presentarn la persistencia de los datos,
la programacin concurrente, la seguridad y la comunicacin de red.

Para poder publicar aplicaciones con la mayor calidad posible, descubrir cmo agregar
trazas y probar su aplicacin. Por ltimo, ser guiado, paso a paso, para publicar sus
aplicaciones a usuarios del mundo entero.

La obra finaliza presentando la determinacin de la localizacin geogrfica, asuntos avanzados


tales como la creacin de AppWidget y laproteccin de aplicaciones de pago (LVL). Tras su
lectura, ser capaz de desarrollar y publicar aplicaciones nativas Android (en distintas versiones,
hasta la versin 3 inclusive) para Smartphones y Tabletas tctiles.

Por ltimo, como complemento y para ilustrar de forma prctica el propsito de la obra, los
proyectos completos y funcionales estn disponibles para su descarga en la pgina
Informacin.

Los captulos del libro:


Prlogo El universo Android Primeros pasos Descubrir la interfaz de usuario Los
fundamentos Completar la interfaz de usuario Componentes principales de la aplicacin La
persistencia de los datos Concurrencia, seguridad y red Trazas, depuracin y pruebas
Publicar una aplicacin Mapas y localizacin geogrfica Funcionalidades avanzadas

Sbastien PROCHON
Sbastien PROCHON es el fundador de Mobiquit, empresa especializada en el desarrollo y la
formacin a desarrolladores de aplicaciones mviles (Android, iPhone, iPad). Una de sus
aplicaciones principales ha sido descargada ms de 1.000.000 de veces en un ao. Tras diez
aos de experiencia en el desarrollo de software, la gestin de proyectos y de equipos,
Sbastien Prochon est tambin muy implicado en las comunidades de desarrollo sobre Android,
y es organizador del Poitou-Charentes Android User Group. A travs de esta obra, consigue que
el lector disfrute de una experiencia muy rica acerca del desarrollo de aplicaciones mviles y le
proporciona las claves para iniciarse en este prometedor mercado.

4
2. Prlogo

5
Introduccin
Son pocos los sistemas que han conocido una progresin tan brillante como la que recientemente ha
conocido el sistema Android.

Hace todava poco tiempo, el sistema Android slo estaba presente en smartphones. Ms tarde, era
posible encontrarlo tambin en televisores con conexin a Internet. En la actualidad, ha invadido el
mercado de los Tablet PC y dispositivos tctiles con la aparicin de la versin 3.

Muchos son los motivos de este xito. Uno de ellos es, sin duda, la amplia oferta de aplicaciones
disponibles para su descarga, varios cientos de miles, que permiten a cualquiera personalizar su
dispositivo Android.

Para que el lector pueda formar parte de este xito, este libro pretende acompaarle durante sus
primeros pasos en el desarrollo de aplicaciones nativas Android que podr publicar a continuacin y,
eventualmente, vender a usuarios de todo el mundo.

6
2.2 A quin se dirige este libro?
Este libro est dirigido a todo aqul que se interese en mayor o menor medida por el universo Android
y que desee ir ms all descubriendo cmo crear sus propias aplicaciones nativas Android.

7
2.3 Conocimientos previos necesarios para abordar este libro
El propsito de este libro es el desarrollo de aplicaciones Android en lenguaje Java dentro del entorno
de desarrollo integrado Eclipse.

En particular, este libro se centra nicamente en el desarrollo de aplicaciones propias de Android.

Esto supone que se trata de un lector que posee conocimientos previos en programacin orientada a
objetos, particularmente en Java, y conocimientos previos en el uso del entorno de desarrollo
integrado Eclipse.

Es por ello que no se ha considerado oportuno retomar por ensima vez el estudio del lenguaje en
este libro para, as, concentrarse nicamente en la parte especfica a Android.

La escritura de aplicaciones Android no requiere, para comenzar, un nivel elevado en Java. Basta con
que el lector posea algunos conocimientos bsicos sobre Java para recorrer este libro sin problema
alguno y, sobretodo, para realizar sus propias aplicaciones Android.

En lo que respecta al uso del entorno de desarrollo integrado Eclipse, algunos conocimientos bsicos
son ms que suficientes.

8
Objetivos a alcanzar
Este libro tiene como objetivo orientar al lector en sus primeros pasos en el desarrollo de aplicaciones
Android y guiarle hacia funcionalidades ms avanzadas.

Gracias a este libro, el lector, usuario de Android, se convertir en diseador de aplicaciones Android.
Descubrir los fundamentos del sistema Android y las bases del desarrollo de aplicaciones Android
para smartphones y tabletas tctiles hasta la versin 3 incluida. Desde este momento, el lector podr
publicar sus propias aplicaciones Android de modo que estn disponibles para usuarios de todo el
mundo.

Para ello, tras la presentacin de la plataforma Android, el lector descubrir cmo implantar un
entorno de desarrollo para crear y ejecutar su primer proyecto Android. Le seguir un primer estudio
de la interfaz de usuario y de dos componentes principales como son las intenciones y las actividades.
Un estudio complementario de la interfaz de usuario desvelar los elementos ms importantes que
pueden utilizar las aplicaciones.

A continuacin, se abordarn otros componentes principales tales como los fragmentos y los servicios.
Posteriormente se describirn varias soluciones de persistencia de datos. Despus, el lector
descubrir la implementacin de la programacin concurrente en Android, la gestin de la seguridad y
la comunicacin de red.

Se detallarn a continuacin los medios para trazar, depurar y probar las aplicaciones. El lector
descubrir cmo publicar una aplicacin, especialmente en el Android Market.

Por ltimo, este libro terminar con el estudio de los medios de localizacin geogrfica y de
funcionalidades avanzadas tales como la creacin de un App Widget y la proteccin de aplicaciones de
pago.

9
2.5 Descarga
Los ejemplos de cdigo ofrecidos a lo largo del libro sirven para ilustrar cada una de las propuestas
individuales. No se trata de ejemplos de aplicaciones completas.

Por ello se ofrecen de forma complementaria proyectos Eclipse completos y funcionales. Estos
proyectos permiten ilustrar de manera concreta las prcticas y los conceptos descritos en este libro, y
tambin nociones ms avanzadas, detalladas o no en el libro.

Estos proyectos estn disponibles para su descarga en la pgina Informacin del libro digital online.

10
Informacin complementaria
La cantidad de temas relativos al desarrollo de aplicaciones Android es muy extensa, demasiado
extensa para abordarla en un nico libro. Se ha realizado una seleccin respecto a la cantidad de
temas abordados en este libro. Por un lado, algunos temas se han tratado con detalle, otros se han
abordado de forma ms ligera, y algunos otros se han omitido de forma voluntaria.

La seleccin de estos temas se ha realizado con el objetivo de cubrir un conjunto coherente de temas
que sea suficiente en lo relativo al aprendizaje del desarrollo de aplicaciones Android. Corresponde al
lector, una vez haya adquirido los conocimientos bsicos, ir ms all y descubrir por s mismo las
funcionalidades complementarias. El libro sugiere en varias ocasiones retomar el estudio de las clases
y las funcionalidades que permiten profundizar en los distintos temas abordados.

A su vez, si bien la prctica totalidad de las funcionalidades de desarrollo de aplicaciones Android est
disponible tanto en Eclipse como por lnea de comandos, se ha optado por centrarse principalmente
en el desarrollo de aplicaciones bajo Eclipse.

11
2.7 Recursos
Como complemento al libro y al cdigo fuente disponible para descargar que le acompaa, existen
numerosos recursos y documentacin como soporte al desarrollador. Los principales son:

El sitio oficial de desarrollo Android: http://developer.android.com/.

Este sitio Web incluye numerosos recursos, entre ellos, la gua de desarrollo y la
documentacin de las APIs del SDK que pueden descargarse para consultarlas de forma local,
tal y como se explica en el libro.

Este sitio incluye tambin diversos recursos tales como proyectos de ejemplo, vdeos y un blog
oficial que publica artculos muy tiles e interesantes para los desarrolladores.

El foro oficial para desarrolladores Android: http://groups.google.com/group/android-


developers.

Preguntas/respuestas entre desarrolladores


Android:http://stackoverflow.com/questions/tagged/android

La lista de bugs de Android: http://code.google.com/p/android/issues

Un proyecto Android oficial ApiDemos que permite descubrir numerosas funcionalidades de


Android as como consultar y estudiar el cdigo correspondiente.

Feliz lectura!

12
3. El universo
Android

13
Introduccin
Plataforma integrada por primera vez en un smartphone (telfono inteligente) aparecido en Espaa
en marzo de 2009, Android se ha emancipado rpidamente para conquistar numerosos aparatos,
mviles o no tales como netbooks (mini-ordenadores), las tabletas tctiles y los televisores con
conexin a Internet.

Si bien, a da de hoy, Android no es ni ms ni menos que uno de los sistemas operativos ms


importantes del mundo.

Para comprender bien cmo Android ha llegado aqu tan rpidamente, vamos a presentarlo en primer
lugar y mostrar el camino que ha recorrido. A continuacin, en segunda instancia, vamos a instalar y
preparar el entorno de desarrollo.

14
Presentacin de Android
Antes de sumergirse plenamente en el universo Android, es preciso presentar la plataforma.

Vamos a descubrir aqu los orgenes y la historia de la plataforma Android, sus distintas versiones y su
distribucin actual y pasada en los dispositivos Android. Descubriremos, por ltimo, la arquitectura de
la plataforma Android sobre la que se ejecutan las aplicaciones.

1. Open Handset AllianceTM


Comprada por Google en 2005, Android era inicialmente una startup (empresa joven) que
desarrollaba un sistema operativo para dispositivos mviles.

Desde entonces, varios rumores anunciaban la aparicin de un telfono Google llamado Gphone. No
obstante Google preparaba, de hecho, mucho ms que eso.

El 5 de noviembre de 2007 se anunci la creacin del OHA (Open Handset Alliance): un consorcio
creado por iniciativa de Google que reuna en su comienzo a una treintena de empresas. La mayora
de empresas eran operadores mviles, fabricantes de dispositivos, empresas industriales y
fabricantes de software. El rol del OHA es favorecer la innovacin en los dispositivos mviles
proporcionando una plataforma realmente abierta y completa.

El mismo da, el OHA presenta oficialmente Android: la primera plataforma completa y abierta para
dispositivos mviles. Esta plataforma incluye un sistema operativo, el middleware (las aplicaciones
intermedias), una interfaz de usuario y aplicaciones de referencia.

Algunos das ms tarde, el 12 de noviembre de 2007, el OHA anuncia la aparicin del primer
SDK(Software Development Kit) o kit de desarrollo del software Android que permite a los
desarrolladores poder crear sus propias aplicaciones para la plataforma Android.

A mediados de 2011, el OHA agrupa a ms de ochenta empresas miembros.

2. Historia
El 21 de octubre de 2008, Google y el OHA anuncian la publicacin del cdigo fuente de la plataforma
Android en open source, bajo licencia Apache 2.0.

Desde entonces es posible descargar el cdigo fuente del sistema Android, compilarlo, instalarlo y
ejecutarlo. Tambin es posible contribuir a su evolucin. Todo el cdigo fuente y la informacin se
encuentran en el sitio web Android Open Source Project:

http://source.android.com/

En noviembre de 2008 apareci el Android Market, la tienda de aplicaciones de Google que permite a
los desarrolladores y fabricantes de software poner a disposicin de cualquier cliente de Android las
aplicaciones desarrolladas por ellos. Esta tienda est disponible directamente en los dispositivos
Android a travs de la aplicacin Android Market, y tambin en el sitio web disponible en la siguiente
direccin:

https://market.android.com

Inicialmente la versin web slo permita consultar algunas aplicaciones de referencia. A partir del 2
de febrero de 2011, existe una nueva versin del sitio llamado Android Market Webstore que
permite en lo sucesivo consultar todas las aplicaciones en lnea y comprarlas e instalarlas en
dispositivos Android mediante descarga inalmbrica.

El primer smartphone Android apareci en octubre de 2008 en los Estados Unidos y en marzo de
2009 en Espaa. Fue el HTC Dream G1. Su particularidad consista en poseer un teclado fsico
deslizante. Su pantalla ocupaba 8 cm de diagonal y posea una resolucin de 320 x 480 pxeles.
Contaba con 192 MB de memoria RAM, 256 MB de ROM, una cmara digital sin flash de 3,1 mega-
15
pxeles, Wi-Fi y 3G.

Ms adelante, y hasta mediados de 2011, apareceran en el mercado un centenar de modelos de


smartphones Android, sin contar las distintas adaptaciones de cada uno de los modelos. Los
tamaos de pantalla varan entre los 6,5 cm y los 15 cm de diagonal, las resoluciones entre los 240
x 320 pxeles y los 480 x 854 pxeles. La resolucin de las cmaras digitales llega hasta los 8 mega-
pxeles.

A mediados de 2009 aparecen las primeras tabletas tctiles Android. Pero ser necesario esperar
hasta principios de 2011 para la aparicin de la versin Android 3.0 concebida especialmente para
las tabletas, con el propsito de hacerlas disponibles para el gran pblico.

Estas tabletas se ejecutan sobre procesadores de doble ncleo como ciertos smartphones Android,
poseen pantallas cuyo tamao puede alcanzar hasta los 30 centmetros de diagonal y cuya
resolucin mxima es de 1366 x 768 pxeles. Por ltimo, algunas de ellas poseen dos cmaras, una
frontal y otra en la parte posterior.

De este modo, a mediados de 2011, existen cerca de 400 modelos de smartphone y de tabletas
Android teniendo en cuenta todas las variaciones.

Los ltimos dispositivos estn tambin equipados con NFC (Near Field Communication) que les
permite comunicarse en el corto alcance, como por ejemplo para realizar un pago sin contacto.

Se ha recorrido mucho camino tras la aparicin de la plataforma Android. Cada semana supone otra
tanda de nuevos smartphones y tabletas. Y sigue creciendo!

3. Versiones de Android
Igual que con el imperio romano, Android no se ha llevado a cabo en un da. Es por ello que la
progresin en el nmero de funcionalidades es similar a la de su cuota de mercado, es decir,
simplemente impresionante.

Estas funcionalidades, mejoras y correcciones de bugs han ido apareciendo con el tiempo en las
sucesivas versiones.

Veamos a continuacin cada una de estas versiones desde la aparicin oficial de Android y su
reparto actual y pasado en el conjunto de dispositivos Android.

a. Cronologa de versiones

En septiembre de 2008 apareci la primera versin de la plataforma Android, la versin 1.0. A


continuacin apareci la versin 1.1 en febrero de 2009. Esta versin fue la que se integr en el
primer smartphone Android comercializado en Espaa en marzo de 2009.

Algunos meses ms tarde, Android pas directamente a la versin 1.5, versin mayor que apareci
en abril de 2009. Le seguiran tres revisiones de esta versin: la 1.5r2, la 1.5r3 y la 1.5r4.

La versin 1.5 aportaba nuevas funcionalidades tales como la deteccin de la rotacin mediante un
acelermetro, la grabacin de vdeo y la integracin de los App Widgets (vase el captulo
Funcionalidades avanzadas - App Widget).

La versin 1.6 apareci en septiembre de 2009. Esta versin integr en particular el soporte de
numerosas resoluciones y tamaos de pantalla distintos. Tambin se integr la sntesis vocal. A
continuacin aparecieron dos revisiones, la 1.6r2 y la 1.6r3.

En octubre de 2009 apareci la versin mayor 2.0, aportando el soporte de HTML5 y de Exchange.

En diciembre de 2009 apareci la 2.0.1 y, en enero de 2010, la 2.1 que integraba los fondos de
pantalla dinmicos. A continuacin apareci la revisin 2.1r2.

Estas ltimas versiones fueron rpidamente reemplazadas por la versin 2.2. Esta versin aport
la funcionalidad de hotspot (punto de acceso Wi-Fi) y supuso una mejora neta del rendimiento, de
16
2 a 5 veces ms rpido que la versin 2.1. Esta versin permite a su vez la instalacin de
aplicaciones en un almacenamiento externo como una tarjeta de memoria extrable. Todava
apareci una revisin: la 2.2r2.

A finales de 2010, apareci la versin 2.3 que incluy el NFC, soporte a varias cmaras, una
interfaz mejorada, mejor gestin de la energa, gestin de nuevos sensores, una mejora
importante en el rendimiento, de la mquina virtual Dalvik, un teclado virtual ms rpido con la
funcionalidad copiar/pegar mejorada, soporte para VoIP (Voice over Internet Protocol) y SIP (Session
Initiation Protocol)

La versin 2.3 slo estuvo disponible en el smartphone Nexus S de Google.

Fue preciso esperar a la versin 2.3.3 para que los dems telfonos, el Nexus One entre otros,
pudieran situarse al mismo nivel.

En febrero de 2011 apareci la versin 3.0. Esta versin marc una etapa importante en el mundo
Android. Estaba especialmente diseada para tabletas tctiles con el objetivo de aprovechar sus
pantallas de grandes dimensiones. Adems de la integracin de una nueva interfaz de usuario rica
en nuevos componentes que incorporaba un nuevo tema grfico, la versin 3.0 aport el soporte
de la arquitectura de procesadores de mltiples ncleos.

En mayo de 2011 apareci la versin 2.3.4. Es la versin ms reciente de la que se pueden


beneficiar los smartphones a mediados de 2011 y ello a pesar de la aparicin de la versin 3.0,
dado que esta ltima est dedicada exclusivamente a las tabletas. Ambas coexisten por tanto en
la actualidad como ramas de versiones paralelas, una para los smartphones, otra para las
tabletas.

Es muy probable que alguna versin futura fusione ambas ramas donde converjan los
smartphones, las tabletas y es posible que incluso los televisores con conexin a Internet.

Aparecida tambin en mayo de 2011, la versin 3.1 est todava dedicada a las tabletas. Esta
versin aporta en concreto el soporte de USB (Universal Serial Bus) maestro y la posibilidad de
gestionar diversos perifricos conectados a los puertos USB.

A estas versiones del sistema Android le corresponden niveles de interfaz de programacin o


simplemente API (Application Programming Interface) del SDK. A continuacin aparece una tabla que
muestra esta correspondencia.

Versin de la Fecha Nombre Nivel de API


plataforma Android

1.0 09/2008 1

1.1 02/2009 2

1.5 04/2009 Cupcake 3

1.5r2 05/2009

1.5r3 07/2009

1.5r4 05/2010

1.6 09/2009 Donut 4

1.6r2 12/2009

1.6r3 05/2010

2.0 10/2009 Eclair 5

2.0.1 12/2009 6

2.1 01/2010 7

17
2.1r2 05/2010

2.2 05/2010 Froyo 8

2.2r2 07/2010

2.3 12/2010 Gingerbread 9

2.3.3 02/2011 10

3.0 02/2011 Honeycomb 11

3.1 05/2011 Honeycomb 12

Observe que las versiones mayores estn tituladas con nombres de postres y cuya primera
letra es la siguiente en orden alfabtico respecto al nombre del postre anterior. Cupcake-
>Donut->Eclair->Froyo->Gingerbread->Honeycomb->I...

El sistema Android asegura a las aplicaciones una compatibilidad ascendente. Esto significa que
una aplicacin pensada para funcionar sobre una versin mnima de Android 1.6 (API 4) funcionar
automticamente sobre todas las versiones de Android 1.6 (API 4) y superiores, y por tanto, por
ejemplo, sobre la versin 3.0 (API 11).

b. Reparto de las distribuciones Android

Cada quince das, el sitio web Android proporciona el reparto de las versiones de Android en los
sistemas que han accedido al Android Market en las dos ltimas semanas. Tambin aparecen los
datos histricos que permiten seguir la evolucin en este reparto.

Esta informacin est disponible en la siguiente direccin:

http://developer.android.com/resources/dashboard/platform-versions.html

Estos datos ayudan al desarrollador a la hora de escoger, con toda la informacin disponible, la
versin mnima sobre la que deber ejecutar su aplicacin. Gracias a la compatibilidad ascendente
de Android, esta aplicacin funcionar automticamente en las versiones superiores.

Cuanto menor sea la versin mnima de Android requerida por la aplicacin, mayor ser el
nmero de dispositivos, y en consecuencia el nmero de usuarios y de compradores
potenciales, que podrn ejecutar la aplicacin. En contrapartida, la aplicacin dispondr de
menos APIs de SDK que las versiones ms recientes. Es, por tanto, tarea del desarrollador
encontrar el mejor compromiso entre las funcionalidades requeridas del SDK y la extensin del
pblico objetivo.

Por ejemplo, el 1 de abril de 2011, cerca del 94% de los dispositivos que accedan al Android
Market funcionaban sobre versiones de Android 2.1 (API 7) o superiores. El desarrollador debe
preguntarse si merece la pena perder el 6% de la cuota de mercado y aprovechar en contrapartida
las nuevas API disponibles desde la versin de Android 2.1 (API 7).

4. Arquitectura
El sistema Android est basado en el ncleo de Linux 2.6. Este ncleo tiene en cuenta la gestin de
las capas inferiores, tales como los procesos, la gestin de la memoria, los permisos de usuario y la
capa de hardware mediante los drivers.

En Android 3.0 (API 11), la versin del ncleo de Linux usada es la 2.6.36.

Sobre este ncleo, se sita la capa de bibliotecas principales del sistema proporcionadas por los
18
fabricantes. stas, de bajo nivel, estn escritas en C y/o C++. Proporcionan los servicios esenciales
tales como la gestin de la visualizacin 2D y 3D, un motor de base de datos SQLite, la reproduccin
y la grabacin de audio y vdeo, un motor de navegador web

Las funcionalidades ofrecidas por estas bibliotecas las recoge y utiliza la capa superior bajo la forma
de bibliotecas Java. stas proporcionan bibliotecas y componentes reutilizables especficos a
dominios particulares. Encontramos, por ejemplo, bibliotecas de acceso a bases de datos, de
telefona, de localizacin geogrfica, de comunicacin sin contacto de corto alcance

Android proporciona a su vez una multitud de bibliotecas Java bsicas estndar tales como las
del paquete java.*.

Por ltimo, la capa de ms alto nivel es la de las aplicaciones. Estas aplicaciones son las que se
incluyen por defecto, tales como la aplicacin de bienvenida o escritorio, la aplicacin que permite
ejecutar otras aplicaciones, el navegador web, la aplicacin de telefona... Pero tambin son las
aplicaciones especficas creadas por desarrolladores, de los que usted formar parte muy pronto!

Si bien es posible desarrollar aplicaciones basadas en cdigo C y/o C++ mediante el NDK (Native
Development Kit), sobretodo para mejorar el rendimiento, no se abordar este tema en este libro.
Utilizaremos nicamente las API Java que proporciona el SDK y que bastan, en la gran mayora de
casos, para crear todo tipo de aplicaciones estndar. Si se tratara de aplicaciones con un gran
consumo de recursos grficos tales como juegos 2D o 3D, el escenario sera distinto.

Por defecto, cada aplicacin se ejecuta en una mquina virtual Java alojada en un proceso Linux
dedicado. Esta mquina virtual es especfica a la plataforma Android y est especializada para
entornos embebidos. Se le llama mquina virtual Dalvik.

19
Entorno de desarrollo
Pieza central del desarrollo de aplicaciones, el entorno de desarrollo de Android puede adoptar varios
aspectos segn el uso y costumbres del desarrollador. Este entorno puede restringirse a una simple
lnea de comandos y un editor de texto sencillo, pero potente, acompandola o ir hasta un entorno
de desarrollo integrado, rico en recursos pero funcional.

Detallamos todo ello a continuacin en esta seccin, para centrarnos despus en el caso particular de
un entorno de desarrollo integrado.

1. Requisitos previos
Para poder desarrollar aplicaciones Android, es preciso asegurarse de que el puesto de desarrollo
es compatible con los criterios requeridos.

Sistemas operativos soportados:

Windows XP (32 bits), Windows Vista (32 o 64 bits), Windows 7 (32 o 64 bits).

Mac OS X 10.5.8 o superior (x86 nicamente).

Linux (Biblioteca GNU C (glibc) 2.11 o superior; las distribuciones de 64 bits deben ser
capaces de ejecutar aplicaciones de 32 bits).

Se requiere un mnimo de 200 MB de espacio en disco slo para la instalacin del SDK, de sus
herramientas y de alguna versin de la plataforma Android.

Se requiere el JDK (Java Development Kit) de Java 5 o superior. Si el puesto de desarrollo todava no
est disponible, es posible descargar el JDK de la plataforma Java SE (Java Platform, Standard Edition)
en la siguiente direccin:

http://www.oracle.com/technetwork/java/javase/downloads/index.html

2. Instalacin del SDK Starter Package


El SDK Android no se descarga directamente. Es preciso utilizar la herramienta SDK Starter Package
(Herramienta de instalacin del SDK). Esta herramienta nos va a permitir instalar las herramientas
bsicas del SDK para descargar a continuacin todos los componentes del SDK de la o las versiones
que deseemos.

El archivo que comprende las herramientas bsicas del SDK, y por tanto de la instalacin del SDK,
est disponible para su descarga aqu: http://developer.android.com/sdk/index.html

Si el archivo de descarga tiene formato zip o tgz, descomprmalo en una ubicacin especfica.
Recuerde bien esta ubicacin, se le solicitar posteriormente durante la instalacin del mdulo de
extensin ADT (Android Development Tools).

Si el archivo de instalacin descargado es para Windows (.exe), ejectelo. ste verificar la


conformidad de la instalacin del JDK Java e instalar las herramientas del SDK en la ubicacin por
defecto o en la ubicacin que se le indique.

En lo sucesivo en este libro, ciertas rutas utilizan el trmino sdk, por ejemplo sdk/platform-
tools. Ser preciso reemplazar el trmino sdk por la carpeta raz de la instalacin del SDK.

3. Eclipse y el Plug-in ADT


Si bien el uso de Eclipse para el desarrollo de aplicaciones Android no es obligatorio, se aconseja
20
encarecidamente. Acoplado al plug-in ADT, Eclipse se convierte en un verdadero entorno de
desarrollo de aplicaciones Android.

El plug-in ADT integra numerosas funcionalidades especficas al desarrollo de aplicaciones Android


bajo Eclipse, desde el asistente para la creacin de un proyecto Android hasta la exportacin de la
aplicacin final. La instalacin vara segn la versin de Eclipse que se utilice.

a. Instalacin de Eclipse

Es necesaria una versin de Eclipse 3.4 o superior. A partir de Eclipse 3.5, se recomienda la edicin
Eclipse Classic. No obstante, cualquier edicin de Eclipse que incluya el plug-in Eclipse JDT puede
servirnos. En este libro utilizaremos la versin Eclipse Classic 3.6 en ingls, idioma por defecto.

Es posible descargar Eclipse de la siguiente direccin: http://www.eclipse.org/downloads

b. Instalacin del plug-in ADT en Eclipse 3.4

En el men general de Eclipse, seleccione Help - Software Updates.

Se muestra una ventana.

Seleccione la pestaa Available Software.

Haga clic en el botn Add Site.

Introduzca la direccin https://dl-ssl.google.com/android/eclipse/ en la ventana que aparece y


a continuacin haga clic en el botn OK.

Si apareciera algn problema de descarga, reemplace https por http en la url.

Marque la opcin Developer Tools y a continuacin haga clic en Install.

Haga clic en el botn Next y a continuacin en el botn Finish.

La descarga y la instalacin de los componentes se ejecutan automticamente.

Espere hasta que finalice la instalacin y a continuacin reinicie Eclipse.

c. Instalacin del plug-in ADT en Eclipse 3.5 y 3.6

En el men general de Eclipse, seleccione Help - Install New Software.

Se muestra la ventana Install.

21
Instalacin del plug-in ADT

Haga clic en el botn Add... situado arriba a la derecha.

En la nueva ventana Add Repository que aparece, introduzca Android en el campo Name y la
direccin https://dl-ssl.google.com/android/eclipse/ en el campo Location.

Instalacin del plug-in ADT

Haga clic en el botn OK.

Si apareciera algn problema de descarga, reemplace https por http en la url.

En la lista de componentes disponibles aparece el grupo Developer Tools. El Developer permite


ver los elementos que contiene.

Es probable que los nmeros de versin que se muestran en la pantalla sean ms recientes a
22
los de las capturas de pantalla del libro. Esto no cambia en nada lo que viene a continuacin.

Marque la opcin Developer Tools.

Instalacin del plug-in ADT

Haga clic en el botn Next. Esta etapa puede durar cierto tiempo si se trata de una instalacin
nueva de Eclipse.

23
Instalacin del plug-in ADT

Haga clic en el botn Next.

Lea y acepte los trminos de la licencia de uso de los componentes marcando la opcin I
accept the terms of the license agreements.

24
Instalacin del plug-in ADT

Haga clic en el botn Finish.

La descarga y la instalacin de los componentes se ejecutan automticamente.

Instalacin del plug-in ADT

Es posible que aparezca un mensaje de advertencia durante la instalacin.

25
Instalacin del plug-in ADT

Si tal fuera el caso, haga clic en el botn OK.

Al finalizar la instalacin, la ventana Software Updates le invita a reiniciar Eclipse.

Instalacin del plug-in ADT

Haga clic en el botn Restart Now para reiniciar Eclipse inmediatamente.

d. Configuracin del plug-in ADT

A continuacin queda indicar al plug-in ADT el lugar donde se encuentran las herramientas bsicas
del SDK Android instaladas anteriormente. Para ello:

En el men General de Eclipse, seleccione Eclipse - Preferences....

Aparece a continuacin la ventana Preferences.

26
Instalacin del plug-in ADT

Seleccione Android en la parte izquierda y en la parte derecha, en el campo SDK Location,


especifique el lugar donde se encuentra el SDK Android descargado anteriormente.

27
Instalacin del plug-in ADT

Haga clic en el botn OK.

Aparece a continuacin la ventana Android SDK Verification que le advierte de que faltan las
herramientas del SDK especficas a las plataformas Android.

Esta advertencia es normal puesto que, para desarrollar una aplicacin Android, es preciso
instalar como mnimo el SDK de una plataforma Android as como las herramientas asociadas.
Esta etapa se describe a continuacin.

Instalacin del plug-in ADT

Haga clic en el botn OK.

28
4. Instalacin del SDK Android
Para desarrollar una aplicacin Android, es preciso instalar como mnimo el SDK de una plataforma
Android as como las herramientas asociadas. Para ello:

En el men general de Eclipse, seleccione Window - Android SDK and AVD Manager o haga clic
directamente sobre el icono correspondiente en la barra de herramientas.

Icono del Android SDK and AVD Manager

A continuacin se abre la herramienta Android SDK and AVD Manager.

Instalacin del SDK Android

En la parte izquierda, seleccione Installed packages para visualizar la lista de componentes del
SDK que ya estn instalados. En la lista de la derecha aparece el nico componente instalado
por defecto, a saber Android SDK Tools en su ltima versin. sta comprende las herramientas
bsicas del SDK Android comunes a todas las plataformas Android.

29
Instalacin del SDK Android

En la parte izquierda, seleccione a continuacin Available packages para mostrar la lista de


componentes disponibles. En la lista de la derecha, despliegue las dos categoras
propuestas,Android Repository y Third party Add-ons, para descubrir aquellas que le
convienen.

30
Instalacin del SDK Android

Una vez ms, es muy probable que la lista que se muestre sea diferente a la de la captura de
pantalla. Esto no tiene importancia.

De arriba a abajo, la categora Android Repository contiene:

Android SDK Platform-tools: la ltima versin de las herramientas dependientes de la


plataforma Android.

Documentation for Android SDK: la ltima versin de la documentacin del SDK Android. Se
trata de una copia local de la documentacin disponible en lnea.

SDK Platform Android...: SDK de varias plataformas Android desde la versin 1.5 (API 3),
cada una en su ltima versin. Observe que ciertas versiones, como la 2.0 (API 5) y la 2.0.1
(API 6), no estn disponibles y han sido reemplazadas por la versin 2.1 (API 7).

Samples for SDK API: proyectos Android de ejemplo correspondientes a distintas


versiones del SDK.

Android Compatibility package: paquete que contiene las bibliotecas que permiten utilizar
nuevos conceptos y API sobre las versiones de Android inferiores. En concreto, este paquete
proporciona la biblioteca android-support-v4.jar que permite utilizar los conceptos
presentados en Android 3.0 (API 11), tales como los fragmentos, en versiones Android 1.6
(API 4) o superiores. Gracias a esta biblioteca, el desarrollador puede desa-rrollar una nica
aplicacin para smartphones y tabletas tctiles de versiones 1.6 (API 4) o superior utilizando
los conceptos presentados en Android 3.0 (API 11). Una vez descargada, la
31
biblioteca android-support-v4.jar, que se encuentra en la
carpetasdk/extras/android/compatibility/v4, debe importarse a continuacin en
el proyecto para poder usarse.

La compatibilidad descendente que ofrece esta biblioteca supone por desgracia algunas
restricciones en contrapartida. En este libro utilizaremos por tanto las API nativas de Android
3.0 (API 11), en lugar de las que proporciona esta biblioteca, para describir mejor los nuevos
conceptos que introducen.

La categora Third party Add-ons contiene mdulos complementarios y opcionales ofrecidos por
otros fabricantes y que les son propias. Estos mdulos requieren la instalacin de una versin del
SDK Android. Permiten extender las funcionalidades del entorno de desarrollo o de las aplicaciones
Android. Por ejemplo, ciertas empresas ofrecen emuladores de sus dispositivos Android, como un
emulador de tableta tctil.

Desplegando la carpeta de la empresa Google Inc., aparecen los siguientes componentes:

Google APIs by Google Inc, Android API...: mdulos que proporcionan funcionalidades
suplementarias ofrecidas por la empresa Google tales como los mapas geogrficos de Google
Maps (vase el captulo Mapas y localizacin geogrfica - Google Maps), la gestin de cuentas
de tipo Gmail, parte del Android Market para verificar la licencia (vase el captulo
Funcionalidades avanzadas - Proteger las aplicaciones de pago), compras integradas...

Google Market Licensing package: biblioteca que permite proteger las aplicaciones de pago
mediante la verificacin en lnea de la licencia (vase el captulo Funcionalidades avanzadas -
Proteger las aplicaciones de pago). Esta funcionalidad implica que la aplicacin est publicada
en el Android Market.

Google Market Billing package: biblioteca que permite comprar contenido desde una
aplicacin. Este servicio se llama In-app Billing (compra integrada). Esta funcionalidad implica
que la aplicacin est publicada en el Android Market.

32
Instalacin del SDK Android

Marque el componente Android SDK Plateform-tools y al menos una versin de SDK Platform
Android.

Las versiones SDK Platform Android 3.0 (API 11) y 3.1 (API 12) estn destinadas
exclusivamente a las tabletas tctiles. En lo que respecta a las versiones 2.3.4 (API 10) e
inferiores, stas se distribuyen para todo tipo de hardware, smartphone y tabletas tctiles.

Tambin es posible seleccionar la documentacin del SDK para descargarla sobre el puesto local. De
este modo, la consulta de esta documentacin podr realizarse directamente en local, mejor y ms
rpido que en lnea. Ocurre lo mismo con los ejemplos. Es posible instalar y desinstalar cada uno de
estos componentes en cualquier momento, a excepcin de las herramientas Android SDK Tools que
permiten, entre otros, administrar la instalacin de los componentes y deben estar por tanto
siempre presentes.

Una vez seleccionados los componentes, haga clic en el botn Install Selected.

Aparece una nueva ventana detallando los componentes seleccionados.

33
Instalacin del SDK Android

Haga clic en el botn Install para ejecutar la descarga y la instalacin de los componentes.

Instalacin del SDK Android

Al finalizar la instalacin, se le propone reiniciar la herramienta ADB (Android Debug Bridge).

La herramienta ADB reagrupa mltiples funciones, las principales se abordarn a lo largo de


este libro. Esta herramienta se ejecuta en modo cliente-servidor sobre el puesto de desarrollo
y en modo demonio sobre el emulador o el dispositivo Android. Aqu, es posible reiniciar el servidor
ADB tras su actualizacin.

34
Instalacin del SDK Android

Haga clic en el botn Yes y espere algunos instantes, el tiempo que tarde en realizarse el
reinicio de la herramienta ADB.

Instalacin del SDK Android

Haga clic en el botn Close.

Estos componentes deben aparecer ahora en la lista de componentes instalados.

Para verificarlo, seleccione la opcin Installed packages en la parte izquierda para mostrar la
lista de componentes instalados.

35
Instalacin del SDK Android

Cierre a continuacin la ventana.

Listo! El entorno de desarrollo est preparado.

36
4. Primeros pasos

37
Primer proyecto Android
Con el entorno de desarrollo ya instalado y listo para su uso, vamos a crear sin esperar ms nuestro
primer proyecto Android bajo Eclipse. A continuacin, lo ejecutaremos en el emulador de Android y,
segn la disponibilidad, sobre un dispositivo Android.

A continuacin, en la seccin siguiente, descubriremos la estructura detallada de un proyecto Android.

1. Creacin del proyecto


En el men general de Eclipse, seleccione File - New - Project....

Aparece la ventana New Project, que muestra los asistentes para la creacin de proyectos.

Creacin de un proyecto Android

Despliegue la carpeta Android, seleccione Android Project y haga clic en el botn Next.

Aparece a continuacin la ventana New Android Project del asistente de creacin de proyectos
Android.

Es preciso informar numerosos campos. He aqu su correspondencia:

Project name: nombre del proyecto Android y de la carpeta que contiene el proyecto. En
nuestro ejemplo, seleccionaremos MiApli.

Contents: permite indicar si se trata de un proyecto en blanco o si el proyecto ya existe y debe

38 En nuestro caso, dejamos la configuracin por


integrarse en el espacio de trabajo de Eclipse.
integrarse en el espacio de trabajo de Eclipse. En nuestro caso, dejamos la configuracin por
defecto.

Este campo permite a su vez crear un proyecto a partir de uno de los proyectos que se
proporcionan en los ejemplos disponibles para su descarga mediante la herramienta Android
SDK and AVD Manager.

Build Target: permite especificar la versin concreta de la plataforma Android utilizada para
compilar la aplicacin.

Properties: contiene varios campos a informar de forma obligatoria. stos son:

Application name: nombre de la aplicacin que podr usar la aplicacin para mostrar al
usuario. Este nombre puede contener espacios en blanco.

Package name: nombre del paquete Java donde se generarn los fuentes. ste sirve a su
vez como identificador nico de la aplicacin. Es preciso utilizar un formato estndar de
nombre de dominio. En nuestro ejemplo,
utilizaremos es.midominio.android.miapli.

Create Activity: si este campo est activado, indica que el asistente tendr que crear una
actividad cuyo nombre se informar justo al lado. Estudiaremos ms adelante qu es una
actividad. De momento, quedmonos con la idea de que la actividad creada ser una clase
que servir de punto de entrada a la aplicacin. En nuestro ejemplo,
utilizaremos MiActividadPrincipal.

Min SDK Version: permite indicar el nivel de API sobre el que queremos que se ejecute
nuestra aplicacin. Para que nuestra aplicacin sea compatible con el mximo nmero de
sistemas Android, se recomienda que el nmero de nivel de API sea el menor posible
compatible con las API que queramos utilizar para desarrollar la aplicacin. En nuestro
ejemplo, para poder utilizar sin problemas todas las API posteriores a la API de Android 3.0
(API 11), utilizaremos la versin 11. En caso de duda, se especificar el mismo nivel de API
que se indique en el campo Build Target.

Si la versin mnima indicada difiere de la versin seleccionada en el campo Build Target,


aparece un mensaje de advertencia en la parte superior del asistente que nos alerta para
poder tomar las acciones oportunas si fuera necesario.

39
Creacin de un proyecto Android

Haga clic en el botn Next.

Se nos propone crear un proyecto de prueba. No haremos nada de momento pues este tema se
abordar en otro captulo del libro (vase el captulo Trazas, depuracin y pruebas - Pruebas unitarias
y funcionales).

Haga clic en el botn Finish.

Se genera el proyecto en el espacio de trabajo de Eclipse y se agrega a la vista Package


Explorer(Explorador de paquetes). Se compila automticamente.

40
Creacin de un proyecto Android

La compilacin del proyecto conlleva la creacin de un archivo binario MiApli.apk en la


carpeta bin del proyecto.

Se trata de un archivo de formato apk (Android Package). En concreto, es un archivo zip que contiene
todo el proyecto: cdigo compilado, datos y archivos de recursos.

Del hecho de que este archivo contiene a la aplicacin, es habitual referirse a este archivo
usando directamente el trmino aplicacin.

2. Ejecucin de la aplicacin
Ahora que el proyecto ha sido creado con xito, que la aplicacin ha sido generada, slo queda
instalarla en un sistema Android y ejecutarla. Para ello:

En la vista Package Explorer de Eclipse, haga clic con el botn derecho sobre el
proyecto MiApli.

41
Creacin de un proyecto Android

A continuacin haga clic en Run As - Android Application.

La vista Consola permite seguir el avance de carga de la aplicacin y de su ejecucin.

Si aparece en la consola un mensaje de error del tipo The connection to adb is


down, and a severe error has occured, reinicie Eclipse e intntelo de nuevo.

Aparece una ventana de dilogo Android AVD Error informndonos de que no existe ningn
AVD(Android Virtual Device), es decir una configuracin del emulador Android o un aparato Android
conectado que posea una versin igual o superior a la versin mnima indicada durante la creacin del
proyecto. Se nos propone crear la configuracin de un dispositivo a emular.

Creacin de un proyecto Android

Haga clic en el botn No y cierre la ventana Android Device Chooser. Volveremos a ella ms
tarde.

Existen dos posibilidades a la hora de ejecutar la aplicacin:


42
Crear un AVD, un perifrico Android virtual, y ejecutarlo sobre el emulador.

Utilizar un dispositivo Android real, como un smartphone o una tableta tctil, conectada al
ordenador.

a. sobre el emulador Android

El SDK proporciona un emulador de perifricos Android. Este emulador permite emular numerosas
configuraciones de hardware. Un AVD es una configuracin de hardware concreta que utilizar el
emulador.

Veamos cmo se crea un AVD.

Ejecute la herramienta Android SDK and AVD Manager.

Recuerde, la herramienta Android SDK and AVD Manager puede ejecutarse desde la barra
de herramientas haciendo clic en su icono o seleccionado Window - Android SDK and AVD
Manager.

A continuacin se abre la herramienta Android SDK and AVD Manager indicando que no existe
ningn AVD.

Creacin de un AVD

Haga clic en el botn New... situado arriba del todo a la derecha.

Aparece la ventana Create new Android Virtual Device (AVD).

Para crear el AVD es preciso informar numerosos campos:

Name: nombre del AVD. No debe contener caracteres especiales, ni espacios.

Este nombre debe, a su vez, ser corto de cara a tener una mayor comodidad dado que se
utiliza por lnea de comandos o en una consola, y ser lo suficientemente explcito para
caracterizar la configuracin del AVD.
43
Target: lista que proporciona las plataformas disponibles descargadas e instaladas sobre el
puesto de desarrollo. Recuerde, la versin de la API de la plataforma escogida deber ser
igual o superior a la versin mnima de la API especificada en la aplicacin.

SD Card: permite emular la presencia de una tarjeta SD en el dispositivo virtual


especificando un tamao. Preste atencin de no indicar un tamao excesivamente grande
dado que se crear un archivo del tamao de esta tarjeta SD en el puesto de desarrollo.
Tambin es posible reutilizar una tarjeta SD virtual creada anteriormente indicando el
nombre de esta tarjeta SD.

Snapshot: cuando se selecciona esta opcin, es posible realizar una copia de seguridad del
estado en curso del AVD. sta puede ser rpidamente restaurada a continuacin,
ahorrando al desarrollador una nueva espera en el caso de un reinicio completo del AVD.

Skin: permite especificar la resolucin de la pantalla del dispositivo emulado bien


seleccionando una resolucin estndar, o bien especificando una resolucin particular.

Hardware: permite afinar la configuracin de hardware indicando propiedades avanzadas


como, por ejemplo, la presencia o no de una cmara de fotos o un teclado fsico.

He aqu la pantalla informada con los valores que utilizaremos en nuestro ejemplo.

Creacin de un AVD
44
Una vez informados los campos, haga clic en el botn Create AVD para crear el AVD.

A continuacin el AVD se agrega a la lista de AVD existentes.

Es posible crear tantos AVD como se quiera. Esto permite probar la misma aplicacin sobre
numerosas configuraciones de hardware y asegurarse as del buen funcionamiento de sta
sobre el mayor nmero de configuraciones diferentes.

Creacin de un AVD

Los botones Delete..., Repair... y Details... permiten respectivamente suprimir, reparar el AVD
seleccionado actualmente y mostrar sus caractersticas.

El botn Start permite iniciar el emulador con el AVD seleccionado especificando los parmetros de
inicio. Es posible modificar el tamao de la ventana del emulador y borrar los datos de usuario del
AVD como si el dispositivo saliera de fbrica. Tambin es posible indicar que se quiere restaurar el
AVD tras una copia de seguridad marcando la opcin Launch from snapshot. La opcin Save to
snapshot permite realizar una copia de seguridad del AVD tras cada cierre de la ventana del
emulador.

Cierre la ventana.

Vuelva a ejecutar la aplicacin tal y como hemos visto anteriormente.

El emulador Android, en concreto la aplicacin emulator, se ejecuta a continuacin en el puesto


de desarrollo. Espere el tiempo de carga del sistema. Esto puede llevar varios minutos segn la
potencia del puesto de desarrollo. A continuacin aparece la pantalla de bienvenida o la pantalla de
desbloqueo. A continuacin se carga y se ejecuta la aplicacin automticamente.

Si aparece la pantalla de desbloqueo, desbloquee para poder ver la aplicacin.

La interfaz del emulador y la interfaz de la aplicacin son distintas segn la versin concreta de
Android utilizada por el proyecto y la versin del AVD sobre la que se ejecuta la aplicacin.

Por ejemplo, sobre un sistema Android 3.0 (API 11) y con una versin mnima requerida por la
aplicacin tambin Android 3.0 (API 11), la aplicacin se abre sobre un fondo negro. En la parte
superior se muestra la barra de accin que incluye, en la parte izquierda, el icono y el ttulo de la
aplicacin especificados durante la creacin del proyecto. Justo debajo de esta barra de accin se
muestra una lnea de texto que contiene el nombre de la actividad principal, tambin especificada
durante la creacin del proyecto.

45
Emulador de un AVD de tipo tableta tctil bajo Android 3.0 (API 11)

Sobre un sistema Android con versin de interfaz inferior a la 3.0 (API 11) y siendo la versin mnima
del sistema requerido por la aplicacin tambin inferior a Android 3.0 (API 11), la aplicacin muestra
una pantalla negra con una barra de ttulo sobre un fondo de color donde aparece el nombre de la
aplicacin. Debajo se muestra una lnea de texto que contiene el nombre de la actividad principal.

Creacin de un AVD de tipo smartphone


46
bajo Android 2.3.3 (API 10)
Existen numerosos atajos de teclado que permiten interactuar con el emulador. Por ejemplo,
la tecla 7 del teclado numrico del ordenador permite cambiar la orientacin de la pantalla en
un sentido, y la tecla 9 en el otro sentido. Las distintas opciones de ejecucin del emulador
estn disponibles en la
siguiente direccin:http://developer.android.com/guide/developing/tools/emulator.html

b. sobre un dispositivo Android

Si bien el emulador puede adaptarse a numerosas configuraciones de hardware, tambin es cierto


que hay algunas que no puede emular. Uno de los mayores defectos del emulador es su
rendimiento. De este modo, el emulador mostrar rpidamente su debilidad si la aplicacin que
quiere probar requiere un dispositivo potente. Adems, probando una aplicacin a travs del
emulador sta puede parecer correcta mientras que una prueba real va a mostrar en seguida los
defectos de la aplicacin.

Un ejemplo muy sencillo es la presin tctil sobre la pantalla. En el emulador, basta con hacer clic
con el cursor del ratn, que es muy preciso a nivel de pxel. En un dispositivo real, el dedo del
usuario es menos preciso que el cursor del ratn. Si la aplicacin requiere hacer clic sobre una zona
pequea de la pantalla, ser mucho ms delicado si se hace con los dedos, mientras que no
supondr problema alguno utilizando el ratn en un emulador.

Es por ello que es casi obligatorio ejecutar la aplicacin en un dispositivo Android real para validar
su buen funcionamiento, su reactividad y, sobretodo, su ergonoma. No obstante, dado que esto
slo validar la aplicacin en un nico tipo de hardware, lo ideal es combinar pruebas en un
emulador y pruebas sobre dispositivos reales.

Si bien es suficiente un smartphone comercial para probar las aplicaciones, Google permite
comprar smartphones de desarrollo: los llamados Android Dev Phone. Estos smartphones
slo se venden a desarrolladores registrados en el Android Market (vase el captulo Publicar
una aplicacin - Publicacin de la aplicacin en el Android Market). Se trata de modelos de
smartphone comerciales a los que se ha desbloqueado la tarjeta sim de forma oficial y
completamente legal, por lo general a nivel de bootloader. Esto permite en particular instalar
una imagen personalizada del sistema operativo Android. Para ms informacin, consulte la
siguiente direccin: http://market.android.com/publish/buyDeveloperPhone

Para probar una aplicacin sobre un dispositivo Android, es preciso activar la depuracin USB sobre
el dispositivo. Para ello, la primera etapa de la manipulacin es distinta segn el sistema Android
utilizado.

En sistemas Android de versiones inferiores a la 3.0 (API 11), vaya a la pantalla de bienvenida
si no se muestra directamente y presione a continuacin la tecla Men. En sistemas Android
de versiones 3.0 (API 11) o superiores, haga clic sobre la hora en la parte inferior derecha y a
continuacin haga clic en la pequea ventana que contiene la hora que acaba de aparecer.

Seleccione Configuracin.

A continuacin se muestra la aplicacin de configuracin de los parmetros del dispositivo.

Seleccione Aplicaciones, a continuacin Desarrollo.

Active la opcin Depuracin USB y valide el mensaje de advertencia haciendo clic en el


botnOK.

A continuacin hay que hacer que el puesto de desarrollo reconozca al dispositivo Android cuando
se conecte. Siga las instrucciones que aparecen a continuacin segn el sistema operativo instalado
sobre el puesto de desarrollo.

Si apareciesen problemas durante la instalacin de los controladores o si el dispositivo no se


detectase o reconociese, verifique que el cable USB que est utilizando es el entregado
47
originalmente con el dispositivo Android y que est conectado directamente al puesto de
desarrollo.

Mac OS X

Conecte el dispositivo Android al puesto de desarrollo mediante el uso de un cable USB.

El dispositivo Android se detecta automticamente.

Windows XP

Es preciso instalar un controlador USB sobre el puesto de desarrollo para reconocer dispositivos
Android.

Descrguelo mediante la herramienta Android SDK and AVD Manager vista anteriormente. El
paquete se llama Google USB Driver package y se encuentra en Third party Add-ons y a
continuacin Google Inc.

Conecte el dispositivo Android al puesto de desarrollo utilizando un cable USB. Windows


detecta automticamente el dispositivo y ejecuta el asistente para agregar hardware.

Seleccione No, no esta vez y haga clic en Siguiente.

Seleccione Instalar a partir de una lista o de una ubicacin especfica, y haga clic
enSiguiente.

Seleccione Buscar el mejor controlador en esta ubicacin.

Desmarque la opcin Buscar en medios extrables y marque Incluir esta ubicacin en la


bsqueda.

Haga clic en el botn Examinar, seleccione la carpeta sdk\extras\


google\usb_driver\ y haga clic en OK y a continuacin en Siguiente.

Por ltimo, haga clic en el botn Instalar.

Se efectuar la instalacin del controlador.

Windows Vista

Es preciso instalar un controlador USB sobre el puesto de desarrollo para reconocer dispositivos
Android.

Descrguelo mediante la herramienta Android SDK and AVD Manager vista anteriormente. El
paquete se llama Google USB Driver package y se encuentra en Third party Add-ons y a
continuacin Google Inc.

Conecte el dispositivo Android al puesto de desarrollo utilizando un cable USB. Windows


detecta automticamente el dispositivo e intenta instalarlo.

Abra el men Inicio y seleccione Panel de control.

Seleccione Hardware y sonido y a continuacin Administrador de dispositivos.

Haga clic con el botn derecho sobre la lnea Perifrico USB compuesto que muestra un
pequeo icono de alerta en la lista y seleccione a continuacin Actualizar software del
controlador....

Seleccione Buscar software del controlador en el equipo.

Haga clic en el botn Examinar..., seleccione la carpeta sdk\extras\


google\usb_driver\ y haga clic en Siguiente.

Por ltimo, haga clic en el botn Instalar.

Se efectuar la instalacin del controlador. 48


Windows 7

Es preciso instalar un controlador USB sobre el puesto de desarrollo para reconocer dispositivos
Android.

Descrguelo mediante la herramienta Android SDK and AVD Manager vista anteriormente. El
paquete se llama Google USB Driver package y se encuentra en Third party Add-ons y a
continuacin Google Inc.

Conecte el dispositivo Android al puesto de desarrollo utilizando un cable USB. Windows


detecta automticamente el dispositivo e intenta instalarlo.

Abra el men Inicio y seleccione Panel de control.

Seleccione Hardware y sonido y a continuacin Administrador de


dispositivos (bajoDispositivos e impresoras).

Haga clic con el botn derecho sobre la lnea Perifrico USB compuesto que muestra un
pequeo icono de alerta en la lista y seleccione a continuacin Actualizar software del
controlador....

Seleccione Buscar software del controlador en el equipo.

Haga clic en el botn Examinar..., seleccione la carpeta sdk\extras\


google\usb_driver\ y haga clic en Siguiente.

Por ltimo, haga clic en el botn Instalar.

Se efectuar la instalacin del controlador.

Ubuntu

Desconecte el dispositivo Android del puesto de desarrollo si est conectado.

Abra una consola y ejecute el comando lsusb.

$ lsusb
Bus 001 Device 002: ID 80ee:0021
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

Conecte el dispositivo Android al puesto de desarrollo utilizando un cable USB.

Ejecute de nuevo el comando lsusb. Aparece una nueva lnea asociada al dispositivo
Android.

$ lsusb
Bus 001 Device 003: ID 18d1:4e12 Google Inc. Nexus One Phone
Bus 001 Device 002: ID 80ee:0021
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

En esta nueva lnea, anote el cdigo de fabricante que se corresponde con los cuatro primeros
caracteres situados tras ID. En nuestro ejemplo, este cdigo es 18d1.

Desconecte el dispositivo Android del puesto de desarrollo.

Para que Ubuntu pueda reconocer un dispositivo Android, es preciso proporcionar un archivo de
reglas que contengan la configuracin USB correspondiente a este dispositivo.

Conctese como root.


Cree el archivo /etc/udev/rules.d/##-android.rules reemplazando ## por 70para
las versiones de Ubuntu 9.10 y superiores, y por 51 para las versiones inferiores.

Inserte en el archivo la siguiente lnea correspondiente a la versin de Ubuntu del puesto de


49
desarrollo:

Ubuntu 10.10 y superiores:

SUBSYSTEM==usb, ATTR{idVendor}==18d1, MODE=0666

Ubuntu 7.10 a 10.04:

SUBSYSTEM==usb, SYSFS{idVendor}==18d1, MODE=0666

Ubuntu 7.04 e inferiores:

SUBSYSTEM==usb_device, SYSFS{idVendor}==18d1, MODE=0666

Reemplace en esta lnea el cdigo 18d1 por el cdigo de fabricante correspondiente al


dispositivo Android anotado anteriormente, o seleccinelo de la siguiente lista:

Fabricante Cdigo

Acer 0502

Dell 413c

Foxconn 0489

Garmin-Asus 091E

Google 18d1

HTC 0bb4

Huawei 12d1

Kyocera 0482

LG 1004

Motorola 22b8

Nvidia 0955

Pantech 10A9

Samsung 04e8

Sharp 04dd

Sony Ericsson 0fce

ZTE 19D2

Ejecute el siguiente comando reemplazando ##-android.rules por el nombre del archivo


creado anteriormente.

$ chmod a+r /etc/udev/rules.d/##-android.rules

Reinicie el demonio udev para que tenga en cuenta este nuevo archivo de reglas utilizando
uno de los siguientes comandos:

$ sudo reload udev


$ sudo service udev reload
$ sudo restart udev

Vuelva a conectar el dispositivo Android al puesto de desarrollo.


50
Verificacin de la conexin

Llegados a este punto, es importante verificar que el entorno de desarrollo reconoce bien el
dispositivo Android conectado.

Abra una consola y ejecute el siguiente comando:

$ adb devices

El cliente adb se encuentra en la carpeta sdk/platform-tools. Por comodidad, se


recomienda agregar esta ruta a la variable PATH del sistema.

Debe aparecer la siguiente respuesta, con un identificador del dispositivo distinto al indicado aqu. Si
tal es el caso, el dispositivo Android ha sido detectado correctamente.

List of devices attached


HT018PXXXXXX device

Las combinaciones en las configuraciones del entorno de desarrollo y los dispositivos Android
son tan numerosas, que es posible que el dispositivo no se reconozca. En este caso, tras
verificar que se han seguido correctamente las instrucciones, se recomienda realizar alguna
bsqueda en lnea. Otros usuarios habrn tenido seguramente el mismo problema y le ofrecern
sin duda alguna solucin.

Ejecutar la aplicacin

Lance la ejecucin de la aplicacin en el dispositivo.

La aplicacin se carga rpidamente y se ejecuta automticamente.

Si aparece la pantalla de desbloqueo, es preciso desbloquear el dispositivo antes de poder


ver la aplicacin.

51
Estructura de un proyecto Android
Descubriremos ms adelante qu contiene el proyecto creado y, de forma ms general, qu constituye
un proyecto Android.

Un proyecto Android contiene varias carpetas y algunos archivos de configuracin en su raz. En la vista
Explorador de Eclipse, tenemos los elementos siguientes.

La carpeta src contiene el cdigo fuente Java del proyecto.

La carpeta gen contiene los archivos generados automticamente por el plug-in ADT, como
el archivo R.java. Este ltimo permite identificar fcilmente los recursos del proyecto desde el cdigo
Java asociando una constante con el identificador nico de un recurso.

La carpeta Android o Google APIs incluye el SDK de la versin concreta de compilacin tras la
creacin del proyecto.

La carpeta assets permite almacenar archivos de datos brutos como, por ejemplo, archivos MP3. La
aplicacin podr a continuacin leer estos archivos en su formato original bajo la forma de flujo de
bytes. El formato del archivo se conserva tal cual.

La carpeta res contiene todos los archivos de recursos de la aplicacin clasificados en las subcarpetas
segn su tipo (vase Los recursos). Estos archivos, a diferencia de los que se almacenan en la
carpeta assets, pueden modificarse para optimizarse durante la compilacin del proyecto.

El archivo AndroidManifest.xml es el archivo de manifiesto del proyecto. Este archivo se describe


un poco ms adelante.

El archivo default.properties contiene las propiedades del proyecto. Este archivo no debe
editarse de forma manual dado que se actualiza automticamente cuando el desarrollador edita las
propiedades del proyecto mediante la interfaz de Eclipse haciendo clic con el botn derecho en el
nombre del proyecto Android, y a continuacin Propiedades.

Existe tambin la carpeta bin, que no se muestra en Eclipse, y que contiene los archivos
compilados y el archivo binario final de la aplicacin. La carpeta libs puede agregarse para
incluir bibliotecas de terceros.

1. El manifiesto
El archivo AndroidManifest.xml es el archivo de manifiesto del proyecto. Contiene la
configuracin principal de la aplicacin.

En lo sucesivo en este libro, nos referiremos a este archivo llamndolo simplemente manifiesto.

El manifiesto es un archivo en formato XML. El desarrollador puede modificarlo directamente o utilizar


la vista que proporciona el plug-in ADT.

Este archivo permite, entre otros, indicar los componentes definidos por la aplicacin, el punto de
entrada principal, los permisos de seguridad necesarios de la aplicacin, las bibliotecas requeridas,
los entornos de sistema y de hardware compatibles para que funcione la aplicacin

Cualquier componente definido por la aplicacin como, por ejemplo, una actividad, un servicio
debe estar declarado en el manifiesto; sin l, el sistema Android no lo conocer y no
permitir por tanto usarlo.

Existen demasiadas etiquetas y atributos como para detallarlos todos en este libro. Muchos atributos
52
son opcionales. Slo algunos son obligatorios.

Las principales etiquetas y sus atributos se describirn conforme sea necesario en los captulos
dedicados a los componentes o a las funcionalidades que representan.

He aqu los primeros elementos que figuran en este archivo.

Sintaxis

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cadena de caracteres"
android:versionCode="entero"
android:versionName="cadena de caracteres">

<uses-sdk android:minSdkVersion="entero"
android:targetSdkVersion="entero"/>

<application android:icon="recurso gr!fico"


android:label="recurso texto">
<activity android:name="cadena de caracteres"
android:label="recurso texto">
<intent-filter>
<action android:name="cadena de caracteres" />
<category android:name="cadena de caracteres" />
</intent-filter>
</activity>
</application>

</manifest>

La primera lnea del archivo describe el formato del archivo y su codificacin.

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="es.midominio.android.miapli"
android:versionCode="1"
android:versionName="1.0">

<uses-sdk android:minSdkVersion="8"
android:targetSdkVersion="11" />

<application android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".MiActividadPrincipal"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

En este ejemplo, el contenido de la etiqueta intent-filter de la actividad indica que esta


actividad es el componente principal de la aplicacin, es decir la que hay que ejecutar para iniciar la
aplicacin, y que puede aparecer en las aplicaciones que contienen el inventario de actividades
principales, como la aplicacin Lanzador de aplicaciones del sistema Android. Todo esto se describe
con ms detalle en los captulos siguientes. 53
a. Etiqueta manifest

La etiqueta raz del archivo es la etiqueta manifest. Contiene directa o indirectamente a todas las
dems etiquetas.

Incluye varios atributos. El primero xmlns:android define el espacio de nombres Android que se
utilizar en el archivo. Su valor debe ser obligatoriamente
http://schemas.android.com/apk/res/android.

El atributo package contiene el paquete de la aplicacin que se solicit durante la creacin del
proyecto. Es el identificador nico de la aplicacin y debe respetar el formato estndar para los
nombres de dominio.

A continuacin vienen
los atributos android:versionCode y android:versionName querepresentan en nmero y
letra la versin de la aplicacin (vase el captulo Publicar una aplicacin - Preliminares).

b. Etiquetas uses-sdk

La etiqueta uses-sdk permite indicar las versiones del SDK sobre las que podr ejecutarse la
aplicacin. Android utiliza los valores de los atributos de esta etiqueta para autorizar o no la
instalacin de la aplicacin. El Android Market las utiliza tambin para filtrar las aplicaciones
compatibles con el sistema Android del dispositivo del usuario.

El atributo android:minSdkVersion indica el nivel mnimo de API requerido por la aplicacin.


Este valor depende de las API utilizadas por la aplicacin. Es importante tener en cuenta que cuanto
menor sea este valor mayor ser el nmero de sistemas Android que podrn ejecutar la aplicacin.
Aunque en este caso, la aplicacin no podr utilizar las novedades aportadas por las ltimas
versiones de la API. Es preciso encontrar el equilibrio adecuado entre la eleccin de la API que se
quiere utilizar y las versiones de los sistemas Android candidatos.

Preste atencin y verifique bien que el valor del atributo android:minSdkVersion no es


demasiado bajo respecto a las API utilizadas, pues si la aplicacin utiliza una API de alguna
versin superior a la especificada en el atributo android:minSdkVersion, la aplicacin no
funcionar en un sistema Android de alguna versin que no contenga la API utilizada.

Si aparece el atributo android:targetSdkVersion, indica el nivel de API utilizado durante el


desarrollo de la aplicacin y sobre el que se ha probado la aplicacin. El sistema Android utiliza este
atributo para determinar si es preciso o no agregar, en algn caso, mecanismos de compatibilidad.
Si el sistema posee la misma versin que este atributo, el sistema Android no hace nada. En caso
contrario, puede agregar mecanismos de compatibilidad. Esto permite a nuestra aplicacin aplicar
por defecto el tema grfico del sistema de esta versin y ser compatible con los tamaos y
densidades de pantalla de esta versin del sistema.

c. Etiqueta application

La etiqueta application contiene informacin sobre la propia aplicacin. Existen dos atributos
esenciales. Se trata de los atributos android:icon y android:label que permiten especificar
respectivamente el icono y el ttulo de la aplicacin. Este icono y este ttulo se utilizarn para
representar a la aplicacin en diversos lugares, como por ejemplo el propio dispositivo Android o el
Android Market.

Si bien el atributo android:label acepta directamente cadenas de caracteres, se


aconseja indicar solamente referencias a recursos. Esto presenta mltiples ventajas: la
separacin entre cdigo y recursos, o la traduccin automtica de la cadena de caracteres...

Esta etiqueta contiene etiquetas que describen los componentes de la aplicacin. Se trata, entre
54
otros, de las etiqueta activity, service, provider, receiver y uses-library. Estas
etiquetas y sus atributos se estudiarn conforme avancemos a lo largo del libro.

2. Los recursos
Los recursos de una aplicacin Android son los datos que utiliza. Puede tratarse de una imagen como
un icono de la aplicacin, un sonido, un texto como el ttulo de la aplicacin...

Estos recursos se incorporan en formato binario a la aplicacin. Forman parte integrante del proyecto
Android y deben almacenarse en subcarpetas dentro de la carpeta res segn el tipo de datos que
contengan.

res/anim: animaciones de transicin definidas por archivos con formato XML.

res/color: colores con varios estados definidos en archivos con formato XML.

res/drawable: imgenes con formatos 9-Patch, PNG, GIF, JPEG y BMP y diseos de
tipo Drawable definidos en archivos con formato XML.

res/layout: descripciones de interfaces grficas definidas en archivos con formato XML.

res/menu: mens de distintos tipos definidos en archivos con formato XML.

res/raw: datos brutos, idnticos a los que pueden almacenarse en la carpeta assets del
proyecto, pero accesibles nicamente mediante su identificador nico de recurso.

res/values: valores simples de distintos tipos como, por ejemplo, cadenas de caracteres, valores
enteros contenidos en archivos con formato XML. Cada uno de estos valores es accesible mediante
su identificador nico de recurso.

Si bien los nombres de los archivos contenidos en la carpeta res/values se dejan a la eleccin
del desarrollador y los archivos que puede contener corresponden a distintos tipos de recursos
sencillos, es habitual clasificar los recursos en archivos independientes segn su tipo. Los
nombres de estos archivos se corresponden con el tipo de recurso que contienen. Por
ejemplo,strings.xml para recursos de tipo string, arrays.xml para
los array, colors.xmlpara los color...

res/xml: archivos XML diversos, en particular archivos de configuracin de componentes, que se


leen en tiempo de ejecucin.

Todas estas carpetas no se crean por defecto. Es preciso crearlas a medida que se van
necesitando.

No es posible crear subcarpetas en estas subcarpetas para organizar todava mejor los
recursos... lo cual puede resultar algo molesto en proyectos que utilicen una gran cantidad de
recursos del mismo tipo.

Por defecto, un nuevo proyecto incluir las carpetas res/drawable-hdpi, res/drawable-


mdpi y res/drawable-ldpi. De forma general, los trminos que aparecen tras el guin
determinan la configuracin de software o hardware en la que podrn utilizarse los recursos
contenidos en su carpeta correspondiente. Los trminos hdpi, mdpi y ldpi en particular, describen
la categora de densidad de pantalla, y se estudiarn con mayor detalle en el siguiente captulo.

Destaquemos no obstante que ms all de los recursos de tipo Drawable, cualquier recurso puede
verse afectado por una configuracin concreta de software o hardware. Para ello, el nombre de la
carpeta de recursos debe completarse por el o los calificativos correspondientes separados por
guiones. Existe un gran nmero de calificativos disponibles
55 que representan el tamao de la pantalla,
la densidad de la pantalla, la lengua del sistema, la orientacin de la pantalla Descubriremos
algunos en los siguientes captulos.

Sintaxis

tipo_de_recurso[-calificativo_1]...[-calificativo_n]

Ejemplo

res/drawable-hdpi

res/drawable-es-hdpi

En este ejemplo, el ltimo caso corresponde con recursos de tipo Drawable que se utilizarn en un
sistema cuya pantalla posea alta densidad de pxeles y en el que la lengua del sistema sea el
espaol.

Se recomienda que cada recurso disponga de una opcin por defecto. Es decir que el recurso
debe figurar como mnimo en su carpeta de recurso por defecto, que es la que no lleva ningn
calificativo. Por ejemplo, todo recurso de tipo imagen debe figurar como mnimo en la
carpeta res/drawable. Esto permite asegurar la compatibilidad de la aplicacin en las versiones
anteriores de Android.

Cada recurso de la carpeta res posee su propio identificador nico. Es el nico medio por el que es
posible invocar al recurso desde el cdigo Java o desde cdigo XML. Se trata de un valor entero que
se genera automticamente. Este valor permite a mltiples mtodos identificar fcilmente los recursos
a utilizar. No obstante este valor puede cambiar con cada compilacin conforme se agreguen o
eliminen recursos.

Para no tener que incluir estos valores en duro en el cdigo y tener que cambiarlos durante el
desarrollo con cada modificacin, se genera automticamente una clase Java R que realiza la
correspondencia entre los valores enteros de los identificadores nicos y sus constantes asociadas.

Estas constantes, estticas y pblicas, se definen en las subclases de la clase R correspondientes a


los distintos tipos de recursos.

En lo sucesivo, un desarrollador no tiene ms que utilizar estas constantes, cuyo nombre no cambia
automticamente, en lugar de los valores enteros en el cdigo Java.

El nombre completo de estas constantes Java est compuesto por el nombre del paquete donde
estn ubicadas, el tipo y el nombre del recurso. El nombre del paquete puede omitirse si se trata del
paquete en curso.

El tipo de recurso se corresponde con el nombre de la subcarpeta de la carpeta res que contiene el
recurso. El nombre del recurso es el nombre del archivo sin su extensin.

Esta sintaxis es vlida para todos los recursos a excepcin de aquellos ubicados en la
carpeta res/values. Para estos ltimos, el tipo de recurso es el nombre de la etiqueta que define el
recurso. Y el nombre del recurso es el nombre especificado por el atributo name de la etiqueta
correspondiente al recurso.

Sintaxis en cdigo Java

[paquete.]R.tipo.nombre

Ejemplos

R.drawable.icono

R.layout.main

R.string.mensaje
56
R.color.rojo

Ocurre lo mismo con los archivos de recursos. Para no tener que escribir estos datos en duro en
ciertos archivos de recursos, es posible referenciar a los recursos desde el cdigo XML. La sintaxis del
tipo y el nombre de los recursos es la misma que hemos visto anteriormente.

Sintaxis en cdigo XML

@[paquete:]tipo/nombre

Ejemplos

@drawable/icono

@layout/main

@string/mensaje

@color/rojo

En lo sucesivo en este libro, el trmino identificador nico o identificador, ms corto, har referencia al
nombre completo de la constante asociada al valor entero como, por ejemplo,R.string.mensaje.

57
5. Descubrir la
interfaz de usuario

58
Introduccin
Las aplicaciones Android proporcionan, la mayor parte de ellas, una interfaz de usuario. sta va a
permitir una interaccin bidireccional entre el usuario y la aplicacin de forma visual, tctil y sonora.

Es habitual hablar de clic para designar la accin de presionar y levantar la presin rpidamente
sobre un botn de un dispositivo de tipo puntero como, por ejemplo, un ratn. Este trmino hace
referencia al ruido producido por esta accin. O, en el caso de las pantallas tctiles, el dispositivo
para marcar es el dedo del usuario. El uso del trmino clic en estos casos parece menos apropiado.
Esto es porque se usan otras acciones, como por ejemplo tocar la pantalla, dar golpecitos o
presionar la pantalla, en lugar de hacer clic. Este libro se centra en los dispositivos Android en
general, que pueden o no poseer una pantalla tctil, como por ejemplo los notebooks. Por ello, se
utilizar indistintamente los trminos hacer clic y presionar, designando a la misma accin.

Como veremos en el captulo Componentes principales de la aplicacin, una aplicacin Android que
incluye una interfaz de usuario est compuesta por una o varias actividades. De momento,
quedmonos con la idea de que una actividad se corresponde con lo que se llamara una pgina de la
pantalla. Una pgina de la pantalla puede verse como una pgina web por ejemplo, con su interfaz
grfica: texto, botones, imgenes...

Android proporciona una gran cantidad de componentes para ayudar en la construccin de dichas
interfaces. En este captulo vamos a descubrir los principales componentes que son las vistas, los
layouts (contenedores de vistas), los widgets (componentes), los mens

Pero antes, comencemos viendo cmo el sistema Android permite realizar aplicaciones que funcionan
sobre todo tipo de pantallas.

59
Pantallas
Una de las particularidades del sistema Android es que puede adaptarse a un gran nmero de configuraciones de hardware diferentes.

El elemento ms visible que pone de manifiesto este hecho es sin duda la pantalla, y en concreto su tamao. Esto abarca desde un
pequeo smartphone donde la diagonal de la pantalla mide 6,5 cm hasta la tableta tctil de 30 cm pasando por un gran nmero de
dispositivos de tamao intermedio, sin contar los televisores que cuentan con el sistema Google TV basado en Android...

No obstante el tamao es slo una de las caractersticas de la pantalla. La resolucin de la pantalla es otra, yendo por lo general de la
mano de la primera. De este modo, en la mayor parte de casos, cuanto mayor sea el tamao de la pantalla, mejor ser la resolucin
ofrecida. Encontramos por tanto dispositivos Android con una resolucin no muy grande de 240 x 320 pxeles (QVGA) hasta aquellos
que tienen una de 1366 x 768 pxeles (WXGA con formato 16/9) o incluso 1280 x 800 pxeles (WXGA con formato 16/10).

En pocas palabras, vemos que el sistema Android puede funcionar en muchas y muy diversas configuraciones de pantalla. En lo
sucesivo una aplicacin pensada para una pantalla de smartphone de poca resolucin tendr un aspecto mediocre en la inmensidad de
una pantalla ms grande de alta resolucin. Con el objetivo de ofrecer al usuario la mejor experiencia posible en cuanto al uso de la
aplicacin, el desarrollador deber arreglrselas para que la aplicacin se adapte tambin a los distintos tamaos y resoluciones de
pantalla de los dispositivos Android sobre los que se puede ejecutar la aplicacin.

Android clasifica las pantallas segn el tamao de su diagonal en cuatro


categoras: small(pequea), normal (normal), large (grande) et xlarge (muy grande). Esta ltima categora existe desde
Android 2.3 (API 9). Encontraremos por ejemplo pantallas de unos 6,35 cm (2,5 pulgadas) de tamao de diagonal en la categora de
pantallas pequeas, de unos 10 cm (4 pulgadas) en la categora de pantallas normales, de unos 18 cm (7 pulgadas) en la categora de
pantallas grandes y de unos 25 cm (10 pulgadas) en la categora de pantallas muy grandes.

En una misma categora pueden coexistir varias resoluciones. Si bien para una misma superficie de pantalla el nmero de pxeles puede
variar sensiblemente. El nmero de pxeles de una superficie determina su densidad. Se expresa en puntos por pulgada llamados dpi
(dots-per-inch).

Android clasifica as las pantallas en cuatro categoras segn su densidad de pxeles: ldpi (baja),mdpi (media), hdpi (alta)
y xhdpi (muy alta). Esta ltima categora existe desde Android 2.2 (API 8). Encontraremos por ejemplo valores de 120 dpi en la
categora de densidades bajas, 160 dpi en la categora media, 240 dpi en la categora alta y 320 dpi en la categora muy alta. Estos
valores de densidad pueden servirnos como referencia.

Es posible conocer las caractersticas de la pantalla, como su resolucin y su densidad. Para ello, hay que utilizar el
mtodo getWindowManager desde una actividad para recuperar la instancia del gestor de ventana. La llamada al
mtodo getDefaultDisplay sobre esta instancia permite a continuacin recuperar un objeto de tipo Display que contiene la
informacin solicitada. Slo queda recuperarla en un objeto de tipo DisplayMetrics utilizando el mtodo getMetrics.

Ejemplo

Aun as, para un tamao de


DisplayMetrics metrics = new DisplayMetrics(); pantalla estrictamente igual,
getWindowManager().getDefaultDisplay().getMetrics(metrics); un botn de 100 pxeles de
int densidadDpi = metrics.densityDpi; largo, por ejemplo, tendr un
int resolucionX = metrics.widthPixels; tamao de visualizacin
int resolucionY = metrics.heightPixels; diferentes si las resoluciones
son diferentes. Para evitar
esto, Android recomienda utilizar una nueva unidad: el dp o dip (density-independent pixel) o pxel independiente de la densidad.

No confundir dpi y dip!

El sistema se encarga de convertir un valor en dip en nmero de pxeles fsicos teniendo en cuenta la densidad de la pantalla. La
dimensin fsica resultante ser la misma sea cual sea la densidad de la pantalla. Es decir, el botn tendr el mismo tamao fsico en
todas las pantallas.

En Android, las dimensiones pueden especificarse en distintas unidades. En la siguiente tabla se muestra un inventario de estas
unidades:

Unidad Descripcin

dp o dip (density-independent pixel).


Unidad independiente de la densidad de la pantalla.

sp o sip (scale-independent pixel).


Unidad dependiente del tamao preferido para la fuente de caracteres.
Esta unidad se utiliza para ajustar el tamao de la letra en cadenas de
caracteres.

px Pixel. Unidad grfica mnima.

in Pulgada. Unidad de medida que vale 2,54 cm.

mm Milmetro.

Con el objetivo de no confundir dip y dpi, es preferible utilizar nicamente dp y sp.

Para que una aplicacin pueda adaptarse correctamente a todos los tipos de pantalla, tamaos
y resoluciones, se recomienda encarecidamente utilizar nicamente dimensiones independientes
de la densidad, es decir especificadas en dp, en dip, en sp o en sip.
60
Es posible especificar distintas variantes de una misma imagen segn la densidad de la pantalla. Android buscar el recurso que se
corresponda con la categora de densidad de la pantalla en curso. Si existe, la utilizar. Si no, Android buscar este recursos para otra
densidad, de forma prioritaria en las densidades mayores que la actual. Una vez encontrado, el sistema lo redimensionar utilizando
cierto factor.

Para conocer el factor a aplicar, el sistema utiliza la siguiente escala indicando los distintos ratios: 3-4-6-8 que se corresponden
respectivamente con las distintas densidades: ldpi, mdpi, hdpi yxhdpi.

Por ejemplo, si la densidad de la pantalla es alta (hdpi) y el recurso no existe en esta densidad ni en una densidad superior (xhdpi),
el sistema puede utilizar la densidad media (mdpi) suponiendo que exista. A continuacin el sistema modifica automticamente su
tamao aplicando un factor de 1,5, es decir 6/4, para las densidades altas (hdpi). Si la pantalla tiene una densidad baja (ldpi), el
factor utilizado es 0,75, es decir 3/4.

El desarrollador que quiera aportar imgenes dedicadas a una categora de densidades especfica podr utilizar los mismos coeficientes
multiplicadores para determinar el tamao que quiere proporcionar para estas densidades.

Por ejemplo, si aporta una imagen de 100x100 pxeles para una densidad normal (mdpi) y quiere ofrecer una para una densidad alta,
esta imagen deber tener un tamao de 150x150 pxeles, aplicando un coeficiente multiplicador de 1,5.

Como ya se ha visto en el captulo anterior, es posible proporcionar distintas variantes de una misma imagen segn la densidad de la
pantalla que se est utilizando. Para ello, estas variantes deben estar repartidas en distintas subcarpetas drawable de la
carpeta res donde el calificativo que compone el nombre de la subcarpeta es la categora de densidad de la pantalla.

Los recursos que se encuentran en la carpeta res/drawable estn considerados recursos


para una densidad media (mdpi).

Sintaxis

drawable-categora_densidad

Ejemplo

res/drawable-hdpi/icon.png

res/drawable-ldpi/icon.png

res/drawable-mdpi/icon.png

Desde Android 1.6 (API 4), es posible utilizar la etiqueta supports-screen en el manifiesto para indicar al sistema, y de forma
accesoria en Android Market, con qu categoras de tamao de pantalla es compatible la aplicacin.

A cada una de estas categoras le corresponde un atributo de esta


etiqueta:android:smallScreens, android:normalScreens, android:largeScreens yandroid:xlargeScreens. stas
toman un valor booleano que indica si la aplicacin soporta la categora correspondiente o no. Si no es el caso, el sistema busca la
mejor solucin de visualizacin compatible posible y convierte automticamente las dimensiones para adaptarlas a la pantalla utilizada.

Los valores por defecto de estos atributos dependen de los valores de


los atributos android:minSdkVersion y android:targetSdkVersion. En lo sucesivo,
lo ms sencillo es indicar estos valores explcitamente en el manifiesto para evitar cualquier
ambigedad.

El atributo android:anyDensity toma un valor booleano que indica si la aplicacin ha sido diseada de forma independiente a la
densidad, o ms concretamente si utiliza dimensiones de tipo dp o sp o bien convierte las dimensiones especificadas en pxeles. En
caso contrario, el sistema ejecutar la aplicacin en un modo de compatibilidad.

Recuerde, se recomienda encarecidamente realizar aplicaciones cuya interfaz sea independiente


de la densidad de la pantalla.

Sintaxis

<supports-screens
android:smallScreens="booleano"
android:normalScreens="booleano"
android:largeScreens="booleano"
android:xlargeScreens="booleano"
android:anyDensity="booleano"
...
/>

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="es.midominio.android.miapli"
61
android:versionCode="1"
android:versionName="1.0">

<uses-sdk android:minSdkVersion="8"
android:targetSdkVersion="11" />

<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true" />

<application android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".MiActividadPrincipal"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</manifest>

62
Modo programtico y modo declarativo
Para construir una interfaz de usuario, el desarrollador cuenta con dos tcnicas:

El modo programtico: la interfaz se construye escribiendo cdigo Java directamente en el


cdigo Java de la aplicacin. Este modo permite generar la interfaz dinmicamente pero tiene el
inconveniente de mezclar el cdigo de diseo de la interfaz con el cdigo de la aplicacin.

El modo declarativo: la interfaz se construye escribiendo cdigo XML en archivos XML


separados. Este modo permite aislar el cdigo de la interfaz de usuario del cdigo de la
aplicacin en Java.

Ambos modos no son excluyentes. Pueden utilizarse igual de bien tanto de forma separada como
combinados en conjunto para sacar el mximo provecho de las ventajas de cada uno de ellos.

En Eclipse, el plug-in ADT que hemos instalado anteriormente permite habilitar pestaas
suplementarias correspondientes a distintas vistas del archivo en edicin.

Por ejemplo, al abrir un archivo de layout (vase la seccin Layouts en este captulo) permite editar el
archivo al mismo tiempo mediante un editor de cdigo XML y mediante una interfaz grfica
llamadaGraphical Layout.

Editor XML

63
Editor XML

No dude en descubrir las vistas asociadas a otros tipos de archivo.

64
Vistas
El elemento bsico de la interfaz de usuario es la vista (clase View).
Todos los dems elementos de la interfaz de usuario heredan de la clase View. Este es el caso, en
particular, de la clase ViewGroup que es una vista que permite contener a otras vistas. Se le
denomina contenedor de vistas.

En lo sucesivo, la interfaz de usuario de una actividad estar compuesta por un conjunto de vistas y
contenedores de vistas. Dada una actividad, se tendr por ejemplo una jerarqua de vistas del tipo:

Jerarqua de vistas de una actividad

Esta jerarqua permite ordenar la visualizacin de las vistas. La vista que se encuentra en la raz de la
jerarqua se dibuja en primer lugar. Si se trata de un contenedor de vistas, entonces el contenedor
solicita a sus vistas hijas que se dibujen y as recursivamente hasta haber dibujado todas las vistas.

Una vista posee propiedades. Todas las clases que heredan de la clase View heredarn estas
propiedades. Veamos las principales:

Propiedad Descripcin

android:background Elemento a utilizar para el fondo de la vista


(imagen, color...).

android:clickable Especifica si la vista reacciona a los clics.

android:id Identificador nico de la vista.

android:minHeight Altura mnima de la vista.

android:minWidth Longitud mnima de la vista.

android:onClick Nombre del mtodo de la actividad a ejecutar


cuando el usuario hace clic en la vista.

android:padding Dimensin del margen interno para los cuatro


lados de la vista.

android:paddingBottom Dimensin del margen interno inferior de la vista.

android:paddingLeft Dimensin del margen interno izquierdo de la vista.

65
android:paddingRight Dimensin del margen interno derecho de la vista.

android:paddingTop Dimensin del margen interno superior de la vista.

android:tag Permite asociar un objeto a la vista.

android:visibility Especifica la visibilidad de la vista.

El atributo android:tag puede presentar distintos roles y revelarse de gran utilidad en un


buen nmero de situaciones. Se trata de una propiedad que se deja al buen uso del
desarrollador. Por ejemplo, permite asociar un dato a una vista.

66
Layouts
Los layouts son contenedores de vistas (ViewGroup) predefinidos ofrecidos por Android. Cada layout
proporciona un estilo de representacin en pgina distinto permitiendo a las vistas posicionarse las
unas respecto a las otras o respecto al contenedor padre.

Los principales layouts predefinidos


son FrameLayout, LinearLayout, RelativeLayout,TableLayout. Ofrecen respectivamente
una estructura de posicionamiento de las vistas en marco, lineal, relativa y en forma de tabla.

FrameLayout

Contenedor reducido a su mnima expresin. Todo lo que contiene se dibujar a partir de la esquina
superior izquierda. Los ltimos elementos hijos agregados se dibujarn debajo de los ms antiguos.

LinearLayout

Contenedor en el que los elementos hijos se disponen en funcin del valor del atributo de orientacin:

Verticalmente, los unos bajo los otros, un nico elemento por lnea.

Horizontalmente, los unos a continuacin de los otros, a la derecha del anterior.

RelativeLayout

Contenedor en el que las posiciones de las vistas hijas estn determinadas respecto a la vista padre o
respecto a otras vistas hijas.

TableLayout

Contenedor en el que los elementos hijos se disponen en forma de tabla. Las vistas hijas son
objetos TableRow que definen cada uno una lnea de la tabla. Los elementos hijos de los
objetos TableRow son celdas de la tabla.

1. Modo declarativo
El modo declarativo es el modo ms sencillo para declarar la interfaz de usuario de una pantalla.
Veamos en primer lugar cmo declarar este layout y, a continuacin, cmo utilizarlo.

a. Declaracin del layout

La primera etapa consiste en crear un archivo con formato XML, en la carpeta res/layout del
proyecto.

Recuerde (vase el captulo Primeros pasos - Estructura de un proyecto Android), el nombre de la


carpeta layout puede especializarse para filtrar el uso de los layouts segn ciertas caractersticas.
En posible en particular proveer distintos layouts para una misma pantalla, a modo de interfaz,
segn la categora del tamao de la pantalla fsica. Para ello, el calificador que debe usarse es el
nombre de la categora correspondiente al tamao de pantalla.

Los recursos que se encuentran en la carpeta res/layout estn clasificados como recursos
para pantallas con tamaos normales (normal).

Ejemplo

res/layout-small/principal.xml

67
res/layout-normal/principal.xml

res/layout-xlarge/principal.xml

Tambin es posible crear layouts distintos segn la orientacin de la pantalla. El calificativo que
debe especificar es port para el modo vertical y land para el modo apaisado. Es posible combinar
las distintas categoras de calificadores para afinar al mximo el filtrado.

Ejemplo

res/layout-port/principal.xml

res/layout-xlarge-land/principal.xml

El archivo layout XML debe tener la sintaxis siguiente:

Sintaxis

<?xml version="1.0" encoding="utf-8"?>


<Tipo_de_layout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="dimensin"
android:layout_height="dimensin"
... >
...
</Tipo_de_layout>

La primera lnea describe la versin XML y la codificacin del archivo.

La segunda lnea especifica el tipo de layout deseado utilizando la etiqueta XML correspondiente. Se
especifican a continuacin las propiedades de esta etiqueta y, por tanto, del layout.

El layout raz de la pantalla debe especificar el atributo xmlns:android con el valor


asignado anteriormente para definir el espacio de nombres android que se utilizar para la
declaracin de los atributos.

Los atributos android:layout_width y android:layout_height son obligatorios, y se


produce una excepcin en caso contrario.

Los posibles valores de estos atributos son:

match_parent: la vista mide igual que la vista padre menos el valor del espaciado
(padding). Desde la versin 8 del SDK, este valor reemplaza al valor fill_parent.

wrap_content: la vista mide igual que las dimensiones de su contenido ms el valor del
espaciado (padding). Es decir, el tamao ms pequeo posible pero suficiente como para
mostrar su contenido.

una dimensin: la vista se dimensiona de forma precisa segn este valor. Una dimensin
descrita por un nmero, en coma flotante si fuera preciso, seguido de una unidad. Por
ejemplo: 42dp.

Recuerde, para que una aplicacin pueda adaptarse a cualquier tipo de pantalla, tamao y
resolucin, se recomienda encarecidamente utilizar nicamente dimensiones independientes
de la densidad. De este modo, para las dimensiones de un layout, se dar prioridad a los
valores match_parentwrap_content y a aquellas especificadas en dp.

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout
68
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</RelativeLayout>

En este ejemplo, la pantalla aplica un layout relativo cuyas dimensiones son las de la vista padre. Es
decir, en este caso la pantalla completa salvo por la barra de estado y la barra de ttulo en la parte
superior.

b. Uso del layout

Ahora que se ha definido el layout en el archivo XML, es preciso que lo utilice alguna actividad para
crear su interfaz de usuario. Para ello se utiliza el mtodo setContentView de la
clase Activity.

Sintaxis

public void setContentView (int layoutResID)

Este mtodo recibe como parmetro un nmero entero que es el identificador nico del layout.

Ejemplo

public void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);
setContentView(R.layout.principal);
}

En este ejemplo, la actividad en curso utiliza el archivo


llamado res/layout/principal.xmlpara construir la interfaz de usuario a visualizar tras la
creacin de la actividad.

Se especifica la constante R.layout.principal en lugar de indicar un nmero entero.


Recuerde, esta constante se genera automticamente en tiempo de compilacin del proyecto en el
archivo gen/paquete/R.java. Contiene el valor del identificador nico del layout principal. Este
valor puede cambiar con cada compilacin segn se agreguen o eliminen nuevos recursos,
volvindolo as inservible en s mismo. De ah que el uso de la constante permita al desarrollador
abstraerse del valor intrnseco.

2. Modo programtico
El modo programtico es el ms flexible y el ms potente de los dos modos. En contrapartida,
tambin es el ms complejo.

Permite generar dinmicamente la interfaz de usuario tras la creacin de la actividad. Tambin, y


principalmente, permite modificar esta interfaz durante la ejecucin de la aplicacin. Por ejemplo,
cuando un botn OK deshabilitado debe activarse cuando el usuario rellena todos los campos de un
formulario.

Creacin y uso del layout

Para crear un layout, es preciso instanciar un nuevo objeto de la clase del tipo de layout deseado.
Tomemos, por ejemplo, un layout relativo.

Sintaxis

public RelativeLayout (Context context)

Este constructor recibe como parmetro un contexto. De momento, quedmonos con la idea de que
69
un contexto sirve para reagrupar un conjunto de informacin asociada al entorno de la aplicacin. Y
que la clase Activity hereda indirectamente de la clase Context.

Una vez creado el objeto, hay que especificar sus dimensiones usando su
mtodo setLayoutParams.

Sintaxis

public void setLayoutParams (ViewGroup.LayoutParams params)

Este mtodo recibe como parmetro un objeto de tipo ViewGroup.LayoutParams. Es preciso


crear uno utilizando uno de sus constructores.

Sintaxis

public ViewGroup.LayoutParams (int width, int height)

Los parmetros width y height son nmeros enteros. Como hemos visto anteriormente, puede
ser un valor a escoger entre match_parent, wrap_content o una dimensin.

Para terminar, es preciso definir este layout como vista raz de la actividad para construir su interfaz
de usuario gracias al segundo mtodo setContentView que recibe esta vez como parmetro un
objeto de tipo View.

Sintaxis

public void setContentView (View view)

Ejemplo

public void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);

RelativeLayout layout = new RelativeLayout(this);


LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
layout.setLayoutParams(lp);
setContentView(layout);
}

En este ejemplo, el constructor RelativeLayout recibe como parmetro this dado que el
mtodo onCreate corresponde al de un objeto que hereda de la clase Activity, heredando ella
misma de la clase Context.

3. Combinacin de ambos modos


En la mayora de casos, es mejor declarar los layouts en modo declarativo de cara a separar la
interfaz de usuario del cdigo de la aplicacin. Se especifican los valores por defecto de los atributos
de las vistas declaradas que podremos modificar en tiempo de ejecucin de la aplicacin mediante el
modo programtico.

Esto nos permite tener una visin clara de la jerarqua de vistas establecida en el layout. Y esto
permite tambin poder especificar distintos layouts segn el tamao de la pantalla, la lengua utilizada
por el usuario sin tener que modificar el cdigo de la aplicacin.

De este modo, se aprovecha lo mejor de ambos modos. En lo sucesivo, en este libro, se dar
preferencia a esta forma de proceder para los layouts y dems componentes grficos.

70
Widgets
Un widget es un componente de la interfaz grfica que puede o no permitir la interaccin con el usuario.

Android proporciona un conjunto de componentes bsicos que permiten crear una interfaz grfica ms o menos compleja.

1. Declaracin
La declaracin de estos componentes se ve facilitada en los archivos de layouts con formato XML. La sintaxis de su declaracin es la
siguiente.

Sintaxis

<Tipo_de_widget
android:id="@[+][paquete:]id/nombre_recurso"
android:layout_width="dimensi n"
android:layout_height="dimensi n"
...
/>

La propiedad android:id permite asociar un identificador nico al componente. Se trata de una propiedad opcional pero, gracias a
este identificador, es sencillo recuperar el objeto correspondiente en el cdigo Java y modificarlo a continuacin. Es por este motivo por lo
que se indica aqu.

Generalmente, el valor del identificador nico tendr el formato @+id/nombre_recurso. El signo ms indica que se trata de un nuevo
identificador. Se le asignar un nuevo valor de forma automtica durante la generacin del archivo R.java.

2. Uso
Para poder utilizar el componentes desde el cdigo Java de la aplicacin, basta con utilizar elmtodo findViewById y pasarle como
parmetro el identificador nico del componente afectado. Este mtodo devuelve un objeto de tipo View que hay que convertir a
continuacin en el tipo de clase adecuado.

Sintaxis

public View findViewById (int id)

3. Descubrir algunos widgets


Sera demasiado extenso presentar de forma exhaustiva todos los componentes y todas sus propiedades. Ciertos componentes pueden
tener ms de cincuenta propiedades especficas.

Todos estos componentes forman parte del paquete android.widget.


Por ello, vamos a presentar nicamente los principales componentes grficos que proporciona Android y algunas de sus propiedades
principales.

En cada ocasin, mostraremos una captura de pantalla junto al trozo de cdigo utilizado en el ejemplo.

a. TextView (Campo de texto)

El componente TextView permite visualizar texto.

71
Componente TextView

Las principales propiedades del componente TextView son:

Propiedad Descripcin

android:autoLink Permite convertir automticamente los enlaces de


hipertexto y las direcciones de correo electrnico en
enlaces sobre los que es posible hacer clic.

android:ellipsize Especifica cmo debe mostrarse el texto cuando es


ms largo que la vista.

android:gravity Indica dnde debe estar posicionado el texto en la


vista cuando es ms pequeo que ella.

android:height Altura del componente.

android:lines Nmero exacto de filas que se desea mostrar.

android:maxHeight Altura mxima del componente.

android:maxLines Nmero mximo de filas que se desea mostrar.

android:maxWidth Longitud mxima del componente.

android:minLines Nmero mnimo de filas que se desea mostrar.

android:text Texto que se quiere mostrar.

android:textColor Color del texto.

android:textSize Tamao del texto.

android:textStyle Estilo del texto.

android:width Longitud del componente.

A saber: el componente TextView posee a su vez cuatro propiedades que permiten mostrar a
sus lados un recurso de tipo Drawable, como por ejemplo una imagen. stas son las
propiedades: android:drawableTop,android:drawableBottom, android:drawableLeft y android:drawableRight.

Ejemplo

Las propiedades del componente


<?xml version="1.0" encoding="utf-8"?> pueden modificarse en el cdigo
<RelativeLayout Java utilizando
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<TextView android:id="@+id/textview_mensaje"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
72
android:background="#FFF"
android:textColor="#000"
android:textSize="14sp"
android:maxLines="3"
android:gravity="center"
android:text="@string/mensaje" />

</RelativeLayout>

el mtodo findViewById como se ha visto anteriormente.

Ejemplo

En este ejemplo, modificamos el


public void onCreate(Bundle savedInstanceState) { texto del componente antes de
super.onCreate(savedInstanceState); mostrarlo.

setContentView(R.layout.textview);
TextView msg = (TextView) findViewById(R.id.textview_mensaje);
msg.setText(R.string.nuevo_mensaje);
}

El uso de colores para el fondo de las vistas permite verificar rpidamente las
dimensiones de las mismas.

b. EditText (Campo para introducir texto)

El componente EditText permite al usuario introducir texto. Cuando el usuario hace clic sobre el componente, aparece el teclado
virtual. El usuario puede utilizar tambin el teclado fsico si el dispositivo posee uno.

Componente EditText

Este componente hereda del componente TextView. Sus propiedades son las mismas que las del componente TextView. Las
principales propiedades utilizadas por este componente son:

Ejemplo
Propiedad Descripcin

android:inputType Permite filtrar el texto introducido por el


usuario especificando el tipo de dato
que acepta el componente.

android:scrollHorizontally Permite deslizar el texto horizontal


cuando es mayor que la longitud del
componente.

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<EditText android:id="@+id/edit_texto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
73
android:layout_margin="10dp"
android:background="#FFF"
android:textColor="#000"
android:lines="5"
android:gravity="top"
android:inputType="textMultiLine|textAutoCorrect"
android:text="@string/edit_texto"/>

</RelativeLayout>

c. Button (Botn)

El componente Button representa un botn sobre el que el usuario puede presionar y hacer clic. Es posible asociar acciones a estos
estados.

Componente Button

Este componente hereda del componente TextView. Sus propiedades son las mismas que las del componente TextView. Las
principales propiedades utilizadas por el componente son:

El uso de la
Propiedad Descripcin propiedad onClick implica la
android:text Texto a mostrar sobre el botn. creacin del mtodo
correspondiente en la clase de la
android:onClick Nombre del mtodo de la actividad a ejecutar cuando el actividad. Este mtodo debe
usuario hace clic sobre el botn. definirse pblicamente y recibir
como parmetro un objeto de
tipo View.

Sintaxis

public void nombreMtodo(View vistaAsociada)

Ejemplo

He aqu el
<?xml version="1.0" encoding="utf-8"?> mtodo onClickButton creado
<RelativeLayout en nuestra actividad.
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" En este ejemplo, cuando el
android:layout_height="match_parent" > usuario hace clic sobre el botn, la
propiedad onClick indica que es
<Button android:id="@+id/button1_pulse" preciso ejecutar el
android:layout_width="wrap_content" mtodo onClickButton. ste
android:layout_height="wrap_content"
recibe como parmetro la vista
android:layout_centerInParent="true"
afectada. Aqu, se trata de un
android:padding="50dp"
android:textSize="20sp" botn y por ello convertimos la
android:text="@string/pulse" vista en un botn para poder
android:onClick="onClickButton" /> modificar su texto.

</RelativeLayout> Existe una alternativa al uso de la


propiedad onClick que consiste
en declarar la accin en el cdigo
public void onClickButton(View view) { Java en lugar de en el cdigo XML.
((Button)view).setText(R.string.pulse);
74
} Para ello, se utiliza el

mtodo setOnClickListener del objeto botn para definir la accin a realizar cuando el usuario haga clic sobre el botn.

Sintaxis

public void setOnClickListener (View.OnClickListener l)

Este mtodo recibe como parmetro un objeto de tipo View.onClickListener. Es preciso crear uno e implementar su mtodo
abstracto onClick, donde se informar la accin a realizar.

Sintaxis

public void onClick (View v)

Ejemplo

A continuacin aparece la
<?xml version="1.0" encoding="utf-8"?> declaracin del evento a ejecutar:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<Button android:id="@+id/button2_pulse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:padding="50dp"
android:textSize="20sp"
android:text="@string/pulse" />

</RelativeLayout>

public void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);

setContentView(R.layout.button2);
final Button btn =
(Button) findViewById(R.id.button_pulse);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
btn.setText(R.string.pulse);
}
});
}

d. Y otros

Existen muchos otros componentes, ms o menos sofisticados. Hay disponibles, por ejemplo, casillas de opcin (CheckBox), botones
de radio (RadioButton), listas desplegables (Spinner), barras de progreso (ProgressBar), imgenes (ImageView)

En Android 3.0 (API 11) han aparecido nuevos componentes, en particular un calendario (CalendarView), una lista de eleccin en una
ventana flotante (ListPopupWindow) y un selector de nmero (NumberPicker).

75
6. Los fundamentos

76
Introduccin
Como se ha visto por encima hasta el momento, la actividad es un componente de la aplicacin
fundamental en un sistema Android. La estudiaremos con ms detalle en este captulo.

Pero antes, descubriremos las intenciones, que son el vnculo entre los distintos componentes de la
aplicacin en el sistema Android. Gracias a ellos, una aplicacin Android puede, en particular,
aprovechar otras aplicaciones instaladas en el sistema, incluso sin conocerlas. En efecto, las
intenciones se resuelven dinmicamente en tiempo de ejecucin del sistema.

Por ltimo decir que, en primer lugar, y aunque suene de forma repetida a lo largo de este libro, es
preciso aprehender bien una de las nociones ms importantes del sistema Android: es el sistema el
que gestiona el ciclo de vida de las aplicaciones. En concreto, es el sistema quien decide cundo se
destruye una aplicacin, especialmente en funcin de los recursos del sistema disponibles tales como
el procesador, la memoria o en funcin de la duracin de la inactividad del usuario... Por ello,
cualquier aplicacin desarrollada de manera seria, deber tener en cuenta todo esto.

Hecha esta advertencia, descubriremos a continuacin las intenciones y, ms adelante, las


actividades.

77
Intencin
Una de las grandes ventajas de Android es que no es preciso ligar entre s de manera esttica los
componentes de aplicacin, volvindolos as lo ms independientes posible. Este principio se lleva tan
lejos que permite incluso poder utilizar componentes de una aplicacin desde otra aplicacin sin
conocerlos en tiempo de desarrollo. Se escogern en tiempo de ejecucin de la aplicacin, bien por el
sistema, bien por el usuario.

Para poder hacer esto y comunicar de manera dinmica componentes entre ellos, Android proporciona
objetos de tipo Intent (intencin). Como su propio nombre indica, una intencin designa una accin a
realizar. Pero una intencin tambin puede describir un evento que acaba de producirse, como en el
caso de los receptores de eventos (vase el captulo Componentes principales de la aplicacin -
Receptor de eventos).

Un objeto de tipo Intent encapsula nicamente informacin, como por ejemplo un mensaje. Es
tarea del componente origen y del sistema hacer uso del mismo para explotar la intencin que
encierra.

Android proporciona nombres de accin genricos que se pueden utilizar tal cual. Por
ejemplo,android.intent.action.DIAL para iniciar una llamada telefnica.

El desarrollador puede, a su vez, crear sus propias acciones. Dado que las acciones pueden tener un
alcance global en el sistema, es preciso nombrar las acciones creadas precedindolas del nombre del
paquete de la aplicacin que las crea.

La accin de un objeto de tipo Intent puede especificarse y recuperarse utilizando los


mtodos setAction y getAction.ma

Sintaxis

public Intent setAction (String action)


public String getAction ()

El mtodo setAction devuelve el mismo objeto de tipo Intent con el objetivo de poder
encadenar llamadas entre distintos mtodos.

Para realizarse, la accin especificada en la intencin puede requerir datos. Tambin puede necesitar
informacin respecto a los datos que deben utilizarse o modificarse en la accin. Toda esta informacin
puede proporcionarse al objeto de tipo Intent bajo la forma de categora, de datos o de Extras.

La categora se utiliza para determinar el tipo de componente que debe realizar la accin. Existen
varias categoras por defecto. El desarrollador puede, incluso, definir nuevas categoras. Para agregar
una categora a una intencin, basta con invocar a su mtodo addCategory pasndole como
parmetro una cadena de caracteres que designe a la categora.

Sintaxis

public Intent addCategory (String category)

Los datos reagrupan la URI y el tipo MIME del dato afectado. El formato y el sentido de estos datos son
dependientes de la accin especificada en la intencin. En general, el tipo MIME puede deducirse de la
URI. He aqu los principales mtodos disponibles para especificar y recuperar esta informacin:

Sintaxis

public Intent setData (Uri data)


public Uri getData ()
public Intent setType (String type)
public String getType ()
78
El uso de setData y el de setType son concurrentes. Borran sus datos respectivamente.

Los Extras son otros datos de aplicacin que pueden incluirse en la intencin utilizando
el mtodo putExtras, y el mtodo getExtras para recuperarlos. Estos datos deben proporcionarse
bajo la forma de un objeto de tipo Bundle.

La funcin de la clase Bundle es similar a la de la clase Map, es decir almacena los datos, asociados
entre s bajo la forma clave-valor. A una clave le corresponde un nico valor que puede no obstante ser
una tabla de valores del mismo tipo. La clase Bundle slo acepta cadenas de caracteres como clave.
Los valores deben implementar la interfaz Parcelable, mecanismo de serializacin ligera especfico
de Android.

Preste atencin, la interfaz Parcelable y el tipo Parcel asociado no deben utilizarse para
serializar datos persistentes. La representacin interna de los datos puede modificarse con cada
versin del SDK.

Sintaxis

public Intent putExtras (Bundle extras)


public Bundle getExtras ()

Para mayor comodidad, la clase Intent proporciona una multitud de mtodos directos para especificar
los datos extras sin tener que pasar explcitamente por el objeto Bundle.

Sintaxis

public Intent putExtra (String name, int value)


public int getIntExtra (String name, int defaultValue)
public Intent putExtra (String name, String value)
public String getStringExtra (String name)
...

Por ltimo, el mtodo addFlags permite agregar flags a un objeto de tipo Intent, como veremos
ms adelante.

Sintaxis

public Intent addFlags (int flags)

Existen dos formas de escribir una intencin: de forma explcita o de forma implcita.

1. Intencin explcita
Una intencin explcita designa de forma precisa el componente concreto al que est destinada. De
hecho, escoge tambin la accin que quiere realizar. La intencin puede contener tambin la accin a
realizar en el caso en que el componente pueda realizar varias.

Uno de los usos ms comunes de las intenciones explcitas es la ejecucin de componentes de


aplicacin, en particular actividades, en el interior de una misma aplicacin.

El componente de destino se busca entre los componentes declarados en el manifiesto. De


este modo, si el componente no aparece en el archivo, no podr ser invocado.

En concreto, para crear una intencin explcita, es preciso crear un objeto de tipo Intent e indicarle
la clase de destino. Para ello, una solucin consiste en utilizar uno de los constructores de la
clase Intent. stos reciben como parmetro el contexto de la aplicacin y el nombre de la clase de
79
destino y devuelven el objeto de tipo Intent creado. Otro de los constructores permite especificar la
accin y los datos.

Sintaxis

public Intent (Context packageContext, Class<?> cls)


public Intent (String action, Uri data, Context packageContext,
Class<?> cls)

Ejemplo

Intent intent = new Intent(this, MiActividadDestino.class);

2. Intencin implcita
A diferencia de la intencin explcita, que designa al componente de destino, la intencin implcita
indica, en s misma, la accin a realizar. Encarga al sistema que encuentre el componente aplicativo
de destino que mejor se adapte para realizar esta accin, ubicado por lo general en otra aplicacin. Si
existen varios componentes al mismo nivel, el sistema solicitar al usuario que seleccione uno. Si el
sistema no encuentra ninguno, se generar una excepcin.

Descubramos en primer lugar cmo crear una intencin implcita y a continuacin cmo declaran los
componentes de aplicacin las intenciones implcitas a las que pueden responder.

3. Creacin
En particular, para crear una intencin implcita, es preciso crear un objeto de tipo Intent e indicarle
la accin a realizar. Para ello, una solucin consiste en utilizar uno de los constructores de la
clase Intent que reciben directamente la accin como parmetro. Otro de los constructores permite
especificar los datos asociados.

Sintaxis

public Intent (String action)


public Intent (String action, Uri uri)

Ejemplo

Intent intent = new Intent(Intent.ACTION_DIAL,


Uri.parse("tel:654321987"));

El sistema buscar a continuacin el mejor componente de entre los que hayan declarado la
capacidad de realizar la accin solicitada y respondan a los criterios exigidos. Utilizar para ello los
valores action, category y data del objeto intent.

a. Filtro de intenciones

Un filtro de intenciones permite a un componente de aplicacin declarar al sistema el tipo de


intencin implcita a la que puede responder. Slo aquellas intenciones implcitas que se tengan en
cuenta en el filtro se procesarn en el componente afectado.

Los filtros de intencin no tienen ninguna incidencia sobre las intenciones explcitas. Estas
ltimas no tienen nada que hacer con estos filtros y los pasan.

La declaracin de las capacidades de un componente de aplicacin se realiza utilizando la


etiqueta intent-filter en el manifiesto. Un componente de aplicacin puede tener
varios intent-filter distintos. Si no tiene ninguno, el componente slo puede ser ejecutado
80
por intenciones explcitas.

Cuando debe procesarse una intencin implcita, el sistema analiza sus datos y los compara a los de
los filtros de los componentes disponibles. El objeto de tipo Intent debe cumplir los criterios de
uno de los filtros para poder ser procesado. Los criterios son la accin, la categora y los datos.

De ah que las etiquetas intent-filter puedan incluir


etiquetas action, category y datapara describir cada uno de estos puntos.

Sintaxis

<intent-filter android:icon="recurso_gr fico"


android:label="recurso_texto"
android:priority="entero" >
...
</intent-filter>

Los atributos android:icon y android:label pueden mostrarse al usuario segn las


necesidades. Si no se especifican, utilizarn por defecto las del componente padre.

Si una intencin se corresponde con varios filtros de actividades o de receptores de eventos


distintos, el atributo android:priority permite escoger aqul que utilizar el sistema. El valor
de este atributo debe ser un nmero entero. Se dar prioridad al de mayor valor.

La etiqueta action de un intent-filter indica el nombre completo de la accin que el


componente puede procesar mediante el atributo android:name. El nombre completo est
formado por el nombre del paquete de la aplicacin seguido del nombre de la accin en maysculas
separada por un punto. Es posible indicar varias acciones en el mismo filtro intent-filter.

Basta con que la accin del objeto intent se corresponda con una sola de las acciones del
filtro para que se cumpla el criterio de la accin.

Sintaxis

<action android:name="cadena!de!caracteres" />

Ejemplo

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="es.midominio.android.miapli.ACCION1" />
</intent-filter>

La etiqueta category de un intent-filter indica el nombre completo de la categora que


caracteriza al componente. El nombre completo est formado por el nombre del paquete de la
aplicacin seguido del nombre de la categora en maysculas separada por un punto. Es posible
indicar varias categoras en el mismo filtro intent-filter.

Es preciso que todas las categoras del objeto intent estn incluidas en el mismo filtro para
que se cumpla el criterio de la categora. Poco importa si el filtro aporta ms categoras que
las solicitadas por el intent.

Sintaxis

<category android:name="cadena!de!caracteres" />

Ejemplo

81
<intent-filter ...>
<category android:name="android.intent.category.DEFAULT" />
<category
android:name="es.midominio.android.miapli.CATEGORIA1"/>
</intent-filter>

La etiqueta data de un intent-filter permite especificar una URI y/o un tipo MIME. Los
atributos de esta etiqueta son numerosos y, para algunos de ellos, dependientes los unos de los
otros. De hecho, descubriremos el uso de esta etiqueta y de algunos de sus atributos conforme
avancemos en este libro.

Los datos, data y tipo MIME, indicados por el intent y aquellos del filtro deben corresponderse
perfectamente para que se cumpla el criterio de los datos.

Sintaxis

<data android:host="cadena de caracteres"


android:mimeType="cadena de caracteres"
android:path="cadena de caracteres"
android:pathPattern="cadena de caracteres"
android:pathPrefix="cadena de caracteres"
android:port="cadena de caracteres"
android:scheme="cadena de caracteres" />

Los valores de los


atributos android:host, android:mimeType y android:schemedeben escribirse en
minsculas.

Android considera que si slo se indica el tipo MIME entonces el filtro, y por tanto el
componente, acepta los datos content: y file: que descubriremos ms adelante.

Ejemplo

<intent-filter>
<data android:mimeType="video/*" />
</intent-filter>

4. Intencin pendiente
Una intencin pendiente indica un objeto de tipo PendingIntent. sta contiene un objeto de
tipo Intent que describe una accin a realizar. Esta accin puede realizarse en una fecha posterior
por otra aplicacin hacindose pasar por la aplicacin que ha creado el objeto de
tipo PendingIntenty recibiendo los permisos para la ocasin.

Los mtodos estticos getActivity, getService y getBroadcast de la


clase PendingIntent crean un objeto de tipo PendingIntent permitiendo respectivamente
ejecutar una actividad, un servicio o difundir un evento. Estos mtodos reciben como parmetro el
contexto de la aplicacin, un cdigo no utilizado, la intencin a realizar as como los flags.

Sintaxis

public static PendingIntent getActivity (Context context, int


requestCode, Intent intent, int flags)
public static PendingIntent getService (Context context, int
requestCode, Intent intent, int flags)
public static PendingIntent getBroadcast (Context context, int
82
requestCode, Intent intent, int flags)

Ejemplo

Intent intent = new Intent(this, MiActividadDestino.class);


intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);

Este ejemplo crea, o actualiza, el flag PendingIntent.FLAG_UPDATE_ CURRENT, un objeto de


tipo PendingIntent encargado de ejecutar la actividad MiActividadDestino en una fecha
posterior.

El hecho de agregar el flag Intent.FLAG_ACTIVITY_NEW_TASK es obligatorio para


arrancar la actividad en una nueva tarea (vase la seccin Actividad).

83
Actividad
Una actividad es un componente independiente que tiene la mayora de veces una interfaz de usuario.
En el caso ms representativo, una actividad presenta una pantalla al usuario para interactuar con l.
Una aplicacin muy simple puede tener una nica actividad mientras que una ms compleja puede
poseer varias. No obstante, solamente una nica actividad de la aplicacin estar activa a la vez. La
pantalla que la gestiona es la que se muestra al usuario.

Para definir una actividad, es preciso crear una clase que herede de la clase Activity e implementar,
como mnimo, los mtodos heredados.

La ejecucin de una actividad se produce en el proceso ligero, o thread, principal del proceso de la
aplicacin. Este thread tambin se denomina thread de la interfaz de usuario puesto que permite
modificar la interfaz de usuario. Cualquier modificacin en la interfaz desde un thread concurrente
genera un error.

Para preservar la experiencia de usuario, una actividad no debera bloquear su thread principal
ms de cinco o diez segundos segn el caso (vase el captulo Concurrencia, seguridad y red -
Programacin concurrente).

1. Declaracin
Para poder utilizarse, una actividad debe declararse en el sistema mediante el manifiesto.

La etiqueta activity contiene informacin propia de una actividad. Como la mayora de las
etiquetas, esta etiqueta contiene muchos atributos. Veremos algunos de ellos conforme descubramos
las funcionalidades asociadas.

Una actividad que acepta recibir intenciones implcitas debe declarar obligatoriamente
lacategora android.intent.category.DEFAULT en su filtro de intenciones. Esta
categora se agrega automticamente al objeto intent cuando se pasa este objeto
al mtodo startActivity o al mtodo startActivityForResult.

He aqu la sintaxis de esta etiqueta y sus tres atributos principales:

Sintaxis

<activity android:icon="recurso grfico"


android:label="recurso texto"
android:name="cadena de caracteres"
... >
...
</activity>

Los atributos icon y label tienen las mismas funciones que para la etiqueta application pero
limitadas a la actividad. Si no se especifican, se utilizarn por defecto las de la aplicacin.

Observe que el atributo android:screenOrientation permite a la actividad indicar la


orientacin que debe adoptar. Por defecto, la orientacin de una actividad depende de cmo el
usuario sostenga el dispositivo. Es posible obviar estos cambios de orientacin y fijar de manera
permanente la orientacin de la actividad utilizando por ejemplo el
valor portrait, landscapeo nosensor correspondiente respectivamente a vertical,
apaisado, y el uno o el otro en funcin de la eleccin del sistema segn el dispositivo. No
obstante, se recomienda que una aplicacin no lo suponga y fije su orientacin. Esto es todava
ms evidente si debe funcionar en dispositivos de distinto tipo tales como smartphones y tabletas
tctiles. Dado que los usuarios tienen tendencia a utilizar los primeros principalmente en modo
84
vertical y los segundos en modo apaisado.

Desde Android 3.0 (API 11), es posible demandar que la visualizacin de las vistas de una
actividad o de una aplicacin completa utilice la aceleracin de hardware si est disponible en
el dispositivo utilizado. Esto permite mejorar el rendimiento de la representacin de las vistas, las
animaciones y, en general, la reactividad del sistema. De este modo, la experiencia del usuario
ser mejor. Para ello, el desarrollador debe utilizar
el atributo android:hardwareAccelerated bien en la etiqueta application o bien en
una o varias etiquetas activity del manifiesto segn el uso deseado.

El atributo android:name permite especificar el nombre de la actividad concreta, es decir su


nombre de clase Java precedido por el nombre completo del paquete.

Ejemplo

android:name="es.midominio.android.miapli.MiActividadPrincipal"

Para acortarlo, dado que el nombre del paquete se conoce, pues viene especificado por
el atributo package de la etiqueta manifest, es posible indicar el nombre de la clase de la
actividad reemplazando el paquete por un punto.

Ejemplo

android:name=".MiActividadPrincipal"

Ejemplo

<activity android:name=".MiActividadPrincipal"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

En este ejemplo, y a diferencia de lo que se indica en la observacin situada ms arriba, el filtro de la


actividad no declara la categora android.intent. category.DEFAULT. Es el nico caso en el
que no es obligatorio declarar de forma combinada de la accin android.intent.action.MAIN y
de la categora android.intent.category.LAUNCHER.

Recuerde, la accin android.intent.action.MAIN indica que el componente es el punto de


entrada de la aplicacin. La categora android.intent.category.LAUNCHER indica adems
que el compo-nente forma parte de los componentes que puede ejecutar el usuario. La combinacin
de ambas etiquetas permite que este componente, en este caso una actividad, se agregue a la
aplicacin Lanzador de aplicaciones del dispositivo Android.

La aplicacin Lanzador de aplicaciones es la aplicacin que muestra, en forma de parrilla de


iconos con su nombre, la lista de las aplicaciones que puede ejecutar el usuario.

2. Ciclo de vida
El ciclo de vida de una actividad describe los estados en los que la actividad puede encontrarse entre
su creacin, la instanciacin, y su muerte, la destruccin de esta instanciacin.

85
Tras cada cambio de estado se invoca un mtodo que puede derivarse en la clase de la actividad.

Cada uno de estos mtodos debe invocar a su mtodo padre, en caso contrario se generar
una excepcin.

El sistema no puede destruir una actividad mientras se encuentre en un estado anterior al estado de
pausa. En pausa y ms all, el sistema puede decidir destruir la actividad en cualquier momento.

a. onCreate

El mtodo onCreate es el primer mtodo del ciclo de vida que se invoca durante la creacin de
una actividad. Slo se invoca una nica vez durante todo el ciclo de vida de la actividad. La funcin
de este mtodo es permitir inicializar la actividad, crear las vistas que deben mostrarse tras la
creacin de la actividad, recuperar las instancias de estas vistas

Si se produce una llamada al mtodo finish dentro de este mtodo para poner fin
directamente a la actividad sin que haya podido mostrarse en ningn momento, entonces
elmtodo onDestroy se invocar inmediatamente despus, cortocircuitando la secuencia de
llamadas normal: onStart, onResume...

Recibe como parmetro un objeto de tipo Bundle. ste permite recuperar informacin, datos
salvaguardados anteriormente tras la ltima ejecucin de esta actividad. Se describe con ms
detalle ms adelante.

Cabe observar que este parmetro es nulo durante la creacin de esta actividad.

Sintaxis

protected void onCreate (Bundle savedInstanceState)

Ejemplo

public class MiActividad extends Activity {


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.principal);

Intent intent = getIntent();


traitement(intent);
}
}

En este ejemplo, el mtodo invoca a su mtodo padre pasndole el objeto de tipo Bundle e invoca
al mtodo setContentView para crear la vista inicial de la actividad que se mostrar al usuario.
El mtodo getIntent permite recuperar el intent que ha solicitado la ejecucin de esta actividad.

b. onStart

El mtodo onStart es el simtrico del mtodo onStop. Se invoca tras el mtodo onCreate o
tras el mtodo onRestart si la actividad se encontraba en el estado detenido y ha vuelto a primer
plano.

Precede a la visualizacin de la actividad, en concreto de su vista.

Sintaxis

86
protected void onStart ()

Ejemplo

public class MiActividad extends Activity {


@Override
public void onStart() {
super.onStart();
}
}

c. onResume

El mtodo onResume es el simtrico del mtodo onPause. Se invoca tras el mtodo onStart o
tras el mtodo onPause si la actividad estaba en pausa y ha vuelto a primer plano.

En este estado, la actividad se muestra al usuario. Una vez que se sale de este mtodo, la actividad
va a funcionar con normalidad en primer plano y podr interactuar con el usuario.

Sintaxis

protected void onResume ()

Ejemplo

public class MiActividad extends Activity {


@Override
public void onResume() {
super.onResume();
}
}

d. onPause

El mtodo onPause es el simtrico del mtodo onResume. Se invoca cuando otra actividad va a
tomar el control en primer plano de modo que nuestra actividad pasar a un segundo plano desde
este momento. Es preciso que sea a la vez un mtodo rpido y eficaz de cara a no bloquear a la
actividad siguiente, aunque tiene la funcin de salvaguardar los datos persistentes de la actividad y
parar las tareas que consuman CPU, memoria...

Hasta Android 3.0 (API 11), el sistema Android puede decidir matar la aplicacin, en concreto
su proceso, a partir de cualquier momento desde la salida de este mtodo. Es el nico
mtodo que podemos estar seguros de que se invoca antes de suprimir el proceso. Por tanto, es
la ltima ocasin que tenemos de realizar las copias de seguridad y dems acciones importantes
que deben realizarse obligatoriamente. Desde Android 3.0 (API 11), esta observacin ya no es
vlida para el mtodo onPause ya que en lo sucesivo lo es para el mtodo onStop.

Puede ser til utilizar el mtodo isFinishing para determinar si la actividad est tratando de
terminar o si simplemente se est poniendo en pausa. En el primer caso, devolver true, en caso
contrario devolver false.

Sintaxis

public boolean isFinishing ()

Sintaxis del mtodo onPause

protected void onPause ()

87
Ejemplo

public class MiActividad extends Activity {


@Override
public void onPause() {
super.onPause();
if (isFinishing()) {
procesamiento1();
} else {
procesamiento2();
}
}
}

e. onStop

El mtodo onStop es el simtrico del mtodo onStart.


Este mtodo permite liberar ciertos recursos, en particular los objetos de tipo Cursor queveremos
ms adelante (vase el captulo La persistencia de los datos - Bases de Datos SQLite).

Hasta Android 3.0 (API 11), este mtodo puede que jams se invoque si el sistema decide
antes terminar con el proceso de la aplicacin. Es preciso utilizar en su lugar el
mtodo onPause para salvaguardar los datos persistentes.

Desde Android 3.0 (API 11), el sistema Android no puede matar el proceso de la aplicacin
antes de invocar a este mtodo. Por el contrario, puede decidir terminar con la aplicacin a
partir de cualquier momento desde la salida de este mtodo. Por tanto, es la ltima ocasin que
tenemos de realizar las copias de seguridad y dems acciones importantes que deban realizarse
obligatoriamente.

Sintaxis

protected void onStop ()

Ejemplo

public class MiActividad extends Activity {


@Override
public void onStop() {
super.onStop();
}
}

f. onRestart

El mtodo onRestart puede invocarse desde el mtodo onStop si la actividad vuelve a primer
plano. A continuacin contina con una llamada al mtodo onStart.

Este mtodo permite solicitar de nuevo ciertos recursos liberados en el mtodo onStop.
Sintaxis

protected void onRestart ()

Ejemplo

public class MiActividad extends Activity {


88
@Override
public void onRestart() {
super.onRestart();
}
}

g. onDestroy

El mtodo onDestroy es el simtrico del mtodo onCreate. Se invoca despus de invocar


almtodo finish o directamente por el sistema si necesita liberar recursos. Es el ltimo mtodo
invocado que se pone a disposicin del desarrollador antes de destruir efectiva e irreversiblemente
la actividad.

Este mtodo permite liberar recursos ligados a la actividad, por ejemplo un thread que no tiene
sentido sin esta actividad.

Este mtodo puede que jams se invoque si el sistema ha decidido matar antes el proceso
de la aplicacin. Es preciso utilizar en su lugar el mtodo onPause para salvaguardar los
datos persistentes.

Sintaxis

protected void onDestroy ()

Ejemplo

public class MiActividad extends Activity {


@Override
public void onDestroy() {
supprimeThread();
super.onDestroy();
}
}

3. Ejecucin
El mtodo startActivity permite ejecutar una actividad pasndole como parmetro un objeto de
tipo Intent (intencin), implcita o explcita.

Sintaxis

public abstract void startActivity (Intent intent)

Ejemplo

Intent intent = new Intent(this, MiActividadDestino.class);


startActivity(intent);

Si la actividad ejecutada debe devolver un resultado una vez haya finalizado, es preciso utilizar
losmtodos startActivityForResult y onActivityResult que funcionan de forma
conjunta. Una vez que la actividad de destino termina, se invoca el mtodo onActivityResult del
componente origen. Se le pasan los siguientes parmetros: el cdigo informado en la
llamada startActivityForResult que permite identificar el origen del resultado, el resultado de
la actividad que acaba de terminar y los datos suplementarios que proporciona la actividad que acaba
de terminar en los campos extra de un intent.

La ejecucin del mtodo onActivityResult tiene lugar justo antes del mtodo onResume de
la actividad origen.

89
Sintaxis

public void startActivityForResult (Intent intent, int requestCode)


protected void onActivityResult (int requestCode, int resultCode,
Intent data)

Ejemplo

public class MiActividadPrincipal extends Activity {


private static final int REQ_MSG_ACTIVIDADDEST = 1;

private void ejecutaActividadDestino() {


Intent intent =
new Intent(this, MiActividadDestino.class);
startActivityForResult(intent, REQ_MSG_ACTIVIDADDEST);
}

@Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
if (requestCode == REQ_MSG_ACTIVIDADDEST) {
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
procesamiento(bundle);
}
} else
super.onActivityResult(requestCode, resultCode, data);
}
}

La actividad de destino indica el resultado devuelto y si es preciso lo complementa utilizando el


mtodo setResult. Este mtodo modifica precisamente el valor del retorno, borrando el valor
anterior llegado el caso. No termina la actividad en curso. Se utilizar por ejemplo el
mtodo finish para ello.

Sintaxis

public final void setResult (int resultCode)


public final void setResult (int resultCode, Intent data)

Ejemplo

public class MiActividadSecundaria extends Activity {

private void devuelveCancel() {


setResult(RESULT_CANCELED);
finish();
}

private void devuelveOK() {


Intent intent = new Intent();
intent.putExtra("clave", "valor");
setResult(RESULT_OK, intent);
finish();
}
}

4. Salvaguarda y restauracin del estado


Como vimos en la descripcin del mtodo onCreate, un objeto de tipo Bundle permite
salvaguardar el estado de la actividad cuando sta es destruida por el sistema (y nicamente por
ste) para poder recrearla a continuacin con idntico estado. El usuario que cierra voluntariamente
90
una actividad, por ejemplo presionando la tecla Volver del dispositivo, no provocar la copia de
seguridad de este objeto de tipo Bundle.

Este es el caso cuando el sistema necesita recursos o ms habitualmente cuando el usuario cambia la
orientacin del dispositivo. El sistema destruye entonces la actividad y sus vistas en curso para ser
recreadas en un formato compatible con la nueva orientacin. Para ello, el SDK proporciona dos
mtodos complementarios: onSaveInstanceState y onRestore- InstanceState.

El mtodo onSaveInstanceState permite salvaguardar los datos en el objeto de


tipo Bundleque se pasa como parmetro. Este ser el objeto pasado, llegado el momento, al
mtodo onCreate y al mtodo onRestoreInstanceState. Este mtodo se invoca antes del
mtodo onStop. Esto puede ser antes o despus del mtodo onPause pero, en cualquier caso, la
actividad no es destruida por el sistema mientras no se haya invocado a este mtodo.

Existen casos en los que se invoca el mtodo onPause mientras que el


mtodo onSaveInstanceState no. Es el caso descrito anteriormente en el que el usuario
cierra la actividad en curso. Hay que prestar atencin y utilizar el
mtodo onSaveInstanceState en lugar del mtodo onPause, en particular para
salvaguardar los datos persistentes.

El mtodo onRestoreInstanceState recibe como parmetro el objeto de


tipo Bundlesalvaguardado anteriormente. Gracias a esta informacin, la actividad puede restaurar
sus datos y sus vistas en el estado en que estuvieran anteriormente. Tambin es posible hacerlo en
el mtodo onCreate. El mtodo onRestoreInstanceState se invoca despus del
mtodo onStart y antes que el mtodo onResume.

Sintaxis

protected void onSaveInstanceState (Bundle outState)


protected void onRestoreInstanceState (Bundle savedInstanceState)

Ejemplo

public class MiActividad extends Activity {


private static final String CLAVE_1 =
"es.midominio.android.miapli.clave1";
private static final String CLAVE_2 =
"es.midominio.android.miapli.clave2";

private String mValor1;


private int mValor2;

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(CLAVE_1, mValor1);
outState.putInt(CLAVE_2, mValor2);
};

@Override
protected void onRestoreInstanceState(Bundle savedState) {
mValor1 = savedState.getString(CLAVE_1);
mValor2 = savedState.getInt(CLAVE_2);
super.onRestoreInstanceState(savedState);
};
}

5. Pila de actividades
A cada aplicacin el sistema le asocia una pila de actividades de tipo FIFO (First In, First Out) o
Primero en Entrar, Primero en Salir. sta apila 91
las actividades de la aplicacin que se ejecutan las
unas a continuacin de las otras. Esto aplica tambin a las actividades ejecutadas desde la aplicacin
pero proporcionadas por otras aplicaciones como veremos en los prximos captulos.

Esta secuencia de actividades almacenadas en la pila representa una tarea, en el sentido funcional.

Cuando el usuario desea volver a la actividad anterior a la actividad en curso apretando por ejemplo
el botn Volver, el sistema desapila la actividad en curso, la destruye y retoma la ejecucin de la
actividad anterior. La operacin puede repetirse hasta vaciar por completo la pila, que se destruye a
continuacin.

Cuando el usuario vuelve a la pantalla de bienvenida de Android, el escritorio, presionando la


teclaInicio, el sistema salvaguarda en memoria la pila de la aplicacin en curso. Si el usuario vuelve a
ejecutar la aplicacin, por defecto, se restaurar su pila y la actividad en curso estar situada en la
parte superior de la pila.

Si se estima la necesidad, el sistema Android puede destruir en cualquier momento las


actividades que no estn en curso para liberar recursos del sistema. Por ello se aconseja
encarecidamente salvaguardar el estado de las aplicaciones antes de su destruccin de modo que
el sistema pueda restaurarlas en el estado en el que las hubiera dejado el usuario.

Por defecto, el sistema puede vaciar una pila que no se est usando tras cierto lapso de
tiempo y as guardar solamente la primera actividad. El sistema considera en efecto que el
usuario no quiere retomar una accin anterior sino comenzar una nueva. Es posible modificar este
comportamiento haciendo uso de
los atributos android:alwaysRetainTaskState,android:
clearTaskOnLaunch y android:finishOnTaskLaunch de la etiqueta activity de la
actividad de entrada en el manifiesto.

Como veremos ms adelante con la barra de accin (vase el captulo Completar la interfaz de
usuario - Barra de accin), el usuario puede presionar el icono de la aplicacin de esta barra para
volver justo a la actividad anterior. Esto se realiza fcilmente utilizando el mtodo finish que
hemos visto.

No obstante el hecho de presionar el icono de la aplicacin en esta barra de accin tambin puede
indicar que el usuario quiere volver a la actividad de entrada. En el estado actual, si la actividad de
entrada se ejecuta de nuevo usando un intent, se situar en la parte superior de la pila de
actividades. El usuario no comprender que si vuelve atrs para salir de la aplicacin, se encuentre
con una actividad antigua en su lugar... La accin correcta consiste en hacer que todas las
actividades salvo la primera se desapilen de la pila. La nica actividad que queda, la primera, que se
corresponde por lo general con la actividad de entrada, ser la actividad en curso.

Para hacer esto posible de manera sencilla, Android permite modificar el funcionamiento por defecto
de la pila.

Por ejemplo, basta con agregar el flag Intent.FLAG_ACTIVITY_CLEAR_TOP al intent utilizado


para ejecutar la actividad para desapilar las actividades de la pila hasta aquella afectada por el
intent. En nuestro caso, se trata de la actividad de entrada. Esto provoca que todas las actividades
desde la parte superior de la pila hasta la actividad de entrada se desapilen.

Ejemplo

Intent intent = new Intent(this, MiActividadPrincipal.class);


intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

Existen muchos otros flags de tipo Intent.FLAG_ACTIVITY_* que permiten modificar el


comportamiento por defecto.

92
Android permite a su vez a las actividades especificar su modo de agregacin a la pila
directamente en el manifiesto. Para ello, se puede utilizar el
atributo android:launchModede la etiqueta activity. Llegado el momento, los flags
especificados en los intents sern prioritarios a los definidos en el manifiesto.

93
7. Completar la
interfaz de usuario

94
Introduccin
La presentacin de la interfaz de usuario realizada en captulos anteriores nos ha permitido abordar
los temas generales y descubrir los widgets. No obstante, la interfaz de usuario de una aplicacin no
se limita a esto. Existen otros elementos que complementan a los ya expuestos anteriormente y que
aportan nuevas funcionalidades a las aplicaciones.

En este captulo, descubriremos cmo utilizar los nuevos estilos y temas incluidos en Android 3.0,
cmo crear un men o una barra de accin segn el sistema utilizado y veremos los distintos mtodos
para notificar al usuario. Por ltimo, terminaremos describiendo cmo programar una aplicacin
multiidioma.

95
Estilos y temas
De forma similar a las hojas de estilo CSS usadas en las pginas Web, los estilos en Android permite
separar las propiedades de diseo de una vista de su contenido. Esta separacin permite tener un
cdigo ms claro para las vistas y la reutilizacin de estilos.

Un estilo es un recurso definido en un archivo XML de la carpeta res/values. Es habitual reagrupar


todos los estilos en un nico archivo llamado styles.xml. Los estilos se definen utilizando
laetiqueta style. sta permite darle nombre al estilo y, eventualmente, especificar el estilo padre del
que debe heredar sus propiedades. A continuacin se definen los distintos elementos que componen
el estilo utilizando etiquetas item.

Los estilos se aplican nicamente sobre una vista individual utilizando el atributo style de la
etiqueta vista. El valor de este atributo designa el estilo deseado.

Por ello si queremos aplicar un estilo a toda la aplicacin, resulta algo molesto asignar el estilo a
todas las vistas de la aplicacin. Para evitar tener que hacer esta manipulacin, Android permite usar
temas.

Los temas no son ms que estilos aplicados a actividades o a la aplicacin entera.

Si una aplicacin no define su propio tema utilizando el atributo android:theme en su


etiqueta application del manifiesto, utiliza en ese caso el tema del sistema Android sobre el que
se ejecute.

Un nuevo tema grfico, llamado hologrfico, ha hecho aparicin con Android 3.0 (API 11). ste
introduce en concreto un nuevo elemento de la interfaz: una barra de accin (vase la seccin Barra
de accin).

Cualquier aplicacin que quiera utilizar el nuevo tema hologrfico cuando se ejecute sobre un sistema
con versin 3.0 o superior debe especificar un nivel de API igual o superior a 11 en el
atributo android:targetSdkVersion de la etiqueta uses-sdk del manifiesto.

Esto slo es necesario en el caso de una aplicacin hecha para sistemas Android 3.0 o
superiores, es decir cuando el valor de android:minSdkVersion es igual o superior a 11.

De este modo, si la aplicacin se ejecuta sobre un sistema Android de versin inferior a 3.0 (API 11),
utilizar el tema del sistema de esta versin. Y si la aplicacin se ejecuta sobre un sistema 3.0 (API
11) o superior, utilizar el nuevo tema hologrfico.

Recuerde, las API que puede utilizar una aplicacin son aquellas que existen en la versin
especificada por el atributo android:minSdkVersion. De ello se desprende que si el valor
del atributo android:minSdkVersion es inferior a 11, entonces la aplicacin no podr utilizar
los nuevos elementos tales como la barra de accin dado que en estas versiones no existen las
clases correspondientes a estos elementos.

96
Mens
Elementos importantes de la interfaz de usuario, en Android hay disponibles dos tipos de mens: los
mens de actividad y los mens contextuales. Su declaracin se realiza de forma idntica.

1. Declaracin
Recuerde, daremos prioridad aqu al mtodo declarativo si bien es posible crear o modificar los mens
directamente desde el cdigo Java.

La primera etapa consiste en crear un archivo de formato XML en la carpeta res/menu del proyecto
e incluir en l la etiqueta menu.

Sintaxis

<menu xmlns:android="http://schemas.android.com/apk/res/android">
...
</menu>

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<menu xmlns:android="http://schemas.android.com/apk/res/android">
</menu>

Las opciones del men se agregan, a continuacin, una a una utilizando la etiqueta item. Sus
atributos permiten parametrizar la opcin. He aqu las principales:

Propiedad Descripcin

android:title Ttulo de la opcin a mostrar.

android:icon Imagen con el icono asociado a la opcin.

android:onClick Nombre del mtodo de la actividad a ejecutar


cuando el usuario hace clic en la vista. Existe desde
Android 3.0 (API 11).

android:showAsAction Permite especificar si esta opcin debe figurar en la


barra de accin y de qu forma. Existe desde
Android 3.0 (API 11).

android:checked Permite preseleccionar la opcin cuando forma


parte de un grupo de opciones a marcar o de
botones radio.

Sintaxis

<item android:id="@[+][paquete:]id/nombre_recurso"
android:icon="recurso_gr fico"
android:title="recurso_texto"
android:onClick="nombre_mtodo"
android:showAsAction="[always|ifRoom|never][|][withText]"
android:checked="booleano"
...
/>

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


97
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/men_principal_opcin1"
android:icon="@drawable/men_principal_opcin1"
android:title="@string/men_principal_opcin1"
android:onClick="procesamientoOpcin1" />
</menu>

Es posible crear un nivel suplementario de submens. Se trata de mens que se muestran cuando el
usuario ha seleccionado una opcin en el primer men.

Esto permite crear una arborescencia de mens con dos niveles como mximo. No es posible tener
submens de submens.

Para crear un submen, basta con insertar un nuevo men en un tem del primer men utilizando de
nuevo la etiqueta menu. Los tems del submen deben informarse dentro de esta nueva etiqueta
menu.

Sintaxis

<item ...>
<menu>
<item ...>
...
</menu>
</item>

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/men_principal_opcin1"
android:icon="@drawable/men_principal_opcin1"
android:title="@string/men_principal_opcin1">
<menu>
<item android:id="@+id/men_secundario_opcin1"
android:icon="@drawable/men_secundario_opcin1"
android:title="@string/men_secundario_opcin1" />
</menu>
</item>
</menu>

Es posible agrupar parte de las opciones de un men para aplicarles las mismas propiedades.
Tambin es posible agregar casillas para marcar o botones de radio a todos los elementos de un
men. Para estos dos casos, las opciones deben estar agrupadas en la misma etiqueta group. Si
fuera necesario, el atributo android:checkableBehavior permite especificar el tipo de
agrupacin.

Sintaxis

<group android:id="@[+][paquete:]id/nombre_recurso"
android:checkableBehavior="all|none|single" >
...
</group>

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/group"
android:checkableBehavior="single">
<item android:id="@+id/men_contextual_opcin1"
android:icon="@drawable/icon"
android:title="@string/men_config"
98
android:checked="true" />
<item android:id="@+id/men_contextual_opcin2"
android:icon="@drawable/icon"
android:title="@string/men_config" />
</group>
</menu>

2. Uso
La transformacin de la descripcin del men desde el formato XML en una instancia del objeto de
tipo Menu se realiza desde la actividad asociada utilizando un objeto de tipo MenuInflater.

ste es devuelto por el mtodo getMenuInflater de la actividad.

Sintaxis

public MenuInflater getMenuInflater ()

Ejemplo

MenuInflater conversorMenu = getMenuInflater();

El mtodo inflate de este objeto permite leer el archivo de men XML pasado como parmetro
mediante su identificador y agregar los elementos y submens al objeto de tipo Menu pasado como
parmetro.

Sintaxis

public void inflate (int menuRes, Menu menu)

Ejemplo

Menu menu = new Menu();


conversorMenu.inflate(R.menu.principal, menu);

3. Men de actividad
El men de actividad es un men que permite escoger en funcin de la pantalla mostrada
actualmente. Este men puede contener iconos, pero no puede contener casillas de opcin a marcar
ni botones de radio.

Para las aplicaciones que corran sobre una versin inferior a Android 3.0 (API 11), cuando el usuario
presione la tecla Men de su dispositivo, ste aparecer. O, ms bien, aparecern los seis primeros
elementos del men. Si existen ms de seis, el sexto elemento se reemplaza por la opcin Ms. Si el
usuario la selecciona, aparece un nuevo men con forma de lista y muestra el resto de elementos del
men, del 6 hasta el ltimo.

Este men de actividad desaparece cuando el usuario selecciona una opcin o cuando presiona la
tecla Volver.

Para las aplicaciones que corran sobre una versin de Android 3.0 (API 11) o superior, las opciones
del men se reagrupan por defecto en el submen de la barra de accin (vase la seccin Barra de
accin) representadas por un icono de men situado en la parte derecha de la barra de accin. Su
presencia y su apariencia pueden modificarse mediante su atributo android: showAsAction.

a. Creacin

Dado que este tipo de men est asociado a una actividad, debe estar definido por la actividad en
su mtodo onCreateOptionsMenu. Este mtodo recibe como parmetro el objeto de
tipo Menuque debe construir. Devuelve el valor true para permitir la visualizacin de este men.

99
Sintaxis

public boolean onCreateOptionsMenu (Menu menu)

Ejemplo

@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater conversorMenu = getMenuInflater();
conversorMenu.inflate(R.menu.principal, menu);
return true;
}

b. Uso

Desde Android 3.0 (API 11), el atributo android:onClick de la etiqueta item permiteespecificar
directamente el nombre de la actividad que se quiere ejecutar cuando el usuario selecciona la
opcin correspondiente. Este mtodo debe estar definido en la actividad afectada, estar declarado
como pblico y recibir como parmetro el objeto de tipo MenuItem seleccionado.

Sintaxis

public void nombreMtodo(MenuItem item)

Ejemplo

public void onMenuOption1(MenuItem item) {


procesamiento1();
}

El objeto de tipo MenuItem contiene informacin del elemento seleccionado, recuperable mediante
sus distintos accesores. Uno de ellos, el mtodo get-ItemId, permite recuperar el identificador de
la opcin seleccionada por el usuario.

Sintaxis

public abstract int getItemId ()

Ejemplo

int id = item.getItemId();

Existe otra forma de responder a la seleccin del usuario de una opcin de men y que es la nica
disponible en las versiones inferiores a Android 3.0 (API 11). Consiste en implementar
el mtodo onOptionsItemSelected en la actividad o el fragmento asociado. Recibe como
parmetro el objeto de tipo MenuItem seleccionado. Debe devolver true si procesa la opcin
seleccionada, o false en caso contrario.

Sintaxis

public boolean onOptionsItemSelected (MenuItem item)

Ejemplo

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_option1 :
procesamiento1();
return true; 100
}
return super.onOptionsItemSelected(item);
}

En este ejemplo, al finalizar el mtodo onOptionsItemSelected, ste invoca a su


mtodo padre en el caso en el que este ltimo haya definido opciones de men
suplementarias. Es el caso, por ejemplo, de actividades que deseen compartir mens comunes.
Heredan de una misma clase madre que especifica las opciones de men comunes y las acciones
correspondientes.

Para modificar dinmicamente el men, una vez creado, hay que sobrecargar
el mtodo onPrepareOptionsMenu. Desde Android 3.0 (API 11), es preciso tambin
invocar de forma explcita al mtodo invalidateOptionsMenu para forzar la reconstruccin
del men.

4. Men contextual
Un men contextual es un men que depende del contexto en el que se activa. El usuario activa este
men presionando durante cierto tiempo sobre una vista. Si la vista ha declarado tal men, ste
aparecer bajo la forma de una ventana en primer plano. Un men as no puede contener iconos.

Las opciones de men se muestran en forma de lista en un pop-up. Este men contextual
desaparece cuando el usuario selecciona una opcin o presiona sobre la tecla Volver.

a. Creacin

En primer lugar, hay que permitir a la vista gestionar cuando el usuario presiona durante un tiempo
sobre la pantalla. Para ello es preciso utilizar el
mtodo registerForContextMenupasndole como parmetro la vista.

Sintaxis

public void registerForContextMenu (View view)

Ejemplo

View vue = findViewById(R.id.layout_principal);


registerForContextMenu(vista);

Un men contextual debe definirlo la actividad de la vista afectada en


el mtodo onCreateContextMenu. sta recibe como parmetro el objeto men de
tipo ContextMenuque debe construir, la vista sobre la que el usuario tendr que presionar
durante un tiempo y un objeto de tipo ContextMenuInfo que incluya los datos suplementarios
segn el tipo de vista utilizada.

Sintaxis

public void onCreateContextMenu (ContextMenu menu, View v,


ContextMenu.ContextMenuInfo menuInfo)

Ejemplo

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
101
switch (v.getId()) {
case R.id.layout_principal:
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.contextuel, menu);
break;
}
}

b. Uso

El mtodo onContextItemSelected debe sobrecargarse para procesar la eleccin del usuario


entre las opciones del men contextual. Este mtodo recibe como parmetro el objeto de
tipo MenuItem seleccionado. Devuelve true si procesa la opcin seleccionada, o false en caso
contrario.

Sintaxis

public boolean onContextItemSelected (MenuItem item)

Ejemplo

@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_contextual_opcion1 :
procesamientoContextual1();
return true;
}
return super.onContextItemSelected(item);
}

102
Barra de accin
Nuevo elemento aparecido con Android 3.0 (API 11) a travs del tema hologrfico, la barra de accin
reemplaza a la barra de ttulo as como al men de actividad tal y como aparecen en las versiones
anteriores.

Por defecto, de izquierda a derecha, la barra incluye el icono de la actividad o por defecto de la
aplicacin, su ttulo as como las opciones del men de actividad que se muestran directamente en la
barra, mediante un submen representado por un icono situado a la derecha del todo.

Tambin es posible insertar directamente widgets en la barra de accin como, por ejemplo, una barra
de bsqueda, pestaas con fragmentos o una lista de navegacin. Tambin es posible modificar la
apariencia de la barra de accin y reemplazar el icono por una imagen.

1. Opciones de men
Visibles directamente o accesibles mediante el submen, las opciones de men se gestionan tal y
como se definen en este captulo (vase seccin Mens).

Por defecto, las opciones de men aparecen en el submen de la barra de accin accesible mediante
el icono situado a la derecha del todo. Para situar directamente una de estas opciones de men
sobre la barra de accin, hay que utilizar el atributo android:showAsAction de la
etiqueta item correspondiente en la descripcin XML del men.

Especificar el valor ifRoom en este atributo permite situar la opcin de men correspondiente
directamente en la barra de accin si hay sitio suficiente. Es posible agregar el valor withTextpara
indicar que tambin debe mostrarse el ttulo de la opcin.

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_principal_opcion1"
android:icon="@drawable/menu_principal_opcion1"
android:title="@string/menu_principal_opcion1"
android:onClick="traitementOption1"
android:showAsAction="ifRoom|withText" />
</menu>

El mtodo getActionBar de una actividad permite recuperar la instancia de su barra de accin de


tipo ActionBar.

Sintaxis

public ActionBar getActionBar ()

Ejemplo

ActionBar actionBar = getActionBar();

2. Icono de la aplicacin
En una barra de accin, el icono de la actividad o por defecto de la aplicacin forma tambin parte del
botn de accin. Cuando el usuario hace clic sobre l, se recomienda que la actividad en curso vuelva
a su estado inicial o que la aplicacin vuelva a la pantalla de bienvenida (vase el captulo Los
fundamentos - Actividad).

Para detectar el clic sobre el botn, hay que implementar el


mtodo onOptionsItemSelectedvisto anteriormente (vase la seccin Mens). ste recibe un
objeto de tipo Item cuyo identificador nico es, en
103
este caso, android.R.id.home. A continuacin
es preciso implementarlo e iniciar la accin correspondiente.

El mtodo setDisplayHomeAsUpEnabled permite agregar una marca al icono para indicar al


usuario que al hacer clic sobre l es posible volver, no al inicio, sino a la actividad anterior. Hay que
pasarle como parmetro un valor booleano que active o no esta posibilidad.

Este mtodo slo permite modificar la visualizacin del icono, es tarea del desarrollador
procesar el clic del botn como se ha descrito anteriormente.

Sintaxis

public abstract void setDisplayHomeAsUpEnabled(boolean showHomeAsUp)

Ejemplo

actionBar.setDisplayHomeAsUpEnabled(true);

104
Notificaciones
Una aplicacin puede necesitar advertir y notificar al usuario. Para ello, Android proporciona varias
soluciones dependiendo de si la aplicacin se ejecuta en primer plano o como tarea de fondo. Estas
tres soluciones son: toast (mensaje temporal), la caja de dilogo y la barra de estado.

1. Toast
En Android, un toast es un mensaje que se muestra durante varios segundos en primer plano en una
ventana independiente hecha a medida del mensaje.

Esta ventana no acepta la interaccin del usuario. Android se encarga de hacerla aparecer y
desaparecer a continuacin.

Es el sistema de notificacin perfecto para mensajes de carcter puramente informativo.

Es posible que el usuario no vea los mensajes toast si desva su vista durante algunos
segundos de la pantalla. La importancia de estos mensajes es muy baja y no deben suponer
ninguna incidencia.

Para crear un objeto de tipo Toast muy sencillo, basta con utilizar uno de los mtodos
estticos makeText de la clase Toast. Este mtodo recibe como parmetro el contexto de la
aplicacin, el identificador nico del mensaje que se quiere visualizar o directamente el mensaje en
forma de cadena de caracteres y, por ltimo, la duracin de la visualizacin del mensaje en pantalla.
Esta duracin puede ser la constante Toast.LENGTH_SHORT para indicar una duracin muy corta,
del orden de algunos segundos, o la constante Toast.LENGTH_LONG para una duracin algo ms
prolongada. El mtodo makeText devuelve el objeto Toast creado.

Sintaxis

public static Toast makeText (Context context, int resId,


int duration)
public static Toast makeText (Context context, CharSequence text,
int duration)

Ejemplo

Toast toast = Toast.makeText(this, "Mensaje",


Toast.LENGTH_SHORT);
Toast toast = Toast.makeText(this, R.string.message,
Toast.LENGTH_LONG);

Para mostrar el mensaje, basta con invocar a continuacin al mtodo show.


Sintaxis

public void show ()

Ejemplo

toast.show();

Un pequeo truco, para evitar tener que declarar el objeto toast, consiste en encadenar
directamente la llamada al mtodo show tras la llamada al mtodo makeText.

Ejemplo

105
Toast.makeText(this, "Mensaje", Toast.LENGTH_SHORT).show();

La clase Toast proporciona otros mtodos que permiten posicionar el mensaje en cualquier
lugar de la pantalla o incluso personalizar la vista del mensaje proporcionando su propio
layout.

2. Caja de dilogo
Una caja de dilogo es una ventana flotante modal, es decir, que aparece en primer plano e impide
realizar cualquier otra interaccin con las ventanas de fondo. El usuario slo puede interactuar con la
caja de dilogo mediante, por ejemplo, el uso de botones Aceptar y Cancelar.

En trminos de notificacin, una caja de dilogo as puede utilizarse, por ejemplo, para hacer esperar
al usuario mostrando una barra de progreso. Tambin puede utilizarse para realizar una pregunta al
usuario y solicitarle su aprobacin (Aceptar) o no (Cancelar).

a. Generalidades

Es posible crear todo tipo de cajas de dilogo pasando un layout personalizado a la clase Dialog.
No obstante, la mayor parte de las aplicaciones tienen prcticamente las mismas necesidades en
cuanto a cajas de dilogo. Por ello, Android proporciona cajas de dilogo preformateadas,
simplificando el trabajo al desarrollador. stas heredan de la clase Dialog.

La caja de dilogo ms extendida es la caja de dilogo de alerta, que estudiaremos aqu. Otra es la
caja de dilogo de progreso, representada por la clase ProgressDialog, que permite informar al
usuario que un procesamiento est en curso y le permite adems seguir el nivel de progreso.

Otras cajas de dilogo permiten al usuario introducir una fecha o una hora. Se representan
respectivamente por las clases DatePickerDialog y TimePickerDialog.

Observe que sobre ciertos dispositivos y sobre ciertas versiones de Android, la fecha inicial de
una caja de dilogo de tipo DatePickerDialog que se muestra al usuario no puede ser
inferior al ao 2000 aunque el desarrollador haya informado una fecha anterior en
el atributo android:startYear y la compilacin de la aplicacin se haya realizado sin
problemas.

b. Caja de dilogo de alerta

Como su propio nombre indica, la caja de dilogo de alerta permite alertar al usuario. Para ello,
permite mostrar un ttulo, un icono, entre cero y tres botones as como un mensaje o una lista de
elementos que incluyen por lo general casillas de opcin o botones de radio.

Una caja de dilogo de alerta es una instancia de tipo AlertDialog. Para ayudar a su
construccin, Android proporciona la clase AlertDialog.Builder. El uso de una instancia de
este tipo permite generar este tipo de caja de dilogo.

La creacin de una instancia de tipo AlertDialog.Builder se realiza mediante uno de sus


constructores. stos reciben como parmetro el contexto de la aplicacin y para uno de ellos el
tema grfico.

Sintaxis

public AlertDialog.Builder (Context context)


public AlertDialog.Builder (Context context, int theme)

Ejemplo
106
AlertDialog.Builder builder = new AlertDialog.Builder(this);

Los distintos mtodos de la clase AlertDialog.Builder permiten componer a continuacin la


caja de dilogo. Por ejemplo, los mtodo setTitle y setMessage permiten especificar
respectivamente el ttulo y el mensaje bien pasando como parmetro una secuencia de caracteres,
o bien indicando el identificador del recurso que se quiere mostrar. Estos mtodos devuelven la
misma instancia de tipo AlertDialog.Builder de modo que sea posible encadenar las
llamadas a los mtodos.

Sintaxis

public AlertDialog.Builder setTitle (CharSequence title)


public AlertDialog.Builder setTitle (int titleId)
public AlertDialog.Builder setMessage (CharSequence message)
public AlertDialog.Builder setMessage (int messageId)

Ejemplo

builder.setTitle(R.string.title).setMessage(R.string.message);

Los mtodos setIcon permiten especificar el icono que se quiere mostrar. Reciben como
parmetro un objeto de tipo Drawable, o bien el identificador del recurso. Devuelven el objeto de
tipo AlertDialog.Builder.

Sintaxis

public AlertDialog.Builder setIcon (Drawable icon)


public AlertDialog.Builder setIcon (int iconId)

Ejemplo

builder.setIcon(android.R.drawable.ic_dialog_alert);

Es posible agregar botones en una caja de dilogo para interactuar con el usuario permitindole,
por ejemplo, anular o confirmar una accin. La clase AlertDialog.Builder define tres botones,
todos opcionales. Se corresponden con una respuesta negativa, neutra o positiva del usuario. Estos
botones se agregan a la caja de dilogo utilizando respectivamente
los mtodos setNegativeButton, setNeutralButton y setPositiveButton. Estos
mtodos reciben como primer parmetro el texto que se muestra sobre el botn que se representa
bien mediante una cadena de caracteres, o bien mediante el identificador del recurso. Su segundo
parmetro es un objeto de tipo DialogInterface.OnClickListener cuyo
mtodo onClick se invoca cuando el usuario hace clic sobre el botn correspondiente. Estos
mtodos devuelven, tambin, el objeto de tipo AlertDialog.Builder.

El botn positivo se posiciona automticamente en la parte izquierda, el neutro en el medio y


el negativo a la derecha. Siendo opcionales, existen mltiples combinaciones en la
visualizacin de estos botones.

Los trminos negativos, neutros o positivos sirven para ayudar al desarrollador. No imponen
ninguna restriccin. Si bien no se recomienda, es posible anular una accin desde un botn
positivo y validar una accin desde un botn negativo...

Sintaxis

public AlertDialog.Builder setNegativeButton (CharSequence text,


DialogInterface.OnClickListener listener)
107
public AlertDialog.Builder setNegativeButton (int textId,
DialogInterface.OnClickListener listener)
public AlertDialog.Builder setNeutralButton (int textId,
DialogInterface.OnClickListener listener)
public AlertDialog.Builder setNeutralButton (CharSequence text,
DialogInterface.OnClickListener listener)
public AlertDialog.Builder setPositiveButton (int textId,
DialogInterface.OnClickListener listener)
public AlertDialog.Builder setPositiveButton (CharSequence text,
DialogInterface.OnClickListener listener)

Ejemplo

builder.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
})
.setNegativeButton(android.R.string.no,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
}
);

En vez de un mensaje, es posible informar una lista de elementos que incluyan eventualmente
casillas de opcin o botones de radio. Es posible hacer esto utilizando uno de
los mtodos setItems. Reciben como parmetro bien el identificador de un recurso de tipo tabla, o
bien una tabla de secuencias de caracteres. Su segundo parmetro es un objeto de
tipo DialogInterface.OnClickListener cuyo mtodo onClick se invoca cuando el usuario
presiona sobre el botn correspondiente. Estos mtodos devuelven el objeto de
tipo AlertDialog.Builder.

Esta lista puede incluir botones de radio o casillas de opcin sobre cada uno de los elementos
para componer una lista de seleccin nica o mltiple. Para ello, en vez del
mtodo setItems, se utilizar respectivamente los
mtodos setSingleChoiceItems ysetMultiChoiceItems.

Sintaxis

public AlertDialog.Builder setItems (int itemsId,


DialogInterface.OnClickListener listener)
public AlertDialog.Builder setItems (CharSequence[] items,
DialogInterface.OnClickListener listener)

Ejemplo

final String[] seleccion = { "Selecci!n 1", "Selecci!n 2", "Selecci!n 3" };

builder.setItems(choix, new DialogInterface.OnClickListener() {


public void onClick(DialogInterface dialog, int item) {
Toast.makeText(MiActividadPrincipal.this, seleccion[item],
Toast.LENGTH_SHORT).show();
}
});

Si bien la clase AlertDialog.Builder proporciona un mtodo show que permite crear y


mostrar la caja de dilogo, se recomienda dejar su gestin a la actividad o al fragmento del que
108
depende.

De este modo, una vez se hayan definido los distintos elementos que componen la caja de dilogo,
slo queda generar la instancia de tipo AlertDialog correspondiente invocando
almtodo create del objeto de tipo AlertDialog.Builder asociado. Este mtodo devuelve
una instancia de tipo AlertDialog que podr explotarse en la actividad o el fragmento
correspondiente.

Sintaxis

public AlertDialog create ()

Ejemplo

AlertDialog dialogo = builder.create();

Para una actividad, es necesario implementar el mtodo onCreateDialog que devolver la


instancia de tipo AlertDialog creada aqu. La visualizacin de la caja de dilogo se realiza
mediante el mtodo showDialog de la actividad.

Para un fragmento, es necesario crear una nueva clase que herede de la


clase DialogFragment e implemente el mtodo onCreateDialog que devolver la
instancia de tipo AlertDialog creada aqu. La creacin y la visualizacin del fragmento, y por
tanto de la caja de dilogo, se realizan desde la actividad, como para cualquier fragmento.

3. Barra de notificacin
La barra de notificacin o barra de estado es el sistema que proporciona Android para permitir a las
aplicaciones que se ejecuten como tarea de fondo y advertir al usuario sin perturbar su uso actual del
dispositivo. Esta barra recibe y almacena las notificaciones que se le envan desde las aplicaciones.

En las versiones inferiores a Android 3.0 (API 11), se sita en la parte superior en la pantalla. En su
lado izquierdo, muestra los iconos de las notificaciones que ha recibido. Estirndolas hacia abajo,
aparece el detalle de cada una de ellas.

La visualizacin de una notificacin en la barra de notificacin se realiza utilizando un layout por


defecto. ste est compuesto por un icono, un ttulo en una primera lnea, un mensaje en una
segunda lnea y una fecha. Es posible especificar una accin a realizar cuando el usuario haga clic
sobre la notificacin.

Tras la recepcin de la notificacin, es posible iniciar otras funcionalidades solas o combinadas entre
s tales como la visualizacin de un mensaje en la parte superior de la barra de notificacin, la
reproduccin de un sonido, la vibracin del dispositivo o incluso el parpadeo de la luz del dispositivo.

Tambin es posible utilizar un layout personalizado para mostrar la notificacin en la barra de


notificacin en lugar del layout por defecto.

Desde Android 3.0 (API 11), la ubicacin de las notificaciones se sita en lo sucesivo en la parte
inferior derecha de la pantalla. El layout por defecto permite agregar una imagen de
tipo Bitmapadems del icono, as como cierta informacin.

a. Creacin de una notificacin

La clase Notification.Builder hace su aparicin con Android 3.0 (API 11) con el objetivo de
facilitar la creacin de notificaciones representadas por la clase Notification. La
clase Notification.Builder proporciona todo un conjunto de mtodos que permiten definir los
109
elementos de una notificacin sin utilizar directamente el objeto de tipo Notification. No
detallaremos aqu ms que las caractersticas esenciales de una notificacin estndar.

Para las versiones inferiores a Android 3.0 (API 11), que no pueden utilizar la
claseNotification.Builder, hay que crear directamente un objeto de tipo Notification y pasarle
los elementos que se quieren utilizar en sus variables pblicas.

Para crear una notificacin con la clase Notification.Builder, basta con utilizar su
constructor. ste recibe como parmetro el contexto de la aplicacin.

Sintaxis

public Notification.Builder (Context context)

Ejemplo

Notification.Builder notificationBuilder =
new Notification.Builder(this);

Los mtodos setContentTitle, setContentText y setContentInfo permitenespecificar


respectivamente el ttulo, el mensaje y la informacin de la notificacin. Reciben como parmetro
una secuencia de caracteres de tipo CharSequence y devuelven el objeto Builderen curso de
modo que permita encadenar las sucesivas llamadas.

La llamada al mtodo setContentInfo puede reemplazarse por la llamada al


mtodo setNumber si la informacin que se quiere visualizar slo afecta a un nmero
entero. La visualizacin del resultado ser ms apropiada.

Sintaxis

public Notification.Builder setContentTitle (CharSequence title)


public Notification.Builder setContentText (CharSequence text)
public Notification.Builder setContentInfo (CharSequence info)

Ejemplo

notificationBuilder.setContentTitle("T!tulo de la notificaci#n")
.setContentText("Mensaje de la notificaci#n")
.setContentInfo("Informaci#n");

Los mtodos setSmallIcon permiten especificar el icono que se quiere mostrar en la barra de
notificacin y en la propia notificacin. Reciben como parmetro el identificador nico de la imagen y
un ndice para identificar la imagen si forma parte de un conjunto de imgenes de
tipo LevelListDrawable.

Se recomienda encarecidamente especificar un icono que permita al usuario ver rpidamente


la presencia de la notificacin.

Sintaxis

public Notification.Builder setSmallIcon (int icon)


public Notification.Builder setSmallIcon (int icon, int level)

Ejemplo

110
notificationBuilder.setSmallIcon(R.drawable.icon);

El mtodo setLargeIcon permite agregar una imagen en la notificacin adems de la del icono.
Este mtodo recibe como parmetro el objeto de tipo Bitmap que se quiere mostrar y devuelve el
objeto Builder en curso.

Sintaxis

public Notification.Builder setLargeIcon (Bitmap icon)

Ejemplo

notificationBuilder.setLargeIcon(bitmap);

El mtodo setContentIntent permite especificar una accin, por ejemplo la ejecucin de una
actividad, que se ejecutar cuando el usuario haga clic sobre la notificacin. Para ello, este mtodo
recibe como parmetro un objeto de tipo PendingIntent.

Sintaxis

public Notification.Builder setContentIntent (PendingIntent intent)

Ejemplo

notificationBuilder.setContentIntent(pendingIntent);

Por ltimo, el mtodo getNotification permite crear la notificacin segn las caractersticas
presentadas. Devuelve el objeto de tipo Notifi-cation.

Sintaxis

public Notification getNotification ()

Ejemplo

Notification notification = notificationBuilder.getNotification();

b. Envo de una notificacin

La gestin y la ejecucin de las notificaciones las realiza el gestor de notificaciones. Se trata de un


servicio del sistema que gestiona las notificaciones.

Como para todo servicio del sistema, es posible recuperar su instancia utilizando
el mtodo getSystemService. ste recibe como parmetro el nombre del servicio y devuelve la
instancia de tipo Object que quiere convertir en el tipo de servicio concreto.

En este caso, el servicio deseado es el gestor de notificaciones que viene indicado por
la constante Context.NOTIFICATION_SERVICE de tipo NotificationManager.

Sintaxis

public abstract Object getSystemService (String name)

Ejemplo

NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);

Cada notificacin debe estar identificada de forma nica en la aplicacin. Para ello, el identificador se
111
representa por la combinacin de un entero y de una cadena de caracteres. Si la cadena es null, el
valor entero representa por s solo al identificador. En ese caso, debe ser nico en la aplicacin.

Si se utiliza un identificador existente, la notificacin a la que reenva se modificar con los nuevos
parmetros indicados.

El envo de una notificacin se realiza a continuacin invocando simplemente a uno de


los mtodos notify. stos reciben como parmetro el identificador de la notificacin y la
notificacin correspondiente.

Sintaxis

public void notify (int id, Notification notification)


public void notify (String tag, int id, Notification notification)

Ejemplo

notificationManager.notify(1, notificacion);

112
Internacionalizacin
Una de las principales claves del xito de los smartphones Android es la oferta de cientos de miles de
aplicaciones a travs del Android Market. Como veremos en otro captulo (vase el captulo Publicar una
aplicacin - Publicacin de la aplicacin en el Android Market), el Android Market permite descargar
aplicaciones en distintos pases del mundo. Por ello, si el desarrollador quiere satisfacer de la mejor
forma a los usuarios, tendr que proveer aplicaciones en su idioma. Tendr no slo que traducir los
textos sino tambin adaptar el formato de los nmeros, las monedas, los grficos, los archivos de
sonido...

Android tiene en cuenta la internacionalizacin de forma nativa. De modo que es relativamente sencillo
programar una aplicacin multiidioma.

A menudo se abrevia el vocablo ingls internacionalizacin (internationalisation) utilizando el


trmino i18n, dado que se trata de una i, seguida de 18 caracteres, y termina con una n.

Durante la ejecucin de una aplicacin, Android utiliza automticamente los datos de la aplicacin que
mejor se corresponden con el dispositivo y su configuracin.

Cuando el dispositivo est configurado para utilizar parmetros regionales distintos a los que propone
la aplicacin, Android utiliza los parmetros regionales por defecto de la aplicacin.

El archivo strings.xml debe estar ubicado por defecto en la carpeta res/values/.


En este archivo se indican los valores de las cadenas de caracteres en la lengua que se utilizar por
defecto.

Sintaxis

<string name="nombre recurso">"cadena de caracteres"</string>

Las comillas que agrupan la cadena de caracteres no son obligatorias pero permiten utilizar
caracteres especiales tales como el apstrofe...

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="nombre_aplicacion">"MyApplication"</string>

<string name="aceptar">"Ok"</string>
<string name="bienvenida">"Welcome!"</string>
<string name="confirmacion">"Are you sure?"</string>

</resources>

En este ejemplo, el idioma ingls se utiliza como idioma por defecto.

El archivo de traduccin por defecto, strings.xml, debe existir obligatoriamente y contener


todas las cadenas de caracteres utilizadas en la aplicacin. Si no fuera el caso, la aplicacin no
funcionar y aparecer un mensaje de error.

A continuacin bastar con traducir todo o parte de este archivo en los idiomas deseados creando
nuevos archivos strings.xml en las ubicaciones correspondientes:

Ejemplo de traduccin espaola - archivo res/values-es/strings.xml


113
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="nombre_aplicacion">"MiAplicacion"</string>

<string name="bienvenida">"Bienvenido!"</string>
<string name="confirmacion">"Est seguro/a?"</string>

</resources>

Tambin es posible restringir la aplicacin de una traduccin a un pas adems de a una lengua.

Por ejemplo, se crear el archivo res/values-es-rAR/strings.xml para la traduccin espaola


utilizada en Argentina.

Para un recurso concreto, Android buscar siempre en primer lugar el recurso en el parmetro regional
correspondiente a la configuracin del dispositivo. Si el recurso no existe, se buscar en los archivos
por defecto.

Por ejemplo, supongamos que los parmetros regionales del dispositivo estn configurados para
Espaa y que el recurso buscado es la traduccin de la palabra Aceptar. Android buscar a
continuacin el recurso en el archivo res/values-es/strings.xml. No lo encontrar. Lo buscar
a continuacin en el archivo por defecto res/values/strings.xml. All el valor s aparece. Android
utilizar por tanto este valor.

Si fuera necesario, tambin es posible internacionalizar los dems tipos de recursos tales como layouts,
recursos grficos y dems recursos especializando del mismo modo las carpetas correspondientes.

Ejemplo

res/drawable/...

res/drawable-es/...

res/drawable-es-rAR/...

Es posible recuperar la secuencia de caracteres correspondiente a un recurso utilizando uno de


losmtodos getString. stos permiten parametrizar el identificador del recurso. Uno de ellos permite
tambin pasar como parmetro argumentos complementarios para reemplazarlos en la cadena de
caracteres. Estos mtodos devuelven la cadena de caracteres construida de esta manera.

Sintaxis

public final String getString (int resId)


public final String getString (int resId, Object... formatArgs)

Ejemplo

String msg = getString(R.string.mensajes_no_leidos, "Usuario",


5);

114
8. Componentes
principales de la
aplicacin

115
Introduccin
Efectivamente, las actividades, abordadas en un captulo anterior, no son los nicos componentes de
la aplicacin. Existen otros que responden a necesidades distintas.

Por ello, en este captulo descubriremos los fragmentos, una especie de mini-actividad, que permiten
explotar plenamente pantallas de gran tamao. Estudiaremos a continuacin los servicios, que
permiten ejecutar una tarea de fondo sin interfaz grfica. A continuacin llegar el turno a los
receptores de eventos que se activan solamente tras la recepcin de un mensaje.

Por ltimo, si bien no son un componente principal de la aplicacin hablando con propiedad,
ilustraremos la implementacin de una lista, pues se trata de uno de los elementos ms utilizados en
las aplicaciones.

116
Fragmento
La integracin de Android en dispositivos con pantallas extra-grandes, tales como las tabletas tctiles, ha
revelado nuevas necesidades, en particular a la hora de utilizar plena, eficaz y fcilmente las grandes
resoluciones que proporcionan estas pantallas.

La versin de Android 2.3 (API 9) incluy una primera toma de contacto con estas pantallas gracias
alatributo android:xlargeScreens en la etiqueta supports-screens. ste permita a las
aplicaciones aprovechar los recursos de forma adaptada, especificando en concreto la nueva
etiqueta xlarge. Pero esto no era sino lo mnimo necesario...

Hara falta esperar a la versin de Android 3.0 (API 11) y su nuevo lote de novedades para aportar
soluciones especficas a las pantallas extra-grandes.

Una de estas novedades es el fragmento.

Recuerde, si bien se introdujo con Android 3.0 (API 11), el concepto de fragmento puede
encontrarse en las versiones de Android 1.6 (API 4) y superiores importando la librera de
compatibilidad descendente de Android en el proyecto (vase el captulo El universo Android -
Entorno de desarrollo).

Un fragmento puede verse a grandes rasgos como una mini-actividad. Ms precisamente, es una entidad
independiente que posee la mayor parte del tiempo una interfaz de usuario. Un fragmento no puede
existir solo, debe estar incluido en una o varias actividades para poder existir.

Una actividad que quiera ofrecer una pantalla de usuario adaptada especialmente a pantallas extra-
grandes podr incluir varios fragmentos, cada uno de ellos con su propio layout. De este modo, la
combinacin de distintos fragmentos permite ofrecer distintas combinaciones de interfaz de usuario. Este
uso de los fragmentos puede realizarse de manera dinmica durante la ejecucin de la actividad.

La clase madre de los fragmentos es la clase Fragment. De forma similar a las clases hijas ofrecidas por
el SDK, especializando la clase madre Activity, existen varias clases hijas de la
clase Fragment que son DialogFragment, ListFragment y PreferenceFragment,representando
fragmentos especializados en funciones particulares.

Para definir un fragmento, hay que crear una clase que herede, directa o indirectamente, de la
clase Fragment e implementar, llegado el caso, los mtodos heredados.

1. Integracin del fragmento


La integracin de un fragmento con una actividad puede realizarse de forma declarativa o de forma
programtica. Si no posee layout, el fragmento slo puede agregarse de forma programtica.

a. Modo declarativo

Recuerde, el modo declarativo permite describir el layout directamente en el cdigo XML.

Para incluir un fragmento en un layout de una actividad, basta con utilizar la etiqueta fragment y
especificar en su atributo android:name el nombre de la clase del fragmento que se quiere
instanciar. Una vez instanciado y habiendo invocado al mtodo onCreateView, la vista que se
recupera se insertar en el layout de la actividad en el lugar de la etiqueta fragment especfica.

Como con cualquier otro widget, es posible indicar sus dimensiones mediante los
atributos android:layout_width y android:layout_height. Tambin tiene que poder
identificarse. Para ello, es posible asignarle un identificador mediante el atributo android:id o una
cadena de caracteres mediante el atributo android:tag. Si no se le asigna ninguno de estos
atributos, el sistema utilizar el identificador interno de la vista del fragmento.

En lo que queda de captulo, aparecen varios mtodos que hacen referencia al identificador
117
nico de la vista contenedora. En modo declarativo, este identificador corresponde simplemente
con el valor del atributo android:id especificado en la etiqueta fragment.

Sintaxis

<fragment android:name="nombre completo de la clase"


android:id="@[+][paquete:]id/nombre_recurso"
android:tag="recurso_texto"
android:layout_width="dimensi!n"
android:layout_height="dimensi!n"
... />

Ejemplo

<fragment
android:name="es.midominio.android.miapli.MiFragmento"
android:id="@+id/mifragmento"
android:layout_width="match_parent"
android:layout_height="match_parent" />

b. Modo programtico

El gestor de fragmentos permite realizar diversas operaciones relativas a stos.

La instancia del gestor de fragmentos, de tipo FragmentManager, la devuelve


el mtodo getFragmentManager invocado desde la actividad que lo alberga.

Sintaxis

public FragmentManager getFragmentManager ()

Ejemplo

FragmentManager fragmentManager = getFragmentManager();

Las operaciones relativas a los fragmentos deben realizarse dentro de transacciones. Una misma
transaccin puede contener una o varias operaciones secuenciales. Esta transaccin, o serie de
operaciones, se realiza de forma atmica. Es decir, que todas las operaciones contenidas en la
transaccin forman un todo indivisible, y se realizarn todas prcticamente al mismo tiempo.

Para crear una transaccin, hay que invocar al mtodo beginTransaction del gestor de
fragmentos recuperado anteriormente. ste devuelve la transaccin bajo la forma de un objeto de
tipo FragmentTransaction.

Sintaxis

public abstract FragmentTransaction beginTransaction ()

Ejemplo

FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();

La transaccin puede recibir a continuacin una lista de operaciones relativas a los fragmentos, como
por ejemplo agregar o suprimir fragmentos.

El mtodo add del objeto de tipo FragmentTransaction permite agregar un fragmento en una
vista contenedora. Este mtodo recibe como parmetro el fragmento de tipo Fragment y el
identificador nico de la vista contenedora que contiene el fragmento, o bien la etiqueta asociada al
fragmento, o bien las dos. Este mtodo devuelve el objeto de tipo FragmentTransactionde cara a
poder encadenar las llamadas a estos mtodos.
118
El uso de una etiqueta es el nico medio para identificar un fragmento que no posee vistas.

Las vistas de los fragmentos se agregan al contenedor en el orden de llamada al


mtodo add.

Sintaxis

public abstract FragmentTransaction add (int containerViewId,


Fragment fragment)
public abstract FragmentTransaction add (Fragment fragment,
String tag)
public abstract FragmentTransaction add (int containerViewId,
Fragment fragment, String tag)

Ejemplo

MiFragmento fragmento = new MiFragmento();


fragmentTransaction.add(R.id.vista_contenedora, fragmento);

El mtodo replace del objeto de tipo FragmentTransaction permite reemplazar el o los


fragmentos agregados a la vista contenedora por un nuevo fragmento. Este mtodo recibe como
parmetro el identificador nico de la vista contenedora, el nuevo fragmento de tipo Fragment, y
eventualmente la etiqueta asignada al fragmento. Este mtodo devuelve el objeto de
tipo FragmentTransaction en curso.

Sintaxis

public abstract FragmentTransaction replace (int containerViewId,


Fragment fragment)
public abstract FragmentTransaction replace (int containerViewId,
Fragment fragment, String tag)

Ejemplo

fragmentTransaction.replace(R.id.vista_contenedora, fragmento);

El mtodo remove del objeto de tipo FragmentTransaction permite suprimir un fragmento y sus
eventuales vistas de la vista contenedora. Este mtodo recibe como parmetro la instancia del
fragmento que se quiere suprimir y devuelve el objeto de tipo FragmentTransaction en curso.

Sintaxis

public abstract FragmentTransaction remove (Fragment fragment)

Ejemplo

fragmentTransaction.remove(fragmento);

La transaccin as preparada debe ejecutarse invocando a su mtodo commit. Si se ha solicitado


agregar esta transaccin en la pila de las transacciones de fragmentos que detallamos ms adelante,
este mtodo devuelve un valor entero positivo identificando la transaccin. En caso contrario, devuelve
un valor entero negativo.

Sintaxis

public abstract int commit ()

Ejemplo
119
fragmentTransaction.commit();

El gestor de fragmentos permite buscar la instancia de un fragmento particular gracias al identificador


nico de la vista contenedora o a la etiqueta del fragmento. Para ello, el gestor proporciona
respectivamente los mtodos findFragmentById y findFragmentByTag. Estos mtodos
devuelven la instancia de tipo Fragment o null si ningn fragmento se corresponde con el
identificador que se ha proporcionado.

Sintaxis

public abstract Fragment findFragmentById (int id)


public abstract Fragment findFragmentByTag (String tag)

Ejemplo

fragmentManager.findFragmentById(R.id.vista_contenedora);

2. Ciclo de vida
Los mtodos onCreate, onStart, onResume, onPause, onStop y onDestroy son similares a los
de una actividad pero slo aplican al fragmento. Se invocan al mismo tiempo que los mismos mtodos de
la actividad host. Esto es as puesto que el ciclo de vida de un fragmento depende tambin del de la
actividad que lo contiene.

Aparecen otros mtodos, especficos del ciclo de vida de un fragmento. Se trata de los
mtodos onAttach, onCreateView, onActivityCreated, onDestroyView y onDetach.

a. onAttach

El mtodo onAttach es el primer mtodo del ciclo de vida del fragmento que se invoca tras su
creacin. Recibe como parmetro la instancia de la actividad host que lo contiene.

La instancia de la actividad host que se recibe como parmetro del


mtodo onAttachtambin puede recuperarse en el fragmento en cualquier momento
mediante su mtodo getActivity.

Sintaxis

public void onAttach (Activity activity)

Ejemplo

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
procesamiento(activity);
}

b. onCreateView

El mtodo onCreateView, opcional, permite pasar la vista raz del layout del fragmento as como
toda la jerarqua de vistas correspondiente que se utilizar para disear el fragmento. Se invoca tras
el mtodo onCreate o despus del mtodo onDestroyView. Recibe como parmetro un objeto de
tipo LayoutInflater que permite agregar vistas al fragmento, la vista contenedora de
tipo ViewGroup, en la que se insertar el fragmento, o null si no existe la vista contenedora, y un
objeto de tipo Bundle que contiene los datos salvaguardados de un estado que se pasa al
fragmento. Debe devolver la vista raz de tipo View del layout del fragmento. Por defecto, este
mtodo devuelve null, lo que significa que el fragmento no tiene interfaz grfica.
120
Sintaxis

public View onCreateView (LayoutInflater inflater,


ViewGroup container, Bundle savedInstanceState)

Ejemplo

@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.mifragmento, container,
false);
}

La asociacin entre la vista y la vista contenedora la realiza el sistema automticamente. Esto es as


porque, en este ejemplo, se especifica que la vista no debe estar asociada, una segunda vez, a su
vista contenedora especificando el valor false en el ltimo parmetro del mtodo inflate.

c. onActivityCreated

El mtodo onActivityCreated se invoca cuando la actividad host y su jerarqua de vistas estn


creadas. Esta jerarqua comprende en particular, llegado el caso, la del fragmento en curso. En
concreto, esta llamada se realiza tras la ejecucin del mtodo onCreate de la actividad host. Este
mtodo permite recuperar las instancias de las vistas y restaurarlas si fuera necesario mediante el uso
del objeto de tipo Bundle que contiene los datos salvaguardados de un estado que se pasa al
fragmento.

Sintaxis

public void onActivityCreated (Bundle savedInstanceState)

Ejemplo

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
restauraElFragmento(savedInstanceState);
}

d. onDestroyView

El mtodo onDestroyView es el simtrico del mtodo onCreateView. Se invoca justo antes de


que la jerarqua de vistas del fragmento se suprima de la vista contenedora. Este mtodo se invoca
incluso si el fragmento no ha proporcionado ninguna vista raz en el mtodo onCreateView.

Sintaxis

public void onDestroyView ()

Ejemplo

@Override
public void onDestroyView() {
super.onDestroyView();
limpiaVista();
}

e. onDetach

El mtodo onDetach es el simtrico del mtodo onAttach. Se invoca cuando se libera el fragmento
de la actividad. Es el ltimo mtodo puesto a disposicin del desarrollador que se invoca antes de la
121
destruccin efectiva e irreversible del fragmento.

Este mtodo permite liberar recursos ligados al fragmento.

Sintaxis

public void onDetach ()

Ejemplo

@Override
public void onDetach() {
super.onDetach();
procesamiento();
}

3. Salvaguarda y restauracin del estado


De forma similar a una actividad, un fragmento tambin puede salvaguardar su estado cuando se
destruye para poder reconstruirlo de forma idntica ms adelante.

La salvaguarda de este estado se realiza en el mtodo onSaveInstance-State de la


clase Fragment. Es la actividad host del fragmento la que decide cundo salvaguardar el estado del
fragmento y, por tanto, invocar a este mtodo. La sintaxis y el principio son los mismos que para el
mtodo onSaveInstanceState de la clase Activity.

La restauracin del fragmento puede realizarse en los


mtodo onCreate, onCreateView yonActivityCreated que reciben todos ellos el objeto de
tipo bundle anteriormente salvaguardado.

4. Pila de fragmentos
De forma similar a la pila de actividades, existe una pila de transacciones de fragmentos llamadaBack
Stack que permite al usuario volver atrs, en concreto a transacciones de fragmentos anteriores. Una
transaccin consiste en una serie de operaciones que se realizan de forma atmica, de modo que la
vuelta atrs, o desapilamiento, de una transaccin afecta al conjunto de operaciones contenidas en
esta transaccin.

A diferencia de las actividades, esta pila la gestiona completamente el desarrollador, en particular para
las transacciones de fragmentos y el gestor de fragmentos.

Por ejemplo, cada una de las transacciones de fragmentos puede indicar que tiene que ser incluida en la
pila utilizando el mtodo addToBackStack. Este mtodo debe invocarse antes del mtodo commit.
Recibe como parmetro una cadena de caracteres opcional que identifica a la transaccin, y devuelve la
transaccin en curso.

Tras el commit, el fragmento reemplazado o suprimido se agrega a la pila y se invoca a sus


mtodo onPause, onStop y onDestroyView.

En el caso en que el fragmento reemplazado o suprimido no sea agregado a la pila, es decir, si


el mtodo addToBackStack no se utiliza, se invocan sus
mtodos onDestroy yonDetach y ste se destruye a continuacin.

Sintaxis

public abstract FragmentTransaction addToBackStack (String name)

Ejemplo

OtroFragmento otroFragmento = new OtroFragmento();


122
fragmentTransaction.replace(R.id.fragmento, otroFragmento)
.addToBackStack(null).commit();

En cualquier momento, el usuario puede volver atrs, y desapilar las transacciones de fragmentos
presionando la tecla Volver. La aplicacin tambin puede desapilar las transacciones de fragmentos de
la pila utilizando una de las mltiples variantes de
los mtodos popBackStack o popBackStackImmediate del gestor de fragmentos.

La diferencia entre los mtodos popBackStack y popBackStackImmediate reside en el hecho de


que la operacin de desapilar se realiza de forma asncrona en el primero, o bien inmediatamente en las
llamadas al segundo.

Las variantes ms simples no reciben ningn parmetro y desapilan la ltima transaccin agregada a la
pila. Los dems reciben como parmetro el identificador de la transaccin hasta la que se desea
desapilar. Este identificador es bien el identificador de la transaccin devuelto anteriormente por el
mtodo commit, o bien el nombre de la transaccin que se ha pasado como parmetro al
mtodo addToBackStack.

Por ltimo, es posible pasar un flag como parmetro con el valor POP_BACK_STACK_INCLUSIVEpara
indicar que la transaccin designada tambin debe desapilarse, o el valor 0 en el caso contrario.

El fragmento que se encuentra en la parte superior de la pila es, en lo sucesivo, el fragmento


activo. Retoma su ciclo de vida tras el mtodo onCreateView.

Sintaxis

public abstract void popBackStack ()


public abstract void popBackStack (int id, int flags)
public abstract void popBackStack (String name, int flags)
public abstract boolean popBackStackImmediate ()
public abstract boolean popBackStackImmediate (int id, int flags)
public abstract boolean popBackStackImmediate (String name, int flags)

Ejemplo

fragmentManager.popBackStack();

El gestor de fragmentos ofrece otras funcionalidades tales como especificar animaciones para
las transiciones, un ttulo de tipo breadcrumb o incluso la posibilidad de agregar un listener que
reaccione a modificaciones en la pila. Para obtener ms informacin, consulte respectivamente
losmtodos setTransition, setBreadCrumbTitle yaddOnBackStackChangedListener.

123
Servicio
Un servicio es un componente de aplicacin independiente que no tiene interfaz grfica y que se
ejecuta en segundo plano. Como su propio nombre indica, este componente de aplicacin representa
un servicio, en el sentido estricto del trmino, que est disponible para la aplicacin que lo contiene y/o
para otras aplicaciones.

Un servicio proporciona una interfaz que permite a los dems componentes de la aplicacin
comunicarse con l.

Para definir un servicio, es preciso crear una clase que herede de la clase Service e implementar,
llegado el caso, los mtodos heredados.

Como con la actividad, la ejecucin de un servicio se realiza en el thread principal del proceso de la
aplicacin de la que forma parte.

Un servicio no se ejecuta en un proceso separado, ni en un thread concurrente del thread


principal. Por tanto, no debe bloquear el thread principal durante ms de diez segundos, igual
que ocurre con las actividades. En el caso de tener que realizar un procesamiento largo, el servicio
puede crear un thread concurrente para ello (vase el captulo Concurrencia, seguridad y red -
Programacin concurrente). O, para mayor comodidad, el servicio puede heredar de
la clase IntentService que facilita la gestin de procesamientos asncronos.

Es posible utilizar un servicio de varias formas: directamente, estableciendo una conexin con l o bien
combinando ambos modos.

1. Declaracin
Para poder utilizarse, un servicio debe estar declarado en el sistema mediante el manifiesto.

La etiqueta service contiene la informacin propia de un servicio. Como la mayora de etiquetas,


proporciona multitud de atributos. Descubriremos algunos de ellos a medida que vayamos
descubriendo las funcionalidades correspondientes. He aqu la sintaxis de esta etiqueta y de sus tres
atributos principales:

Sintaxis

<service android:icon="recurso_grfico"
android:label="recurso_texto"
android:name="cadena de caracteres"
... >
...
</service>

Los atributos android:icon y android:label tienen las mismas funciones que para la
etiqueta application pero limitndose al servicio. Si no se especifican, se utilizarn por defecto los
de la aplicacin.

El atributo android:name permite especificar el nombre del servicio afectado, es decir, su nombre
de clase Java precedido del nombre completo del paquete. De forma similar a la actividad, este
nombre puede empezar por un punto, queriendo decir que se utilizar el nombre del paquete
indicado por el atributo package de la etiqueta manifest para componer el nombre completo.

Ejemplo

<service android:name=".MiServicio"/>

2. Uso directo
124
Es posible ejecutar un servicio invocando al mtodo startService y pasndole como parmetro
un objeto intencin (intent), implcita o explcita, que permita identificar el servicio que se va a
ejecutar.

Si el servicio no existe, el mtodo devuelve null, en caso contrario devuelve un objeto


de tipo ComponentName, objeto que permite simplemente identificar un componente de aplicacin
mediante su paquete y el nombre de su clase.

Sintaxis

public abstract ComponentName startService (Intent service)

Ejemplo

Intent intent = new Intent(this, MiServicio.class);


startService(intent);

Una vez iniciado, este mismo servicio puede recibir nuevos intents y, por tanto, nuevas
instrucciones que procesar, llamando de nuevo al mtodo startService. El servicio
procesar a continuacin estos intents como si se tratase del primer intent recibido durante el
arranque del servicio. Este truco permite, en ciertos casos, evitar tener que establecer una
conexin con el servicio tal y como se describe ms adelante.

Este servicio puede detenerse en cualquier momento. Sea cual sea el nmero de llamadas al
mtodo startService realizadas, una nica llamada al mtodo stopService detiene el servicio
pasado como parmetro. Este mtodo devuelve true si se ha encontrado y detenido algn servicio
en curso, false en caso contrario.

Sintaxis

public abstract boolean stopService (Intent service)

Ejemplo

Intent intent = new Intent(this, MiServicio.class);


stopService(intent);

El servicio tambin puede detenerlo su propio dueo invocando


los mtodos stopSelf o stopSelfResult. Este ltimo mtodo recibe como parmetro un
identificador nico designando la ltima consulta recibida por el mtodo onStartCommand. Esto
permite asegurar que no existen otras consultas pendientes por procesar y permite, por tanto, parar
el servicio. El mtodo stopSelfResult devuelve true si el servicio se detiene, o false en caso
contrario, particularmente si existen consultas por procesar. El mtodo onStartCommand se detalla
ms adelante.

Sintaxis

public final void stopSelf ()


public final boolean stopSelfResult (int startId)

Ejemplo

public void errorDeProcesamiento() {


stopSelf();
}

3. Uso estableciendo una conexin


Un componente de aplicacin tambin puede establecer una conexin con un servicio, si se lo
125
permite, sin tener que pasar por el uso directo descrito anteriormente.

Para ello, el servicio proporciona una interfaz a los dems componentes. Estos ltimos utilizan
entonces esta interfaz para establecer un enlace entre ellos y hacen uso de l para comunicarse.

En concreto, la conexin se realiza invocando al mtodo bindService. Este mtodo recibe como
parmetro un objeto intent que designa el servicio a ejecutar, un objeto que implementa
la interfaz ServiceConnection y unos flags. La interfaz ServiceConnection proporciona dos
mtodos,onServiceConnected y onServiceDisconnected, que se invocan respectivamente
cuando se establece y cuando se pierde la conexin con el servicio. Este mtodo devuelve true si la
conexin al servicio se ha establecido con xito.

Si es preciso, se ejecuta el servicio si no est ya en ejecucin mediante la llamada al


mtodo bindService.

Sintaxis

public abstract boolean bindService (Intent service,


ServiceConnection conn, int flags)

Ejemplo

Intent intent = new Intent(this, MiServicio.class);


bindService(intent, conexion, Context.BIND_AUTO_CREATE);

La desconexin con el servicio se realiza invocando al mtodo unbindService que recibe como
parmetro el mismo objeto que se ha pasado durante el establecimiento de la conexin mediante el
mtodo bindService.

Sintaxis

public abstract void unbindService (ServiceConnection conn)

Ejemplo

unbindService(conexion);

4. Ciclo de vida
El ciclo de vida de un servicio describe los estados en los que se puede encontrar el servicio entre su
creacin, la instanciacin, y su muerte, la destruccin de dicha instanciacin. Este ciclo de vida
depende de la eleccin de uso del servicio.

O, como se ha comentado antes, es posible combinar el uso directo del servicio y la implementacin
de una conexin con el servicio. Por ello, la llamada al mtodo stopService puede que no se lleve
a cabo si se ha realizado una conexin con el servicio despus de haber ejecutado la actividad
mediante el mtodo startService.

Tras cada cambio de estado se invoca un mtodo que puede derivarse en la clase del servicio.

Cada uno de estos mtodos debe invocar a su mtodo padre, en caso contrario se generar
una excepcin.

a. onCreate

El mtodo onCreate se invoca automticamente tras la creacin del servicio, bien sea mediante el
mtodo startService o el mtodo bindService.

Sintaxis
126
public void onCreate ()

Ejemplo

@Override
public void onCreate() {
super.onCreate();
init();
}

b. onStartCommand

El mtodo onStartCommand se invoca automticamente cada vez que un cliente ejecuta el


servicio utilizando el mtodo startService.

Este mtodo recibe como parmetro el intent que se proporciona al mtodo StartService, los
flags y un identificador nico que designa al procesamiento de este intent. Este identificador puede
pasarse al mtodo stopSelfResult llegado el caso. El mtodo onStartCommand devuelve un
valor que indica cmo reiniciar el servicio si se ha destruido prematuramente.

Sintaxis

public int onStartCommand (Intent intent, int flags, int startId)

Ejemplo

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mStartId = startId;
return super.onStartCommand(intent, flags, startId);
}

c. onBind

El mtodo onBind se invoca automticamente tras cada peticin de establecimiento de conexin.


Este mtodo recibe como parmetro el objeto intent que se proporciona al mtodo bindServicey
devuelve un objeto que implementa la interfaz IBinder y que permite comunicarse con el servicio.

Preste atencin, el intent recibido se desliga de los datos Extras que se le pudieran haber
proporcionado.

Sintaxis

public abstract IBinder onBind (Intent intent)

Ejemplo

private final IBinder mBinder = new LocalBinder();

@Override
public IBinder onBind(Intent intent) {
return mBinder;
}

d. onUnbind

El mtodo onUnbind se invoca automticamente cada vez que se cierra una conexin. Este
mtodo recibe como parmetro el objeto intent que se proporciona al mtodo bindService. Por
defecto, devuelve false. Devolver true 127 permite llamar al mtodo onRebind en futuras
reconexiones.

Sintaxis

public boolean onUnbind (Intent intent)

Ejemplo

@Override
public boolean onUnbind(Intent intent) {
procesamiento(intent);
return super.onUnbind(intent);
}

El mtodo onRebind se invoca nicamente si el mtodo onUnbind devuelve true. Este mtodo
es similar al mtodo onBind.

Sintaxis

public void onRebind (Intent intent)

Ejemplo

@Override
public void onRebind(Intent intent) {
procesamiento(intent);
super.onRebind(intent);
}

e. onDestroy

El mtodo onDestroy es el simtrico del mtodo onCreate. Lo invoca el sistema


automticamente antes de suprimir un servicio. Es el ltimo mtodo que se pone a disposicin del
desarrollador antes de destruir efectiva e irreversiblemente el servicio.

Este mtodo permite liberar los recursos ligados al servicio, por ejemplo un thread.

Sintaxis

public void onDestroy ()

Ejemplo

@Override
public void onDestroy() {
suprimeThread();
super.onDestroy();
}

128
Receptor de eventos
Un receptor de eventos es un componente de aplicacin cuyo rol consiste nicamente en recibir
eventos y procesarlos como debe.

De forma similar a un servicio, un receptor de eventos no posee una interfaz grfica. Si bien cuando
recibe un mensaje quiere informar al usuario, puede hacerlo usando por ejemplo la barra de
notificaciones o incluso ejecutando una actividad.

Como para la actividad y el servicio, la ejecucin de un receptor de eventos se opera en el thread


principal del proceso de la aplicacin de la que forma parte.

Un receptor de eventos no debe bloquear el thread principal durante ms de diez segundos


(vase el captulo Concurrencia, seguridad y red - Programacin concurrente).

Para definir un receptor de eventos, es necesario crear una clase que herede de la
clase BroadcastReceiver e implementar nicamente el mtodo onReceive.

1. Evento
Los eventos los produce bien el sistema, o bien las propias aplicaciones. Se envan a todos los
receptores de eventos filtrando el evento concreto.

En particular, estos eventos son objetos de tipo Intent que designan la accin que acaba de
ejecutarse o el evento que acaba de producirse.

Para enviar tal evento, el componente emisor dispone de varios mtodos, de los que el ms sencillo
es el mtodo sendBroadcast. Este mtodo recibe como parmetro el objeto intent que se
difundir de forma simultnea a los receptores.

El envo del intent se realiza de forma asncrona de cara a no bloquear el componente que enva el
evento.

Sintaxis

public abstract void sendBroadcast (Intent intent)

Ejemplo

Intent intent = new Intent(es.midominio.android.miapli.EVT_1);


sendBroadcast(intent);

Utilizando este mtodo, la propagacin del intent hacia todos los componentes de destino se realiza
de forma simultnea, o casi. Es no obstante posible propagar el intent receptor a receptor, uno cada
vez, y esto de forma ordenada o no. El receptor de eventos puede entonces decidir pasar un
resultado al receptor de eventos siguiente e incluso detener la propagacin del intent.

Para ello, es preciso utilizar el mtodo sendOrderedBroadcast. Este mtodo recibe como
parmetros el objeto intent que se quiere difundir a los receptores de eventos y un permiso opcional
que debe poseer el receptor, null en el caso de ninguno.

El orden de llamada a los receptores de eventos se determinar segn


el atributo android:priority de su intent-filter (vase el captulo Los fundamentos -
Intencin).

Sintaxis

public abstract void sendOrderedBroadcast (Intent intent,


String receiverPermission)
129
Ejemplo

Intent intent = new Intent(es.midominio.android.miapli.EVT_1);


sendOrderedBroadcast(intent, null);

2. Declaracin
Para crearlo de forma esttica, un receptor de eventos debe declararse en el sistema a travs del
manifiesto.

La etiqueta receiver contiene informacin propia de un receptor de eventos. Como la mayora de


etiquetas, esta etiqueta proporciona varios atributos. Los descubriremos a medida que vayamos
descubriendo las funcionalidades correspondientes. He aqu la sintaxis de esta etiqueta y de sus
principales atributos:

Sintaxis

<receiver android:icon="recurso_grfico"
android:label="recurso_texto"
android:name="cadena de caracteres"
... >
...
</receiver>

Los atributos android:icon y android:label realizan las mismas funciones que para la
etiqueta application pero limitadas al receptor de eventos. Si no se especifican, se utilizarn por
defecto las de la aplicacin.

El atributo android:name permite especificar el nombre del evento correspondiente, es decir su


nombre de clase Java precedido del nombre entero del paquete. De forma similar a la actividad, este
nombre puede comenzar con un punto queriendo decir que se agregar al paquete indicado por el
atributo package de la etiqueta manifest para componer el nombre completo.

3. Ciclo de vida
El ciclo de vida del componente receptor de eventos es muy simple.

Antes de recibir su primer evento, el componente est inactivo. Se activa cuando recibe un evento
como parmetro de su mtodo onReceive. Tras la salida de este mtodo, el componente se vuelve
inactivo de nuevo.

En efecto, para el sistema, el hecho de salir del mtodo onReceive significa que el componente ha
terminado de procesar el evento, incluso si ha ejecutado un thread asncrono que sigue ejecutndose
tras haber finalizado el mtodo onReceive.

En este caso, si ningn otro componente de la aplicacin est activo, el sistema puede decidir matar
el proceso de la aplicacin y, por tanto, el thread en curso.

Tambin, para evitar este problema, se aconseja lanzar la ejecucin del thread desde un servicio. El
sistema detectar entonces el servicio como componente activo y no matar el proceso, salvo en
aquellos casos extremos en que se necesiten recursos.

El sistema gestiona de forma automtica la creacin y la destruccin de la instancia del receptor de


eventos.

El mtodo onReceive se invoca automticamente tras la recepcin de un evento. Este mtodo


recibe como parmetros el contexto de la aplicacin y el evento de tipo Intent recibido.

Sintaxis

public abstract void onReceive (Context context, Intent intent)


130
Ejemplo

public class ReceptorDeEventos extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent intent) {
}
}

131
Lista
Debido a su pequea pantalla, los smartphones deben adoptar una interfaz de usuario con una cierta
ergonoma especfica. Para ello, y como hemos visto en el captulo Completar la interfaz de usuario, la
plataforma Android proporciona mltiples componentes grficos. Uno de los componentes ms
representativos de la forma de navegar en una aplicacin es la lista de elementos. Se trata de una lista
vertical que posee una barra de desplazamiento. El usuario puede desplazar la lista de arriba a abajo
e inversamente para seleccionar un elemento.

Por ejemplo, las preferencias generales del sistema se muestra bajo la forma de una lista de
elementos. La seleccin de los elementos de primer nivel dirige a una nueva lista de elementos
correspondientes a las preferencias del usuario.

La vista que representa una lista es de tipo ListView. La actividad que gestiona esta vista debe
heredar de la clase ListActivity.

Con la llegada de Android 3.0 (API 11), adaptado a las grandes pantallas de las tabletas tctiles,
aparece una variacin de la clase ListActivity como fragmento de tipo ListFragment.

Sea bajo forma de actividad o de fragmento, el funcionamiento general de una lista es el mismo.
Utilizaremos por tanto el trmino lista para denominar a la vez a las listas de tipo ListActivity y
aquellas de tipo ListFragment a continuacin.

1. Vistas
La vista ListView que representa la lista es de hecho una vista de tipo ViewGroup. Cada lnea de
la lista es una vista hija que se encarga de la representacin grfica de los datos de un nico
elemento de la lista.

Android proporciona layouts predefinidos para los elementos de la lista. Su identificador permite
referenciarlos.

Por ejemplo, el layout android.R.layout.simple_list_item_1 comprende nicamente un


objeto de tipo TextView. El layout android.R.layout.simple_list_item_2 comprende
dos objetos de tipo TextView; el segundo debajo del primero y con un tipo de letra menor.

Si, entre el conjunto de layouts predefinidos por Android, no existe ninguno que responda a
nuestras necesidades, es posible crear layouts personalizados. Como ocurre con los dems
layouts, es posible definirlos bajo la forma de archivos XML.

2. Adaptadores
Los datos de los elementos de una lista puede tener distintos orgenes. Este puede ser el caso, por
ejemplo, de datos almacenados a fuego en la aplicacin, datos que provienen de una base de datos
o datos provistos por un proveedor de contenidos (vase el captulo La persistencia de los datos).

Para poder soportar cualquier tipo de origen de datos, una lista consulta los datos que debe
representar mediante una interfaz de tipo ListAdapter. Este adaptador realiza el enlace entre la
vista que debe mostrar los datos y los propios datos. Android proporciona varios tipos de
adaptadores de lista que implementan la interfaz ListAdapter y se corresponden con los orgenes
y tipos de datos ms comunes.

Por ejemplo, la clase ArrayAdapter<T> representa el adaptador de datos almacenados a fuego


en el cdigo. La clase CursorAdapter representa el adaptador de datos almacenados en base de
datos o provistos por un gestor de contenidos. La clase SimpleCursorAdapter, en s misma, es
una especializacin de este adaptador que permite gestionar fcilmente datos de tipo cadena de
caracteres y de tipo imagen.
132
Por defecto, la clase CursorAdapter y, por tanto, la
clase SimpleCursorAdaptertambin, realizan la carga de los datos en el thread principal.
Esto no est aconsejado de cara a no bloquear la aplicacin (vase el captulo Concurrencia,
seguridad y red - Programacin concurrente). Es preferible, por tanto, realizar estas cargas de
datos en un thread secundario. Desde la versin 3.0 (API 11), Android proporciona las clases
complementarias LoaderManagery CursorLoader que permiten realizar esto de forma ms
sencilla.

Cada tipo de adaptador posee un constructor particular. Por ejemplo, uno de los constructores de la
clase ArrayAdapter<T> recibe como parmetro el contexto de la aplicacin, el identificador del
layout y la tabla de elementos de la lista. La clase ArrayAdapter recibe a su vez un tipo genrico
correspondiente al tipo de los elementos de la tabla.

El tipo genrico que gestiona por defecto la clase ArrayAdapter<T> es la cadena de


caracteres. El mtodo toString se utiliza sobre los objetos de la tabla para recuperar los
elementos de la lista e insertarlos en un objeto de tipo TextView cuyo identificador es id.

Sintaxis de uno de los constructores de la clase ArrayAdapter

public ArrayAdapter (Context context, int textViewResourceId,


T[] objects)

Ejemplo

ArrayAdapter<String> adaptatador =
new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
new String[] { "Fila 1", "Fila 2", "Fila 3" });

3. Implementacin
Uno de los primeros pasos para su implementacin consiste en proporcionar a la lista el adaptador
que se quiere utilizar. Para ello, hay que invocar al mtodo setListAdapter que recibe como
parmetro el adaptador de tipo ListAdapter.

Sintaxis

public void setListAdapter (ListAdapter adapter)

Ejemplo

public class MiActividadPrincipal extends ListActivity {


private static final String[] ETIQUETAS = {
"Fila 1", "Fila 2", "Fila 3", "Fila 4"
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, ETIQUETAS));
}
}

133
9. La persistencia de
los datos

134
Introduccin
Este captulo tiene como objetivo presentar la persistencia de los datos en Android.

Los datos persistentes de una aplicacin son los datos salvaguardados antes del cierre de la
aplicacin de tal forma que puedan ser restaurados posteriormente.

Android proporciona varios mecanismos que permiten gestionar la persistencia de los datos.
Descubriremos los archivos de preferencias, los archivos estndar y las bases de datos.

Terminaremos viendo los proveedores de contenido que, ms all de la persistencia de los datos,
proporcionan un mecanismo de comparticin de datos entre las aplicaciones.

135
Archivos de preferencias
Android proporciona un framework simple para salvaguardar y restaurar los datos de tipos primitivos.
Estos datos se salvaguardan en archivos con formato XML bajo la forma de pares clave-valor. Estos
archivos se denominan archivos de preferencias.

Estudiaremos en primer lugar cmo preparar un archivo de preferencias, a continuacin cmo leer y
escribir datos en l. Terminaremos viendo cmo borrar todos los datos, o parte de ellos, de estos
archivos.

El sistema Android permite visualizar y salvaguardar las preferencias generales del usuario. Toda
aplicacin puede adoptar la misma funcionalidad y la misma representacin. La jerarqua de
preferencias propuesta puede realizarse directamente en un archivo XML. La implementacin de tal
pantalla de preferencias se realiza derivando la clase PreferenceActivity. Desde Android 3.0
(API 11), esta clase funciona de forma conjunta con los fragmentos
de tipo PreferenceFragment para poder, entre otros, mostrar de lado a lado los ttulos de las
secciones y de las preferencias que proponen.

1. Preparar el archivo
Por defecto, un archivo de preferencias est asociado a la actividad que lo crea. Este archivo lleva
automticamente el nombre completo de la actividad co- rrespondiente, por
ejemplo:es.midominio.android.miapli.prefsArch1.xml.

La creacin y la gestin del archivo de preferencias se realizan a travs de un objeto


de tipo SharedPreferences devuelto por el mtodo getPreferences.

Sintaxis

public SharedPreferences getPreferences (int mode)

Este mtodo recibe como parmetro el modo de acceso que se quiere asignar al archivo tras su
creacin. Los valores de este parmetro son:

Context.MODE_PRIVATE: modo privado. Es el modo por defecto. El archivo slo puede


leerse desde la aplicacin en curso, o una aplicacin que comparta el mismo identificador de
usuario.

Context.MODE_WORLD_READABLE: las dems aplicaciones pueden leer el archivo.

Context.MODE_WORLD_WRITEABLE: las dems aplicaciones pueden modificar el archivo.

Ejemplo

SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);

Tambin es posible especificar explcitamente otro nombre de archivo. Esto permite crear varios
archivos de preferencias. Para ello, hay que utilizar el
mtodo getSharedPreferencesespecificando el nombre del archivo como primer parmetro.

Sintaxis

public abstract SharedPreferences getSharedPreferences (String name,


int mode)

Ejemplo

SharedPreferences prefs =
136
getSharedPreferences("nombreArchivoPrefs1.xml",
Context.MODE_PRIVATE);

2. Lectura
Los datos contenidos en un archivo de preferencias se almacenan bajo la forma de pares clave-valor.
Tales asociaciones estn compuestas:

por una clave que es una cadena de caracteres de tipo String.


por un valor de tipo primitivo: boolean (booleano), float (nmero de coma
flotante), into long (enteros) o String (cadena de caracteres).

Para leer los datos contenidos en un archivo de preferencias se utiliza el objeto de


tipo SharedPreferences recuperado anteriormente. Se invoca a continuacin a ciertos accesores
que permiten leer individualmente un dato segn su tipo.

Sintaxis

public abstract boolean getBoolean (String key, boolean defValue)


public abstract float getFloat (String key, float defValue)
public abstract int getInt (String key, int defValue)
public abstract long getLong (String key, long defValue)
public abstract String getString (String key, String defValue)

El primer parmetro es el nombre de la clave. El segundo parmetro es el valor por defecto que se
quiere devolver si no existe la clave.

Ejemplo

boolean modoWifi = prefs.getBoolean("modoWifi", false);


int contador = prefs.getInt("contador", 0);
String comentario = prefs.getString("comentario", "");

Tambin es posible recuperar todos los datos de golpe utilizando el mtodo getAll.
Sintaxis

public abstract Map<String, ?> getAll ()

Ejemplo

Map<String, ?> valores = prefs.getAll();


Boolean modoWifi = (Boolean)valores.get("modoWifi");

El mtodo contains del objeto SharedPreferences permite verificar la existencia de una clave
dada que se le pasa como parmetro.

Sintaxis

public abstract boolean contains (String key)

Ejemplo

if (prefs.contains("modoWifi")) {
procesamiento();
}

3. Escritura
La escritura de datos en un archivo de preferencias se realiza a travs de un objeto
137
de tipo SharedPreferences.Editor. Este objeto lo devuelve el mtodo edit invocado sobre el
objeto de tipo SharedPreferences recuperado anteriormente.

Sintaxis

public abstract SharedPreferences.Editor edit ()

Ejemplo

SharedPreferences.Editor editor = prefs.edit();

El objeto editor permite especificar nuevos datos o modificar los datos existentes borrndolos con
los nuevos. Estos mtodos permiten escribir individualmente un par clave-valor. De forma similar a los
mtodos de lectura, existe un mtodo por cada tipo primitivo. Estos mtodos reciben como parmetro
el nombre de la clave y el valor del dato.

Sintaxis

public abstract SharedPreferences.Editor putBoolean (String key,


boolean value)
public abstract SharedPreferences.Editor putFloat (String key,
float value)
public abstract SharedPreferences.Editor putInt (String key,
int value)
public abstract SharedPreferences.Editor putLong (String key,
long value)
public abstract SharedPreferences.Editor putString (String key,
String value)

Ejemplo

editor.putBoolean("modoWifi", true);
editor.putInt("contador", 42);
editor.putString("comentario", "Esto es un comentario");

La escritura de los datos no ser efectiva en el archivo hasta que se ejecute el


mtodo commit delobjeto editor.

Sintaxis

public abstract boolean commit ()

Ejemplo

editor.commit();

Preste atencin a no olvidarse de llamar al mtodo commit. En efecto, si no realiza esta


llamada, el objeto editor no sirve de nada; no se registrarn las modificaciones que
contiene.

4. Borrado
El borrado de los datos contenidos en un archivo de preferencias se hace utilizando el
objeto editor de tipo SharedPreferences.Editor igual que para escribir los datos.

El mtodo remove del objeto editor permite suprimir un par clave-valor. Se pasa el nombre de la
clave como parmetro.
138
Sintaxis

public abstract SharedPreferences.Editor remove (String key)

Ejemplo

editor.remove("modoWifi");

El mtodo clear permite borrar todos los datos, es decir, todos los pares clave-valor.

Sintaxis

public abstract SharedPreferences.Editor clear ()

Ejemplo

editor.clear();

Como ocurre con la escritura, es necesario invocar al mtodo commit para registrar los cambios.

Tambin es posible encadenar las modificaciones, puesto que los mtodos del
objeto editordevuelven este mismo objeto.

Ejemplo

editor.clear().putBoolean("modoWifi", modoWifi).commit();

Cuando se invoca al mtodo commit, el mtodo clear se ejecuta en primer lugar, sea cual
sea la posicin de su llamada.

Es posible, por ejemplo, reescribir la lnea anterior sin modificar el resultado.

Ejemplo

editor.putBoolean("modoWifi", modoWifi).clear().commit();

139
Archivos
Como acabamos de ver en la seccin anterior, los archivos de preferencias son la solucin ideal para
salvaguardar valores de tipos primitivos de manera simple. Pero si lo que se quiere es almacenar datos
ms complejos o datos brutos sin un formato adaptado al formato XML como, por ejemplo, la copia de
una imagen con formato PNG, esta solucin no es adecuada.

Necesitamos poder crear, escribir y leer archivos directamente.

Android permite guardar archivos en el almacenamiento interno del dispositivo o en un almacenamiento


externo como, por ejemplo, una tarjeta SD. Proporciona tambin las API para guardar archivos
temporales o archivos de cach en ubicaciones definidas.

Vamos, por tanto, a ver en primer lugar la gestin de archivos en el almacenamiento interno, y en
segundo lugar sobre un almacenamiento externo. Por ltimo, veremos la gestin de los archivos
temporales.

1. Almacenamiento interno
Por defecto, los archivos se almacenan en el almacenamiento interno del dispositivo. El acceso a
estos archivos est restringido a la aplicacin. Ni el usuario, ni las dems aplicaciones, pueden
acceder a l.

Vamos a ver cmo crear un archivo en el almacenamiento interno, cmo leerlo y, por ltimo, cmo
borrarlo.

a. Escritura

La creacin de un archivo se realiza invocando al mtodo openFileOutput de la clase Context.


Este mtodo recibe dos parmetros: el nombre del archivo sin arborescencia y el modo de acceso
que se quiere asignar a este archivo. El mtodo devuelve un flujo de tipo FileOutputStream.

Sintaxis

public abstract FileOutputStream openFileOutput (String name,


int mode)

Ejemplo

FileOutputStream flujo = openFileOutput("miArchivo.png",


Context.MODE_PRIVATE);

El flujo devuelto permite escribir los datos brutos en el archivo utilizando los distintos
mtodos write.

Sintaxis

public void write (byte[] buffer)


public void write (int oneByte)
public void write (byte[] buffer, int offset, int count)

Ejemplo

flujo.write(contenido.getBytes());

Slo queda cerrar el flujo para escribir definitivamente el archivo sobre el soporte invocando al
mtodo close.

Sintaxis
140
public void close ()

Ejemplo

flujo.close();

b. Lectura

Para poder leer los datos contenidos en un archivo, hay que abrirlo en modo lectura. Para ello,
podemos utilizar el mtodo openFileInput de la clase Context. Este mtodo recibe como
parmetro el nombre del archivo sin arborescencia y devuelve un flujo de tipo FileInputStream.

Sintaxis

public abstract FileInputStream openFileInput (String name)

Ejemplo

intnb = FileInputStream flujo = openFileInput("miArchivo.png");

El flujo devuelto permite leer los datos del archivo utilizando los distintos mtodos read. Estos
mtodos devuelven el nmero de bytes ledos o -1 si se ha alcanzado el final del archivo.

Sintaxis

public int read ()


public int read (byte[] buffer)
public int read (byte[] buffer, int offset, int count)

Ejemplo

flujo.read();

Slo queda el flujo invocando al mtodo close.


Sintaxis

public void close()

Ejemplo

flujo.close();

c. Borrar un archivo

El mtodo deleteFile de la clase Context permite borrar un archivo. Hay que pasarle el
nombre del archivo como parmetro. Devuelve true si el archivo se ha borrado correctamente,
o false en caso contrario.

Sintaxis

public abstract boolean deleteFile (String name)

Ejemplo

boolean exito = deleteFile("nombreArchivo.png");

2. Almacenamiento externo
141
Adems del almacenamiento interno, los dispositivos Android proporcionan un almacenamiento
externo. Los archivos almacenados en este soporte son pblicos. El usuario y todas las dems
aplicaciones pueden, por tanto, leerlos, modificarlos y suprimirlos en cualquier momento.

Al contrario de lo que su propio nombre pudiera indicar, el almacenamiento externo puede ser interno
al dispositivo. Tambin puede ser extrable como, por ejemplo, una tarjeta SD. En este caso, el
usuario puede retirarlo en cualquier momento. La aplicacin debe, por tanto, tenerlo en cuenta
durante su etapa de diseo, y prestar atencin en particular a cmo se quiere gestionar la ausencia
del soporte con cada intento de escritura o de lectura.

Vamos a ver en primer lugar cmo verificar la presencia y la disponibilidad del almacenamiento
externo. Veremos, a continuacin, dnde se almacenan los archivos. Por ltimo, veremos la existencia
de una arborescencia comn a todas las aplicaciones que permite compartir archivos los que
contiene.

a. Disponibilidad del soporte

Para asegurar la disponibilidad del soporte de almacenamiento externo, hay que invocar
al mtodo getExternalStorageState de la clase Environment.

Sintaxis

public static String getExternalStorageState ()

Ejemplo

String estadoSoporteExterno = Environment.getExternalStorageState();

Este mtodo devuelve una cadena de caracteres que indica la disponibilidad del soporte de
almacenamiento, que habr que comparar con los estados predefinidos.

Ejemplo

if (Environment.MEDIA_MOUNTED.equals(estadoSoporteExterno)) {
procesamiento();
}

La siguiente tabla muestra las constantes declaradas en la clase Environment que representan
los distintos estados de disponibilidad.

Estado Descripcin

MEDIA_BAD_REMOVAL El soporte se ha retirado antes de haberse


desmontado por completo.

MEDIA_CHECKING El soporte est presente, en estado de


verificarse.

MEDIA_MOUNTED El soporte est presente, montado con


permisos de lectura/escritura.

MEDIA_MOUNTED_READ_ONLY El soporte est presente, montado con


permisos de slo lectura.

MEDIA_NOFS El soporte est presente, pero el formato del


sistema de archivos no est soportado.

MEDIA_REMOVED El soporte no est presente.

MEDIA_SHARED El soporte est presente, no montado y


compartido como perifrico de
almacenamiento USB.
142
MEDIA_UNMOUNTABLE El soporte est presente, pero no se ha
podido montar.

MEDIA_UNMOUNTED El soporte est presente, pero no est


montado.

b. Accesos y ubicaciones

Cada aplicacin tiene su carpeta en el soporte externo. La ruta es:

/Android/data/paquete_aplicaci n/files/

Los archivos de datos se reparten, a continuacin, en diversas subcarpetas segn su tipo. He aqu
la lista de subcarpetas:

Carpeta Constante Descripcin

Music/ DIRECTORY_MUSIC Contiene archivos de


msica.

Podcasts/ DIRECTORY_PODCASTS Contiene podcasts.

Ringtones/ DIRECTORY_RINGTONES Contiene tonos de


llamada.

Alarms/ DIRECTORY_ALARMS Contiene sonidos de


alarma.

Notifications/ DIRECTORY_NOTIFICATIONS Contiene sonidos de


notificaciones.

Pictures/ DIRECTORY_PICTURES Contiene fotografas.

Movies/ DIRECTORY_MOVIES Contiene vdeos.

Download/ DIRECTORY_DOWNLOADS Contiene otros tipos


de archivo.

El mtodo getExternalFilesDir permite obtener un objeto de tipo File que representa la


subcarpeta correspondiente al tipo de dato a salvaguardar.

Este mtodo, y de forma global todas las operaciones de escritura sobre el almacenamiento
externo, requieren permisos de escritura sobre este almacenamiento. Para obtenerlo, es necesario
incluir la siguiente fila en el archivo manifiesto (vase el captulo Concurrencia, seguridad y red -
Seguridad y permisos) :

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

Sintaxis

public!abstract!File!getExternalFilesDir(String!type)

El parmetro indica el tipo de dato que se quiere salvaguardar. Por ejemplo, para un archivo de
msica, se indicar:

Environment.DIRECTORY_MUSIC

Para obtener la carpeta raz, hay que pasar null como parmetro.

La carpeta raz, as como todas las subcarpetas y sus datos, se suprimirn tras desinstalar la
aplicacin.
143
c. Archivos comunes

Android pone a disposicin una arborescencia comn a todas las aplicaciones sobre el
almacenamiento externo. Esta arborescencia permite compartir archivos entre todas las
aplicaciones. Los archivos creados en esta arborescencia no se suprimirn tras desinstalar la
aplicacin que los haya creado.

La arborescencia de las subcarpetas es similar a aquella privada de cada aplicacin. La carpeta raz
es la carpeta raz del soporte de almacenamiento externo.

El mtodo Environment.getExternalStoragePublicDirectory permite acceder a estas


subcarpetas.

Sintaxis

public static File getExternalStoragePublicDirectory(String type)

El parmetro indica el tipo de dato que se quiere salvaguardar. Por ejemplo, para un archivo de
msica, se indicar:

Environment.DIRECTORY_MUSIC

3. Archivos temporales
Una aplicacin puede necesitar archivos temporales o archivos de cach. Cada aplicacin tiene
reservada una ubicacin especfica para almacenar estos archivos tanto en el almacenamiento interno
como en el almacenamiento externo en el caso de que exista. El uso de uno u otro espacio de
almacenamiento depender del tamao de estos archivos; la capacidad de almacenamiento externo
suele ser ms conveniente que la del almacenamiento interno.

Vamos a ver cmo recuperar estas carpetas tanto en el almacenamiento interno como en el
almacenamiento externo.

a. Almacenamiento interno

La llamada al mtodo getCacheDir de la clase Context devuelve la carpeta donde la aplicacin


debe almacenar sus archivos temporales sobre el almacenamiento interno.

Sintaxis

public abstract File getCacheDir()

El sistema puede suprimir estos archivos en cualquier momento, en particular cuando no existe ms
espacio en el almacenamiento. No obstante esto no es obligatorio. Por ello, la aplicacin debe velar
por que estos archivos no ocupen demasiado espacio, ms de un megabyte en total. Y debera
borrarlos una vez ya no fueran necesarios.

Si la aplicacin requiere ms espacio para sus archivos temporales, podr utilizar el almacenamiento
externo.

Todo el contenido de la carpeta de cach de la aplicacin se borrar tras la desinstalacin de la


aplicacin.

b. Almacenamiento externo

Adems de la ubicacin de cach especfica a la aplicacin sobre el almacenamiento interno, el


sistema proporciona tambin una ubicacin de cach especfica a cada aplicacin en el
almacenamiento externo.

Esta ubicacin permite a una aplicacin crear archivos temporales de mayor tamao.
144
La llamada al mtodo getExternalCacheDir de la clase Context devuelve esta carpeta.

De forma similar al mtodo getExternalFilesDir, este mtodo requiere permisos de


escritura sobre el almacenamiento
externo android.permission.WRITE_EXTERNAL_STORAGE.

Sintaxis

public abstract File getExternalCacheDir()

La aplicacin debe suprimir sus archivos de cach cuando ya no los necesite para liberar espacio.

Todo el contenido de la carpeta de cach de la aplicacin se borrar tras la desinstalacin de la


aplicacin.

145
Bases de datos SQLite
Una aplicacin puede necesitar una base de datos para almacenar y realizar consultas sobre sus
datos. Android permite crear bases de datos con formato SQLite.

Una aplicacin puede crear varias bases de datos. Estas bases de datos son privadas a la aplicacin;
solamente ella tiene acceso.

Android no proporciona un framework de alto nivel de mapping objeto-relacional. Es preciso


utilizar directamente consultas SQL para crear, gestionar y ejecutar consultas sobre las bases de
datos.

En esta seccin, veremos cmo crear una base de datos e insertar una tabla. A continuacin veremos
cmo ejecutar consultas. Por ltimo, veremos cmo modificar una base de datos existente.

1. Creacin de una base de datos


Android proporciona la clase abstracta SQLiteOpenHelper que permite gestionar la creacin y la
actualizacin de las bases de datos.

Esta clase es abstracta, de modo que hay que crear una clase derivada que herede de ella. Esta
clase derivada debe invocar al constructor padre y pasarle como parmetros el nombre y la versin
de la base de datos. El nmero de versin se utiliza durante la actualizacin de la base de datos a
una nueva versin como veremos ms adelante.

Heredando de la clase padre SQLiteOpenHelper, la clase derivada debe sobrecargar, entre otros,
el mtodo onCreate. Este mtodo permite especificar las consultas de creacin de las tablas de la
base de datos.

Sintaxis

public abstract void onCreate (SQLiteDatabase db)

Ejemplo

public class BDDAssistant extends SQLiteOpenHelper {


private static final int VERSION_BDD = 1;
private static final String NOMBRE_BDD = "miBDD";

public BDDAssistant(Context context) {


super(context, NOMBRE_BDD, null, VERSION_BDD);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE miTabla ( _id INTEGER PRIMARY KEY
AUTOINCREMENT, nombre TEXT );");
}
}

La clase SQLiteOpenHelper proporciona el mtodo getWritableDatabase para crear y abrir


la base de datos. Esta clase devuelve un objeto de tipo SQLiteDatabase accesible en modo de
escritura que permite modificar la base de datos.

Sintaxis

public synchronized SQLiteDatabase getWritableDatabase ()

Una vez terminados la creacin y el uso de la base de datos, es preciso cerrarla invocando a
146
losmtodos close en el objeto de tipo SQLiteDatabase y, a continuacin, en el objeto de
tipo SQLiteOpenHelper.

Sintaxis

public void close ()

Ejemplo

BDDAssistant bddAss = new BDDAssistant(this);


SQLiteDatabase bdd = bddAss.getWritableDatabase();
procesamiento(bdd);
bdd.close();
bddAss.close();

La llamada a getWritableDatabase puede devolver un objeto en modo slo lectura si


existe un problema como por ejemplo un disco lleno. Una vez corregido el problema, una nueva
llamada al mtodo getWritableDatabase cerrar el objeto en modo slo lectura y devolver
un objeto accesible en lectura/escritura.

Es tras la primera llamada al mtodo getWritableDatabase cuando la base de datos se


crea realmente. Este mtodo ejecutar sucesivamente
los mtodo onCreate, onUpgrade yonOpen de la instancia miBDD. Una vez abierta la base de
datos, se pone en cach de modo que las sucesivas llamadas a este mtodo devuelven
directamente la base de datos sin invocar de nuevo a los mtodos anteriores.

Para abrir una base de datos en modo slo lectura, se reemplazar la llamada al
mtodo getWritableDatabase por el mtodo getReadableDatabase.
Sintaxis

public synchronized SQLiteDatabase getReadableDatabase ()

Ejemplo

SQLiteDatabase bdd = bddAss.getReadableDatabase();

2. Procedimientos y consultas SQL


El objeto de tipo SQLiteDatabase recuperado en la seccin anterior permite ejecutar sentencias y
consultas SQL: CREATE TABLE, DELETE, INSERT La ejecucin de sentencias SQL la realizan
los mtodos execSQL.

Sintaxis

public void execSQL (String sql)


public void execSQL (String sql, Object[] bindArgs)

Ejemplo

bdd.execSQL("DROP TABLE IF EXISTS miTabla");

Slo est permitido una sentencia por llamada a estos mtodos. El uso de ; para separar las
sentencias est, por tanto, prohibido.

Las consultas SQL pueden ejecutarse con los distintos mtodos query que reciben distintos
parmetros de entrada como el nombre de la tabla, los nombres de los campos
147
Cada uno de estos mtodos devuelve un objeto de tipo Cursor que permite navegar por los
resultados de la consulta y extraer los datos.

Sintaxis

public Cursor query (String table, String[] columns,


String selection, String[] selectionArgs,String groupBy,
String having, String orderBy)
public Cursor query (String table, String[] columns,
String selection, String[] selectionArgs,String groupBy,
String having, String orderBy, String limit)
public Cursor query (boolean distinct, String table,
String[] columns, String selection,String[] selectionArgs,
String groupBy, String having, String orderBy, String limit)

Ejemplo

Cursor cursor = bdd.query("miTabla", new String[] { "_id", "nombre" },


null, null, null, null, "_id desc", 10);

3. Actualizaciones
Tras la creacin de una nueva versin de la aplicacin, es posible que la base de datos necesite
evolucionar, creando por ejemplo nuevas tablas, o modificar las tablas existentes, por ejemplo,
agregando o suprimiendo campos... Es preciso, en estos casos, realizar una actualizacin de la base
de datos.

Para ello, basta con sobrecargar el mtodo onUpgrade para indicar las instrucciones de
actualizacin. Tambin hay que incrementar el nmero de versin de la base de datos para poder
diferenciarla de la anterior.

Sintaxis

public abstract void onUpgrade (SQLiteDatabase db, int oldVersion,


int newVersion)

Ejemplo

public class BDDAssistant extends SQLiteOpenHelper {


private static final int VERSION_BDD = 2;
...
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion) {
db.execSQL("DROP TABLE IF EXISTS miTabla");
onCreate(db);
}
}

La llamada al mtodo onUpgrade se realiza tras la ejecucin de los


mtodos getReadableDatase y getWritableDatabase. El tiempo de actualizacin
puede ser largo. En este caso, es preciso lanzar esta operacin desde un thread distinto al thread
principal (vase el captulo Concurrencia, seguridad y red - Programacin concurrente).

148
Proveedor de contenidos
Los proveedores de contenidos permiten compartir pblicamente datos entre todas las aplicaciones. Es
el caso, por ejemplo, de los datos relacionados con los contactos personales que pueden compartirse
entre todas las aplicaciones. Cada aplicacin puede, si tiene los permisos necesarios, leer, agregar o
modificar los contactos personales.

Existen, por defecto, varios proveedores de contenidos para los datos de audio, de vdeo, las
imgenes, los contactos personales Podemos utilizarlos tal cual para almacenar nuevos registros.
Esto permite no tener que crear nuevos.

Vamos a describir la interfaz comn a los proveedores de contenidos, y despus veremos cmo realizar
consultas y modificaciones sobre estos proveedores de contenidos. Por ltimo, veremos cmo borrar
registros en los proveedores de contenidos.

1. Interfaz y URI
Todos los proveedores de contenidos exponen la misma interfaz. De forma interna, no obstante, cada
uno es libre de salvaguardar sus datos utilizando la o las soluciones de almacenamiento que estime
oportunas.

Sea cual sea el modo de almacenamiento interno, los proveedores de contenidos devuelven sus
datos bajo la forma de tablas de base de datos. Cada fila es un registro y cada columna un valor
correspondiente al campo asociado.

Cada registro posee un campo numrico _ID que identifica de forma nica el registro en la tabla.

Cada proveedor de contenidos provee una URI nica que corresponde con una tabla de sus datos.
Habr, por tanto, tantas URI como tablas de datos.

Sintaxis de la URI

content://es.midominio.nombreProveedor
content://es.midominio.nombreProveedor/id
content://es.midominio.nombreProveedor/ruta
content://es.midominio.nombreProveedor/ruta/id

Fragmento Descripcin

content:// Indica que los datos estn controlados


por un proveedor de contenidos.

es.dominio.nombreProveedor Fragmento autorizado de la URI.

ruta Permite al proveedor de contenidos


determinar el tipo de dato. Est vaco si
gestiona un nico tipo de dato.

id El identificador nico del registro


solicitado, es decir, el valor del
campo _ID. Est vaco si la consulta
devuelve ms de un registro.

Android proporciona URI para los proveedores de contenidos incluidos en el sistema.

Ejemplo de URI para obtener los datos de los contactos

ContactsContract.Contacts.CONTENT_URI

El acceso a ciertos datos requiere algunos permisos. Aqu, se requiere


el permiso android.permission.READ_CONTACTS para poder acceder a los datos de los
contactos. A su vez, se requiere el permiso android.permission.WRITE_CONTACTS para
149
poder agregar, modificar o borrar datos de los contactos.

2. Consultas
La clase ContentResolver contiene los mtodos que permiten realizar consultas para recuperar
los datos almacenados en los proveedores de contenidos.
El mtodo getContentResolverpermite recuperar una instancia de tipo ContentResolver.

Sintaxis

public abstract ContentResolver getContentResolver ()

Ejemplo

ContentResolver resolver = getContentResolver();

El mtodo query de la clase ContentResolver permite ejecutar una consulta pasndole la URI
como parmetro. Los dems parmetros permiten precisar los nombres de los campos que se desea
extraer, una clusula SQL WHERE, los argumentos de la clusula WHERE y una clusula SQL ORDER
BY.
Sintaxis

public final Cursor query (Uri uri, String[] projection,


String selection, String[] selectionArgs, String sortOrder)

Ejemplo

Cursor cursor = resolver.query(


ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

Para una mayor comodidad, en las versiones de Android inferiores a la 3.0 (API 11), es posible utilizar
el mtodo managedQuery de la clase Activity que, a diferencia del mtodo anterior, gestiona el
ciclo de vida del cursor automticamente en funcin del estado de la actividad que la contiene. Por
ejemplo, cuando la actividad est en pausa, el cursor libera la memoria usada y se recarga
automticamente cuando se retoma la actividad.

Sintaxis

public final Cursor managedQuery (Uri uri, String[] projection,


String selection, String[] selectionArgs, String sortOrder)

Ejemplo

Cursor cursor = managedQuery(


ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

Desde la versin 3.0 (API 11), el mtodo managedQuery se ha deprecado en beneficio de la


nueva clase CursorLoader que permite ejecutar fcilmente consultas de forma asncrona.

Estas llamadas devuelven un cursor que apunta sobre todos los registros del resultado. Para
devolver un nico registro, es preciso agregar el identificador nico del registro solicitado a la URI.
Para ello, se utiliza el mtodo withAppendedId de la clase ContentUris que devuelve la URI as
formada.

Sintaxis
150
public static Uri withAppendedId (Uri contentUri, long id)

Ejemplo

Uri uri = ContentUris.withAppendedId(


ContactsContract.Contacts.CONTENT_URI, 42);
Cursor cursor = resolver.query(uri, null, null, null, null);

El cursor obtenido permite leer los valores de los registros. Para ello, la clase Cursor provee, entre
otros, el mtodo getColumnIndex. Este mtodo recibe como parmetro el nombre del campo
solicitado y devuelve el ndice correspondiente.

Sintaxis

public abstract int getColumnIndex (String columnName)

Conociendo el tipo de valor del campo, es posible recuperar el valor utilizando el mtodo
correspondiente de entre los mtodos getInt, getFloat... Por ejemplo, para recuperar un valor
de tipo String, se utilizar el mtodo getString.

Sintaxis

public abstract String getString (int columnIndex)

Ejemplo

int indiceCol =

cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
String nombre = cursor.getString(indiceCol);

3. Agregar un registro
Para agregar nuevos registros a un proveedor de contenidos, hay que crear un objeto
de tipo ContentValues que contendr los datos del registro bajo la forma de pares clave-valor.
Para agregar datos en este objeto se utiliza uno de sus mtodos put que reciben como primer
parmetro el nombre de la clave y como segundo parmetro el valor. Por ejemplo, el
mtodo putcorrespondiente a un valor de tipo String posee la sintaxis siguiente:

Sintaxis

public void put (String key, String value)

Ejemplo

ContentValues registro = new ContentValues();


registro.put(Phone.RAW_CONTACT_ID, 42);
registro.put(Phone.NUMBER, "000-000");
registro.put(Phone.TYPE, Phone.TYPE_MOBILE);

Para agregar el registro en los datos del proveedor de contenidos, basta con invocar a continuacin
al mtodo insert del objeto de tipo ContentResolver y pasarle como parmetro la URI y el
registro. Este mtodo devuelve la URI correspondiente al registro.

Sintaxis

public final Uri insert (Uri url, ContentValues values)

Ejemplo
151
Uri uri = resolver.insert(Phone.CONTENT_URI, registro);

4. Borrado de registros
El borrado de uno o varios registros se realiza invocando al mtodo delete de la
clase ContentResolver.

Sintaxis

public final int delete (Uri url, String where,


String[] selectionArgs)

Si el parmetro url contiene el identificador de un registro, entonces slo se borrar este registro.

Si, por el contrario, el parmetro url no contiene el identificador, entonces se utilizarn los
parmetros where y selectionArgs para especificar la clusula SQL WHERE y sus argumentos.

Ejemplo

Uri uri = ContentUris.withAppendedId(


ContactsContract.Contacts.CONTENT_URI, 42);
resolver.delete(uri, null, null);

152
Copia de seguridad en la nube
Desde la versin 2.2 (API 8), Android permite realizar la copia de seguridad de los datos persistentes
de la aplicacin en la nube, es decir, en lnea, sobre un servidor. Se trata de un servicio complementario
al de la copia de seguridad de los datos en local.

Cuando el usuario reinicializa el dispositivo Android, cuando cambia de dispositivo o utiliza un nuevo
dispositivo adicional, como por ejemplo una tableta como complemento a un smartphone, puede
solicitar (re)instalar una aplicacin. El hecho de tener que reconfigurar la aplicacin y volver a insertar
ciertos datos de forma manual son tareas que pueden resultar poco atractivas al usuario.

Es, en este momento, cuando entra en juego la copia de seguridad en la nube. sta permite evitar
tareas de configuracin largas y tediosas. Es posible descargar e insertar los datos, salvaguardados
previamente en lnea, durante una nueva instalacin. El usuario encontrar automticamente la
aplicacin y los datos que la acompaan sin tener que hacer nada por su parte.

Los datos estn asociados a la cuenta de Google del usuario principal configurado en el
dispositivo. El usuario tendr que configurar a continuacin la misma cuenta principal sobre sus
dems dispositivos para aprovechar plenamente esta funcionalidad.

Cabe observar que, si bien esta funcionalidad est presente en la mayora de dispositivos
Android, algunos no la poseen. Tambin puede darse el caso de que el usuario desactive esta
funcionalidad en los parmetros generales del sistema. En tales casos, la aplicacin funcionar de
manera normal; simplemente los datos persistentes no se salvaguardarn ni se recuperarn. Ser
tarea del usuario reinsertarlos manualmente.

La aplicacin no enva, en s misma, los datos persistentes al servidor. Se comunica con el Gestor de
Copia de Seguridad sobre el sistema Android. ste se encargar de preparar los datos a enviar,
comunicarse con el servidor en lnea y transmitirle los datos. Tambin se encarga de recibir los datos
desde el servidor en el caso de una nueva instalacin de la aplicacin.

La aplicacin debe indicar al Gestor de Copia de Seguridad que quiere utilizar el servicio de copia de
seguridad en lnea, dado que el sistema permite utilizar distintos servicios de copia de seguridad en
lnea. En este caso utilizaremos el servicio de copia de seguridad propuesto por Google: Android
Backup Service.

Corresponde a los responsables de la aplicacin, sea un particular, una empresa u otros verificar
si deben declarar la copia de seguridad de los datos sobre servidores, segn el tipo de dato
afectado y, en especial, si se trata de datos personales, debido a la LOPD (Agencia Espaola de
Proteccin de Datos - Ley Orgnica de Proteccin de Datos - https://www.agpd.es/). Si usa el
servicio Android Backup Service de Google, el responsable deber, sin duda, completar su
declaracin indicando una posible transferencia de datos fuera de la Unin Europea.

1. Suscribirse a Android Backup Service


La inscripcin de la aplicacin en el servicio de Android Backup Service es una etapa obligatoria para
que pueda salvaguardar y restaurar los datos. La inscripcin es gratuita.

En la etapa de inscripcin, se genera una clave nica. Esta clave permite identificar la aplicacin
desde el servicio en las fases de copia de seguridad y de restauracin.

El servicio requiere que cada aplicacin posea su propia clave. Ser preciso, por tanto, inscribir
cada aplicacin, cada paquete, para poder generar tantas claves como aplicaciones quieran
utilizar el servicio.

153
Dirjase a la direccin http://code.google.com/android/backup/signup.html.

Lea las condiciones de uso del servicio Android Backup Service que describen, en particular, las
condiciones y las restricciones de uso del servicio. Marque la casilla I have read and agree with
the Android Backup Service Terms of Service.

Introduzca el nombre del paquete de la aplicacin que quiera utilizar el servicio en el


campoApplication package name.

Haga clic en el botn Register.

Inscripcin en Android Backup Service

Aparece la siguiente pantalla, que incluye la clave nica generada y asociada al nombre del paquete
que se ha indicado.

Guarde la pgina web o, al menos, la clave anotando a qu paquete est asociada. Si fuera
necesario, es posible generar la misma clave varias veces.

154
Clave de Android Backup Service

2. Configuracin de la clave
Una vez generada la clave, es preciso agregarla en el manifiesto insertando una etiqueta meta-
data dentro de la etiqueta application. Esta etiqueta meta-data debe incluir el
atributo android:name identificando al dato, en
este caso com.google.android.backup.api_key, y el
atributo android:value especificando el valor de la clave generada.

Sintaxis

<meta-data android:name="com.google.android.backup.api_key"
android:value="cadena de caracteres" />

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<manifest ...>
<application ...>
...
<meta-data android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAFAIoa...Hq29AXUAFOtQVgwurLtJfF" />
</application>
</manifest>

3. Agente de copia de seguridad


La aplicacin debe proveer un agente de copia de seguridad encargado de transmitir la informacin a
salvaguardar y a restaurar al Gestor de Copia de Seguridad.

Para ello, hay que crear una clase que herede de la clase BackupAgent. La clase creada se
comunicar con el Gestor de Copia de Seguridad y tendr, en especial, que implementar
los mtodos onBackup y onRestore para realizar respectivamente las operaciones de salvaguarda
y de restauracin.

Android provee la clase BackupAgentHelper que hereda de la clase BackupAgent. Esta clase
155
utiliza asistentes capaces de salvaguardar de manera sencilla ciertos tipos de datos y, en particular,
archivos binarios almacenados en local. Por ello, no es necesario implementar los
mtodos onBackup y onRestore. Por el contrario, heredar de la clase BackupAgentHelper entraa
ciertas restricciones como, por ejemplo, la imposibilidad de salvaguardar datos almacenados en una
base de datos SQLite. Para ello, ser preciso heredar directamente de la clase BackupAgent.

Aqu trataremos solamente la herencia de la clase BackupAgentHelper, antes que de la clase


bsica BackupAgent, con el objetivo de aprovechar los servicios que ofrece aqulla.

a. Configuracin

Una vez se ha escogido el nombre de la clase a crear, es preciso indicarla en el manifiesto utilizando
el atributo android:backupAgent de la etiqueta application. Esto permite al Gestor de
Copia de Seguridad conocer y poderse comunicar con el agente correspondiente.

Sintaxis

android:backupAgent="cadena de caracteres"

De forma similar a los dems componentes, este nombre puede comenzar por un punto, de modo
que se utilizar el nombre del paquete indicado en el atributo package de la
etiqueta manifestpara componer el nombre completo.

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<manifest ...>
<application android:backupAgent=".MiAgenteDeCopiaDeSeguridad" >
...
</application>
</manifest>

b. BackupAgentHelper

La clase BackupAgentHelper utiliza los asistentes de copia de seguridad, cada uno


especializado en la salvaguarda de un tipo de datos. Android proporciona dos asistentes
representados por las clases SharedPreferencesBackupHelper y FileBackupHelper.

La clase SharedPreferencesBackupHelper est especializada en la copia de seguridad y la


restauracin de archivos de preferencias. Basta con instanciar esta clase para obtener el asistente
correspondiente. El constructor recibe como parmetros el contexto de la aplicacin as como un
nmero indefinido de nombres de archivos de preferencias que se quiere salvaguardar.

Sintaxis

public SharedPreferencesBackupHelper (Context context,


String... prefGroups)

Ejemplo

SharedPreferencesBackupHelper asistenteArchivosPrefs =
new SharedPreferencesBackupHelper(this, "nombreArchivoPrefs1",
"nombreArchivoPrefs2");

La clase FileBackupHelper est especializada en la copia de seguridad y la restauracin de


archivos binarios de pequeo tamao. Incluso en este caso, basta con instanciar esta clase para
obtener el asistente correspondiente. El constructor recibe como parmetros el contexto de la
aplicacin as como un nmero indefinido de archivos binarios de almacenamiento interno a
salvaguardar.

Sintaxis 156
public FileBackupHelper (Context context, String... files)

Ejemplo

FileBackupHelper asistenteArchivosBin =
new FileBackupHelper(this, "nombreArchivoBin1", "nombreArchivoBin2");

Como se ha indicado, la clase MiAgenteDeCopiaDeSeguridad hereda de la


clase BackupAgentHelper. sta debe indicar los asistentes que utiliza, es decir, las instancias de
los objetos SharedPreferencesBackupHelper y FileBackupHelper. Para ello, debe
utilizar su mtodo addHelper. Este mtodo recibe como parmetros una clave en forma de
cadena de caracteres as como el objeto asistente asociado.

Sintaxis

public void addHelper (String keyPrefix, BackupHelper helper)

Ejemplo

addHelper("archivosPrefs", asistenteArchivosPrefs);

Esta declaracin de asistentes debe realizarse en el mtodo onCreate de la


clase MiAgenteDeCopiaDeSeguridad. Este mtodo se invoca antes de realizar la copia de
seguridad o la restauracin. Permite, por tanto, inicializar el proceso.

Sintaxis

public void onCreate ()

Ejemplo

public class MiAgenteDeCopiaDeSeguridad extends BackupAgentHelper {

@Override
public void onCreate() {
SharedPreferencesBackupHelper asistenteArchivosPrefs =
new SharedPreferencesBackupHelper(this,
"nombreArchivoPrefs1", "nombreArchivoPrefs2");
addHelper("archivosPrefs", asistenteArchivosPrefs);

FileBackupHelper asistenteArchivosBin =
new FileBackupHelper(this, "nombreArchivoBin1",
"nombreArchivoBin2");
addHelper("archivosBin", asistenteArchivosBin);
}

Dado que la copia de seguridad de los datos puede tener lugar en cualquier momento, hay que
asegurar que no ocurre durante una actualizacin de los datos en local por la propia aplicacin. En
caso contrario, los datos almacenados en lnea podran verse corrompidos.

Una de las soluciones propuestas para responder a este problema consiste en volver atmicas las
fases de escritura y de lectura de datos en los archivos. En concreto, esto consiste en sincronizar el
acceso a los datos mediante el uso de un cerrojo, por ejemplo.

El acceso a los archivos de preferencias mediante una interfaz de tipo Shared Preferenceses,
en lo sucesivo, thread-safe. Es decir, esta interfaz asegura la atomicidad de las operaciones de
escritura y de lectura. No es necesario hacer nada para estos archivos.

Por el contrario, este no es el caso de los archivos binarios. Es preciso implantar tal mecanismo en el
157
uso de estos archivos por los componentes de la aplicacin y por el agente de copia de seguridad.
La implementacin de este mecanismo debe realizarse en los mtodos onBackup yonRestoreque
es preciso implementar.

Sintaxis

public abstract void onBackup (ParcelFileDescriptor oldState,


BackupDataOutput data, ParcelFileDescriptor newState)
public abstract void onRestore (BackupDataInput data,
int appVersionCode, ParcelFileDescriptor newState)

Ejemplo

public static final Object sCerrojo = null;

@Override
public void onBackup(ParcelFileDescriptor oldState,
BackupDataOutput data, ParcelFileDescriptor newState)
throws IOException {
synchronized (sCerrojo) {
super.onBackup(oldState, data, newState);
}
}

@Override
public void onRestore(BackupDataInput data, int appVersionCode,
ParcelFileDescriptor newState) throws IOException {
synchronized (sCerrojo) {
super.onRestore(data, appVersionCode, newState);
}
}

4. Gestor de Copia de Seguridad


Corresponde a la aplicacin advertir al Gestor de Copia de Seguridad que sus datos se han
modificado y deben, por tanto, sincronizarse en lnea. El Gestor de Copia de Seguridad decide a
continuacin en qu momento se realizar realmente esta sincronizacin en lnea. Mientras tanto,
incluso si la aplicacin ha vuelto a realizar su peticin varias veces, el Gestor mutualizar estas
peticiones para realizar la copia de seguridad en lnea una nica vez. Utilizar, por tanto, el Agente
de Copia de Seguridad especificado por la aplicacin.

a. Solicitar una copia de seguridad

Para realizar una peticin de copia de seguridad, la aplicacin debe, en primer lugar, crear una
instancia del Gestor de Copia de Seguridad. Para ello, debe utilizar simplemente el constructor de la
clase BackupManager.

Sintaxis

public BackupManager (Context context)

Ejemplo

BackupManager backupManager = new BackupManager(this);

La aplicacin debe, a continuacin, invocar al mtodo dataChanged del Gestor de Copia de


Seguridad para informar que sus datos se han visto modificados y que puede realizar la copia de
seguridad en lnea.

Sintaxis

158
public void dataChanged ()

Ejemplo

backupManager.dataChanged();

Los datos salvaguardados en lnea los restaura automticamente el sistema en el dispositivo


Android tras la instalacin de la aplicacin y, por tanto, antes de su primera ejecucin. Para ello es
necesario que el sistema disponga de esta funcionalidad, que el usuario no la haya desactivado y
que el acceso al servicio en lnea est disponible.

La aplicacin puede, no obstante, forzar una restauracin de datos en cualquier momento


invocando al mtodo requestRestore del Gestor de Copia de Seguridad.

b. Probar el servicio

Para poder probar de forma sencilla la implementacin del sistema de Copia de Seguridad en lnea
por la aplicacin, es posible forzar manualmente las distintas etapas de copia de seguridad y de
restauracin.

Esto se realiza desde una consola. La herramienta adb permite abrir un shell en el dispositivo
Android o el emulador. Desde este shell, hay que utilizar el comando bmgr pasndole las opciones
deseadas. Las opciones ms utilizadas son backup, run y restore que se corresponden
respectivamente con la solicitud de copia de seguridad, la realizacin efectiva de la copia de
seguridad en lnea y la restauracin. Basta con no especificar ninguna opcin para obtener la lista
completa de opciones disponibles.

Sintaxis

adb shell bmgr options

Ejemplo

$ adb shell bmgr enable true


$ adb shell bmgr backup es.midominio.android.miapli
$ adb shell bmgr run
$ adb uninstall es.midominio.android.miapli

En este ejemplo, se activa el servicio de copia de seguridad en el emulador o el dispositivo. A


continuacin, se solicita y se fuerza la ejecucin de la copia de seguridad. Por ltimo, se suprime la
aplicacin.

Slo queda reinstalar la aplicacin para verificar que los datos se restauran correctamente.

159
10. Concurrencia,
seguridad y red

160
Introduccin
Android est basado en el sistema Linux 2.6. Por tanto, retoma las principales caractersticas y, en
concreto, su funcionamiento.

En este captulo, vamos a descubrir la nocin de proceso aplicado a las aplicaciones Android. A
continuacin, detallaremos cmo crear y ejecutar threads secundarios dedicados a procesamientos
costosos. Veremos cmo pueden comunicarse con el thread principal para actualizar la interfaz de
usuario. Por ltimo, estudiaremos la implementacin de la seguridad en Android y, en especial, el uso
de los permisos de las aplicaciones y los componentes.

161
Procesos
Por defecto, toda aplicacin Android se ejecuta en su propio proceso Linux. Para ser ms precisos,
cuando el sistema debe ejecutar por primera vez un componente de una aplicacin, crea un nuevo
proceso Linux. Ejecuta, en este proceso, una mquina virtual Dalvik, y carga la aplicacin y ejecuta el
componente deseado en un slo y nico thread, el thread principal.

Como se ha indicado en varias ocasiones a lo largo de este libro, el sistema puede decidir, en cualquier
momento, matar el proceso entero para liberar recursos del sistema para las dems aplicaciones. El fin
del proceso provoca el fin de la aplicacin, es decir, de todos sus componentes, sin distincin. Se
ejecutar un nuevo proceso cuando se tenga que volver a usar alguno de los componentes de la
aplicacin.

El nombre del usuario Linux creado para ejecutar este proceso es del estilo app_id donde id es un
nmero nico por aplicacin. Por defecto, el sistema crea un usuario por proceso y, por tanto, por
aplicacin.

1. android:process
El proceso toma el nombre del paquete de la aplicacin. Su nombre puede modificarse especificando
el atributo android:process de la etiqueta application del manifiesto. Se recomienda
respetar el formato utilizado para la nomenclatura de los paquetes.

Sintaxis

<application
android:process="[:]cadena de caracteres"
... >
...
</application>

Ejemplo

<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:process="es.midominio.android.miapli.miproceso">
</application>

Por defecto, todos los componentes de la misma aplicacin se ejecutarn en este mismo proceso,
bajo el mismo nombre, y en el mismo thread principal. No obstante, cada componente puede saltarse
esta regla fcilmente. Para ello, basta con que utilice el atributo android:process en su etiqueta
para indicar el nombre del nuevo proceso en el que se ejecutar el componente.

Si el nombre viene precedido por un signo de dos puntos, el proceso ser privado a la aplicacin. Es
decir, su nombre estar precedido por el nombre del paquete de la aplicacin seguido del nombre
especificado.

Ejemplo

<activity android:name=".MiActividadSecundaria"
android:process=":otroProceso" />

En este ejemplo, la actividad secundaria se ejecutar en su propio proceso


llamado es.midominio.android.miapli:otroProceso.

Dado que Android est basado en el sistema Linux, es posible acceder a un shell utilizando la
herramienta adb. sta permite ejecutar distintos comandos.

Sintaxis
162
adb shell [comando]

Ejemplo

$ adb shell
$ ps
USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 224 208 ffffffff 00000000 S /init
root 2 0 0 0 ffffffff 00000000 S kthreadd
root 3 2 0 0 ffffffff 00000000 S ksoftirqd/0
...
app_76 2009 58 129020 20156 ffffffff 00000000 S
es.midominio.android.miapli
app_76 2017 58 136976 20112 ffffffff 00000000 S
es.midominio.android.miapli:otroProceso

En este ejemplo, una vez conectado al shell, el comando ps permite listar los procesos actuales y, en
especial, aquellos correspondientes a una aplicacin o, ms especficamente, a un componente de
una aplicacin. Este es el caso del proceso 2009 correspondiente a la aplicacin, y a la actividad
principal, es.midominio.android.miapli con el proceso 2017 correspondiente a la actividad
secundaria.

2. Comparticin de proceso
Una de las ventajas de especificar el nombre del proceso que se quiere crear y utilizar es poder
compartirlo, no slo entre distintos componentes de una misma aplicacin, sino tambin, y sobretodo,
entre distintas aplicaciones. Es decir, varias aplicaciones que especifiquen el mismo nombre de
proceso se ejecutarn en el mismo proceso, permitindoles acceder a l fcilmente y compartir los
mismos recursos: memoria, archivos, preferencias

Para ello, estas aplicaciones deben no slo especificar el mismo nombre de proceso mediante el
atributo android:process sino que tambin deben compartir el mismo identificador de usuario
Linux y estar firmadas con el mismo certificado digital (vase el captulo Publicar una aplicacin - Firma
digital de la aplicacin).

El identificador de usuario Linux es un identificador nico atribuido por el sistema a cada aplicacin. Es
posible, no obstante, especificar uno de modo que varias aplicaciones usen el mismo. Para ello, hay
que utilizar el atributo android:sharedUserId. El nombre que se pasa como valor debe
contener, al menos, un punto.

Sintaxis

<manifest
android:sharedUserId="cadena de caracteres"
... >
...
</manifest>

Ejemplos

Se muestra a continuacin el archivo AndroidManifest.xml de la aplicacin MiApli.

<?xml version="1.0" encoding="utf-8"?>


<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="es.midominio.android.miapli"
android:sharedUserId="es.midominio.android.usuario1" >
<application android:icon="@drawable/icon"
android:label="@string/app_name"
android:process="es.midominio.android.proceso.compartido" >
163
</application>
</manifest>

Y he aqu el archivo AndroidManifest.xml de la aplicacin MiApli2.

<?xml version="1.0" encoding="utf-8"?>


<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="es.midominio.android.miapli2"
android:sharedUserId="es.midominio.android.usuario1" >
<application android:icon="@drawable/icon"
android:label="@string/app_name"
android:process="es.midominio.android.proceso.compartido" >
</application>
</manifest>

En este ejemplo, las dos aplicaciones comparten el mismo identificador de


usuario es.midominio.android.usuario1 y el mismo
proceso es.midominio.android.proceso.compartido. Estas aplicaciones se ejecutan
entonces en el mismo proceso del sistema y pueden compartir de forma abierta sus recursos, como si
fueran una nica aplicacin.

Una verificacin desde el shell nos confirma que ambas aplicaciones corren en el mismo proceso.

Ejemplo

$ ./adb shell ps
USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 224 208 ffffffff 00000000 S /init
root 2 0 0 0 ffffffff 00000000 S kthreadd
...
app_85 2470 58 142400 20608 ffffffff 00000000 S
es.midominio.android.proceso.compartido

164
Programacin concurrente
Por defecto, un proceso slo comprende un thread, el thread principal. Todos los componentes de la aplicacin se ejecutan en este
thread. Para mejorar la experiencia de usuario, Android considera que una aplicacin est bloqueada cuando no responde tras diez
segundos. El usuario puede destruirla.

Para evitar tal bloqueo de la aplicacin, cualquier procesamiento largo como, por ejemplo, una descarga web o un clculo intensivo
deben realizarse en un thread secundario dedicado, liberando al thread principal. Este ltimo puede entonces dedicarse al
funcionamiento global de la aplicacin y a su representacin grfica, tarea que se realiza de forma obligatoria en el thread principal.

Es posible crear tantos threads secundarios como se desee. Se recomienda encarecidamente crear threads antes que procesos, pues
estos ltimos consumen ms recursos.

Si bien no es obligatorio, en muchos casos puede ser oportuno crear servicios para ejecutar los
threads secundarios. En efecto, llegado el caso, el sistema matar de manera prioritaria aquellos
procesos que no muestren nada al usuario o los receptores de eventos sin actividad antes que los
servicios. La clase IntentService puede ser otra gran idea en este sentido. En efecto, permite
crear rpidamente servicios que integran un thread secundario, y gestionarlos fcilmente. Es, por
tanto, una solucin suplementaria a tener en cuenta adems de las que se detallan en este
captulo.

Es comn ejecutar procesamientos largos y querer visualizar sus resultados una vez terminados. O bien, el procesamiento largo debe
realizarse en un thread secundario y su visualizacin a travs la interfaz de usuario en el thread principal. Es preciso, por tanto, que
estos threads puedan comunicarse mutuamente.

Para ello, existen distintas tcnicas a nuestra disposicin.

1. AsyncTask
Como su propio nombre indica, la clase AsyncTask permite realizar una tarea de forma asncrona. Es, sin duda, la forma ms sencilla
de crear y ejecutar un thread secundario y, a continuacin, mostrar el resultado en el thread principal.

Esta clase permite abstraerse de la manipulacin de threads, y no tener que preocuparse ms que del procesamiento de fondo a
realizar y de la gestin de resultados. La creacin del thread secundario se realiza de forma interna y la visualizacin de resultados se
realiza en el thread principal.

El desarrollador no tiene que preocuparse de la creacin del thread secundario, de la gestin de estos threads ni de la comunicacin
entre ellos.

La clase AsyncTask proporciona mtodos que se invocarn automticamente en cada etapa de la tarea: la inicializacin, la ejecucin
del procesamiento, el progreso y la finalizacin. El desarrollador no tiene que invocar a estos mtodos directamente.

Es preciso, por tanto, crear una clase que herede de la clase AsyncTask e implementar los mtodos deseados. La
clase AsyncTask recibe tres tipos genricos:

Params: tipo de los parmetros pasados a la entrada de la tarea.

Progress: tipo de la unidad de progreso del procesamiento.

Result: tipo del resultado del procesamiento.

Sintaxis

class MiTarea extends AsyncTask<Params, Progress, Result> {


...
}

Ejemplo

La declaracin de la clase que


public class MiActividadPrincipal extends Activity { hereda de la
private class NumerosPrimos extends clase AsyncTask se realiza
AsyncTask<Integer, Integer, Integer> { generalmente como clase
... privada interna al componente
}
utilizado, como ocurre en
}
nuestro ejemplo.

La primera etapa de la realizacin de la tarea es su inicializacin implementando el mtodo onPreExecute. Este mtodo se invoca
desde el thread principal y puede, por tanto, modificar la interfaz de usuario.

Sintaxis

protected void onPreExecute ()

Ejemplo

A continuacin se invoca
@Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(MiActividadPrincipal.this, 165
"Clculo de los nmeros primos iniciado!",
Toast.LENGTH_SHORT)
.show();
}

al mtodo doInBackground que se encarga de realizar el procesamiento de la tarea. Este mtodo se invoca desde el thread
secundario. Esto permite ejecutar el procesamiento largo y no bloquear el thread principal. Este mtodo devuelve el resultado del
procesamiento.

Sintaxis

protected abstract Result doInBackground (Params... params)

Ejemplo

El procesamiento contenido en
@Override el
protected Integer doInBackground(Integer... arg0) {
int n = 0;
int nivel=0;
int step = (arg0[1] - arg0[0]) / 10;
for (int i = arg0[0]; i <= arg0[1]; i++) {
if (isPrime(i)) {
n++;
}
if ((i > arg0[0]) && (i % step == 0))
publishProgress(++nivel);
}
return n;
}

mtodo doInBackground puede invocar en cualquier momento al mtodo publishProgress para actualizar la interfaz de
usuario segn el avance actual del procesamiento. Esta llamada provocar que se invoque el mtodo onProgressUpdate desde el
thread principal.

Sintaxis

protected void onProgressUpdate (Progress... values)

Ejemplo

Una vez realizado el


@Override procesamiento, se invoca el
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Toast.makeText(MiActividadPrincipal.this,
values[0]+"0% completado", Toast.LENGTH_SHORT).show();
}

mtodo onPostExecute para procesar el resultado. Este mtodo se invoca desde el thread principal y puede, por tanto, modificar la
interfaz de usuario.

Sintaxis

protected void onPostExecute (Result result)

Ejemplo

@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
Toast.makeText(MiActividadPrincipal.this,
result + " nmeros primos encontrados en total.",
Toast.LENGTH_SHORT).show();
}

Es posible detener la tarea invocando a su mtodo cancel. Para tener en cuenta esta
anulacin lo ms rpidamente posible, el procesamiento contenido en el
mtodo doInBackground deber verificar de forma regular el valor de retorno
del mtodo isCancelled. En tal caso, se invocar al mtodo onCancelled en lugar de al
mtodo onPostExecute.

Slo queda por utilizar esta clase para ejecutar el procesamiento. Para ello, hay que instanciar la clase e invocar a
su mtodo execute para ejecutar la tarea. Este mtodo recibe como entrada tantos parmetros del tipo Params como sean
necesarios para el procesamiento.

Una tarea slo puede procesarse una nica vez. Es preciso crear una nueva instancia para
ejecutar un nuevo procesamiento.

Sintaxis 166
public final AsyncTask<Params, Progress, Result>
execute (Params... params)
public final boolean cancel (boolean mayInterruptIfRunning)

Ejemplo

En este ejemplo, la tarea se


public class MiActividadPrincipal extends Activity { crea y ejecuta desde la
creacin de la actividad.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

NumerosPrimos tarea = new NumerosPrimos();


tarea.execute(0, 10000000);
}
}

2. Thread
Si bien es prctica, la clase AsyncTask puede que no nos convenga en ciertos casos. Otra solucin consiste en utilizar la
clase Thread. Esta clase permite definir y ejecutar un procesamiento. Es posible ejecutar varios threads concurrentes y sincronizarlos
entre ellos.

La comunicacin entre este thread y el thread principal puede realizarse mediante el uso de objetos de tipo Handler.

a. Creacin

Existen dos formas de crear un thread.

La primera forma de crear un thread consiste en instanciar la clase Thread y pasarle como parmetro un objeto de tipo Runnable,
este ltimo permite especificar el procesamiento en su mtodo run.

Sintaxis

public Thread (Runnable runnable)

Sintaxis del mtodo run de la clase Runnable

public abstract void run ()

Ejemplo

La otra forma de crear un


Thread thread = new Thread(new Runnable() { thread consiste en instanciar
@Override una clase que herede de la
public void run() { clase Threade implementando
Log.d(TAG, "Ejecucin del thread"); el mtodo run.
}
}); Sintaxis

public void run ()

Ejemplo

En ambos casos de creacin del


public class MiThread extends Thread { thread, la ejecucin del
private static final String TAG = "MiThread"; procesamiento se realiza
invocando almtodo start del
@Override objeto de tipo Thread.
public void run() {
super.run(); Sintaxis
Log.d(TAG, "Ejecucin del procesamiento");
}
public synchronized void start ()
}

Ejemplo

MiThread thread = new MiThread();


thread.start();

b. runOnUIThread

Si un thread secundario quiere ejecutar cdigo sobre el thread principal como, por ejemplo, para actualizar directamente la interfaz
de usuario, puede hacerlo utilizando el mtodo runOnUIThread.

Este mtodo recibe como parmetro un objeto de tipo Runnable que contiene el cdigo a ejecutar en el thread principal. Esto evita
tener que implementar un sistema de comunicacin entre ambos threads cuando se trata nicamente de modificar la interfaz de
usuario, por ejemplo.

Sintaxis
167
public final void runOnUiThread (Runnable action)

Ejemplo

runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(MiActividadPrincipal.this, "blablabla",
Toast.LENGTH_SHORT)
.show();
}
};

c. Comunicacin inter-threads

La clase Handler permite a distintos threads comunicarse entre ellos. En concreto, un objeto de tipo Handler puede enviar
mensajes al thread una vez lo ha creado.

La clase Handler es tambin un medio sencillo para enviar mensajes desde y hacia un
mismo thread. Esto permite planificar el procesamiento de ciertos mensajes o procesamientos
en el tiempo sin tener por qu recurrir a un sistema de alarmas o algn equivalente ms
adecuado.

Estos mensajes son bien objetos de tipo Message, o bien objetos de tipo Runnable. Un objeto de tipo Message puede, entre
otros, comportar los siguientes datos: el sujeto o tipo de mensaje mediante un entero, dos enteros y un objeto de tipo Object.

La creacin de un objeto de tipo Handler se realiza instanciando directamente a la clase Handler utilizando el constructor por
defecto. Este handler est asociado al thread que lo ha creado. Esto provoca que, si la instanciacin tiene lugar directamente en la
clase de un componente de aplicacin, el thread del handler es el thread principal. En este caso, esto permite a un thread secundario
comunicarse con el thread principal que puede modificar la interfaz de usuario.

La recepcin de los mensajes enviados al objeto de tipo Handler se realiza implementando elmtodo handleMessage. Este
mtodo recibe como parmetro el objeto de tipo Messagerecibido.

Sintaxis

public Handler ()
public void handleMessage (Message msg)

Ejemplo

La creacin de un objeto de
public class MiActividadPrincipal extends Activity { tipo Message se realiza
private Handler handler = new Handler() { indirectamente mediante el
@Override objeto de
public void handleMessage(Message msg) { tipo Handler utilizando uno de
switch (msg.what) {
case MSG_PROCESAMIENTO_A:
procesamientoA();
break;
case MSG_PROCESAMIENTO_B:
procesamientoB();
break;
}
}
};
}

sus mtodos obtainMessage. Estos mtodos permiten especificar como parmetros todos los datos o una parte de ellos.

Sintaxis

public final Message obtainMessage ()


public final Message obtainMessage (int what)
public final Message obtainMessage (int what, Object obj)
public final Message obtainMessage (int what, int arg1, int arg2)
public final Message obtainMessage (int what, int arg1, int arg2,
Object obj)

Ejemplo

Una vez creado el mensaje,


Message msg = handler.obtainMessage(what, obj); basta con enviarlo al handler.

Tambin en este punto, se


proveen varios mtodos. El primero sendMessage, enva el mensaje y lo procesa inmediatamente.
El segundo sendMessageAtTime, enva el mensaje y lo procesar en el momento indicado en milisegundos desde el arranque del
sistema. Por ltimo, el tercer mtodo, sendMessageDelayed, enva el mensaje y lo procesa tras un tiempo de espera especificado
en milisegundos a partir de la recepcin del mensaje.

Sintaxis

168
public final boolean sendMessage (Message msg)
public boolean sendMessageAtTime (Message msg, long uptimeMillis)
public final boolean sendMessageDelayed (Message msg,
long delayMillis)

Ejemplo

En este ejemplo, el mensaje lo


Message msg = handler.obtainMessage(what, obj); enva y recibe directamente el
handler.sendMessage(msg); mtodo handleMessage del
handler.

Si los mensajes que se quiere enviar son sencillos y slo contienen el asunto, la clase Handlerproporciona para ello mtodos que
tienen en cuenta la creacin de estos mensajes. La variante de los mtodos propuestos es del mismo tipo que el de los
mtodos sendMessage.

Sintaxis

public final boolean sendEmptyMessage (int what)


public final boolean sendEmptyMessageAtTime (int what,
long uptimeMillis)
public final boolean sendEmptyMessageDelayed (int what,
long delayMillis)

Ejemplo

En este ejemplo, el mensaje lo


Message msg = handler.obtainMessage(what, obj); recibir el
handler.sendEmptyMessageDelayed(msg, 5000); mtodo handleMessage del
handler en cinco segundos.

Por ltimo, como se ha indicado antes, la clase Handler permite a su vez enviar objetos de tipo Runnable como mensaje. La
variante de los mtodos propuestos es del mismo tipo que el de los mtodos sendMessage.

Sintaxis

public final boolean post (Runnable r)


public final boolean postDelayed (Runnable r, long delayMillis)
public final boolean postAtTime (Runnable r, long uptimeMillis)

Ejemplo

En este ejemplo, se supone


handler.post(new Runnable() { que el handler ha sido creado
public void run() { en el thread principal. Puede,
Log.d(TAG, "Cdigo enviado al handler"); por tanto, mostrar
Toast.makeText(MiActividadPrincipal.this, "Este cdigo ha sido enviado al handler paradirectamente
la ejecucin un
en su thread.",
mensaje de
Toast.LENGTH_SHORT).show(); tipo Toast.
}
});

169
Seguridad y permisos
Por defecto, Android asigna un identificador de usuario Linux a cada aplicacin durante su instalacin
en el sistema.

Es, por tanto, el sistema de permisos estndar de Linux el que se utiliza para controlar el acceso al
espacio de almacenamiento y, por tanto, a las aplicaciones y sus datos. Cada una de las aplicaciones
dispone de su propio espacio privado: proceso y espacio de almacenamiento. Puede, no obstante,
compartir ciertos datos y archivos especificndolo explcitamente (vase el captulo La persistencia de
los datos - Proveedor de contenidos).

Por defecto, una aplicacin no posee ningn permiso que pueda, entre otros, alterar las dems
aplicaciones, el sistema Android o que permita acceder a los datos privados del usuario.

Si una aplicacin trata de realizar una accin que le est prohibida, se escribir un mensaje de
error en los logs. A menudo, es posible que se eleve una excepcin Java de seguridad, segn el
caso.

El acceso a ciertos datos sensibles, el uso de componentes de hardware del dispositivo Android, el
acceso a la red, la posicin GPS del usuario o bien otras funcionalidades requieren obligatoriamente
que la aplicacin declare explcitamente cada uno de los permisos que requiere.

Esta lista de permisos se le proporcionar al usuario de forma previa a la descarga de la aplicacin, por
ejemplo en el Android Market. El usuario podr, entonces, consultarla y decidir, con total conocimiento,
si instalar la aplicacin o no segn los permisos requeridos.

El usuario debe aceptar todos los permisos solicitados por la aplicacin para instalarla. Por ello,
es preciso no solicitar ms permisos que los estrictamente necesarios para el buen
funcionamiento de la aplicacin. Los usuarios podrn no querer instalar la aplicacin si no
comprenden por qu se solicitan permisos que parecen injustificados respecto a las funcionalidades
que ofrece la aplicacin.

Una vez instalada, la aplicacin dispone de los permisos solicitados para siempre, hasta la prxima
actualizacin de la aplicacin que implique una actualizacin en la lista de permisos.

1. Declaracin de los permisos


La declaracin de los permisos se realiza en el manifiesto. La etiqueta uses-
permission permiteespecificar un permiso requerido. Se utiliza dentro de la etiqueta manifest.
Es preciso, por tanto, insertar tantas etiquetas uses-permission como permisos se soliciten.

Sintaxis

<uses-permission android:name="cadena de caracteres">

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<manifest ...>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SEND_SMS" />
</manifest>

En este ejemplo, la aplicacin solicita dos permisos: uno para poder hacer vibrar el dispositivo y otro
para poder enviar SMS (mensajes de texto cortos enviados a travs de la red de telefona mvil).

170
La lista completa de permisos proporcionados por el sistema pueden consultarse directamente
en la vista Eclipse Permissions del manifiesto. Tambin es posible consultarla en la
direccin:http://developer.android.com/reference/android/Manifest.permission.html

Observe que una aplicacin tambin puede crear sus propios permisos utilizando
la etiqueta permission en el manifiesto.

2. Restriccin de uso
Cada componente de una aplicacin puede solicitar que pueda ser utilizado slo por aquellos
componentes que posean ciertos permisos.

A partir de Android 3.0 (API 11), existe una excepcin. Incluso si un componente requiere un
permiso especfico para poder ser ejecutado, otro componente de la misma aplicacin puede
utilizarlo sin poseer, l mismo, los permisos solicitados por el componente.

Para ello, debe especificarse el atributo android:permission dentro de la etiqueta del


componente que quiera controlar su acceso.

Observe que el componente de tipo ContentProvider permite especificar de forma ms fina el


acceso proporcionando otros
dos atributos android:readPermission yandroid:writePermission. Estos atributos
permiten respectivamente indicar quin puede leer y escribir la informacin en el proveedor de
contenidos.

Se elevar una excepcin Java de seguridad si un componente cliente utiliza un componente para el
que no posee permisos, salvo en el caso del receptor de eventos.

En el caso del envo no autorizado de un evento al receptor de eventos, no se generar


ninguna excepcin, aunque el receptor de eventos no recibir este evento. Tambin es posible
especificar un permiso requerido que el receptor de eventos tendr que poseer obligatoriamente
para recibir el intent tras el envo de un intent (vase el captulo Componentes principales de la
aplicacin - Receptor de eventos).

Sintaxis

<activity android:permission="cadena de caracteres" ...>


<service android:permission="cadena de caracteres" ...>
<receiver android:permission="cadena de caracteres" ...>
<provider android:permission="cadena de caracteres" ...>
<provider android:readPermission="cadena de caracteres" ...>
<provider android:writePermission="cadena de caracteres" ...>

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<manifest ...>
<application ...>
<activity android:name=".MiActividadPrincipal"
android:permission="android.permission.VIBRATE" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
171
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

172
Red
Una de las funcionalidades habituales de la que quiere disponer una aplicacin es la capacidad de
intercambiar informacin con un servidor remoto, bien sea sobre una red privada o sobre Internet.

Segn se trate de un particular, profesional, , corresponde al responsable verificar, llegado el


caso, si es necesario declarar el uso de datos personales de los usuarios recogidos en los
servidores, como por ejemplo sus coordenadas geogrficas. Para ms informacin vaya a la
direccin: http://www.aepd.es/

La duracin de un intercambio con un servidor, es decir, el tiempo entre la construccin y el envo del
mensaje, y el retorno y el anlisis de la respuesta, depende de muchos factores:

La construccin y el envo de la consulta, que puede llevar ms o menos tiempo segn la


potencia del dispositivo Android y la complejidad de la consulta.

La calidad de la red y su velocidad, en especial cuando la conexin se establece mediante la


red de telefona mvil.

El tiempo de respuesta del propio servidor que puede tardar varios segundos, o decenas de
segundos, antes de enviar una respuesta.

El desarrollador es totalmente dependiente de factores que no puede controlar en trminos de


duracin. Es preciso, por tanto, tenerlo en cuenta en la etapa del desarrollo de la comunicacin con el
servidor. En concreto, la tarea de comunicacin puede ser larga, y tendr que realizarse en un thread
secundario para no bloquear la aplicacin.

Para poder comunicarse con un servidor remoto, la primera etapa consiste en dotar a la aplicacin de
los permisos para abrir sockets de red. Para ello, hay que agregar
el permiso android.permission.Internet en el manifiesto.

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


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

Android incluye la librera HTTP Apache que permite utilizar el protocolo HTTP de forma sencilla. Esta
librera contiene numerosas clases y mtodos. Dado que no es especfica de Android, no detallaremos
ms que algunas de sus clases y ciertos mtodos.

Desde la versin 2.2 (API 8), Android proporciona tambin la clase AndroidHttpClient que
implementa la interfaz HttpClient, configurada especialmente para Android. Esta clase prohbe, en
concreto, el envo de consultas HTTP desde el thread principal, elevando una excepcin.

Ejemplo

java.lang.RuntimeException: This thread forbids HTTP requests

En versiones inferiores a Android 2.2 (API 8), es posible reemplazar la


clase AndroidHttpClient por la clase DefaultHttpClient. El firewall que impide su uso en el
thread principal no existe, por lo que habr que velar por ejecutarla sobre un thread secundario.

Veamos, a continuacin, cmo utilizar algunas de las clases y los mtodos de estas libreras para
enviar una consulta a un servidor remoto y recuperar la respuesta.

173
1. Agente usuario
El user-agent (agente usuario) es una cadena de caracteres incluida en el encabezado de una
consulta HTTP enviada por un cliente a un servidor. Permite identificar el sistema del cliente indicando,
por ejemplo, el nombre de la aplicacin cliente, su versin

El servidor puede entonces utilizar esta informacin para adaptar mejor su respuesta. Por ejemplo,
un servidor web podr detectar que el cliente es un navegador de un dispositivo mvil. Podr,
entonces, redirigir automticamente la peticin hacia la versin mvil del sitio web.

En el caso en que el desarrollador Android gestione tambin la parte servidora, puede ser
interesante para l construir un agente usuario proporcionando la mxima informacin posible sobre
el dispositivo, el sistema y la aplicacin Android. Esto le permitir ver en detalle qu dispositivos, qu
sistemas y versiones del sistema, y qu versiones de las aplicaciones poseen los usuarios.

Para obtener la informacin asociada al sistema, podemos utilizar algunas de las constantes que
proporciona la clase android.os.Build. Los valores de estas constantes son cadenas de
caracteres.

La constante Build.MODEL proporciona el modelo del dispositivo Android en forma de cadena de


caracteres. Los valores devueltos por esta constante pueden ser, por ejemplo: DROID2, Nexus
One, GT-I9000, T-Mobile G2, X10i, ZTE-RACER, MB525, GT-I5700...
Sintaxis

Build.MODEL

Ejemplo

String modelo = Build.MODEL;

La constante Build.VERSION.RELEASE proporciona el nmero de versin del sistema en forma


de cadena de caracteres. Los valores devueltos por esta constante pueden ser, por ejemplo: 3.0,
2.3.3, 2.2.2, 2.1-update1, 1.5...
Sintaxis

Build.VERSION.RELEASE

Ejemplo

String versionSistema = Build.VERSION.RELEASE;

La constante Build.DISPLAY proporciona el nombre de cdigo del sistema en forma de cadena de


caracteres. Los valores devueltos por esta constante pueden ser, por ejemplo: VZW, FRG83G,
ECLAIR, FRF91...
Sintaxis

Build.DISPLAY
Ejemplo

String codigoSistema = Build.DISPLAY;

El cdigo del idioma as como el cdigo regional configurado por el usuario en el sistema Android
tambin pueden recuperarse. Para ello, hay que usar la clase Locale y su mtodo getDefault.
Este mtodo devuelve una instancia de tipo Locale. El uso del mtodo toString permite
recuperar el cdigo del idioma as como el cdigo regional concatenados en forma de cadena de
caracteres. Los valores devueltos pueden ser, por ejemplo: en_US, es_ES, fr_FR, bg_BG,
zh_TW
174
Sintaxis

public static Locale getDefault ()

Ejemplo

String paramsReg = Locale.getDefault().toString();

Android permite obtener informacin sobre las aplicaciones. En nuestro caso, esto permite recuperar
esta informacin de forma dinmica en lugar de incluirla en nuestro cdigo. El cdigo no se habr
modificado tras la actualizacin de la aplicacin y podr reutilizarse para otras aplicaciones.

La identificacin de una aplicacin se realiza mediante el nombre de su paquete. Este nombre se


utilizar en los mtodos detallados ms adelante. Para recuperar dinmicamente el nombre del
paquete en curso, hay que usar el mtodo Context.getPackageName.

Sintaxis

public abstract String getPackageName ()

Ejemplo

String nombrePaquete = context.getPackageName()

La clase PackageManager permite recuperar informacin asociada a las aplicaciones instaladas en


el sistema. Es posible recuperar una instancia de esta clase invocando al mtodo
esttico getPackageManager.

Sintaxis

public abstract PackageManager getPackageManager ()

Ejemplo

PackageManager manager = context.getPackageManager();

El mtodo getPackageInfo permite obtener toda la informacin contenida en el manifiesto. Este


mtodo recibe como parmetros el nombre de la aplicacin identificada por su paquete y un flag
opcional que aqu no se utiliza.

Devuelve un objeto de tipo PackageInfo. Puede elevar una


excepcin NameNotFoundException si el nombre del paquete proporcionado no se encuentra
entre las aplicaciones instaladas.

Sintaxis

public abstract PackageInfo getPackageInfo (String packageName,


int flags)

Ejemplo

PackageInfo info = null;


try {
info = manager.getPackageInfo(context.getPackageName(), 0);
} catch (NameNotFoundException e1) {
}

Queda por recuperar la informacin del objeto de tipo PackageInfo accediendo directamente a sus
variables miembros packageName y versionName proporcionando, respectivamente, el nombre
del paquete y el nmero de versin de la aplicacin.
175
Ejemplo

String nombrePaquete = info.packageName;


String nombreVersion = info.versionName;

La cadena de caracteres agente usuario puede, as, estar constituida por toda esta informacin.

Ejemplo

final String AGENTE_USUARIO = "%s/%s (Android/%s/%s/%s/%s)";


String agenteUsuario = String.format(AGENTE_USUARIO,
info.nombrePaquete, nombreVersion, modelo, versionSistema,
codigoSistema, paramsReg);

2. AndroidHttpClient
Para describir el envo de una consulta y la recepcin de la respuesta del servidor, supondremos que
el servidor remoto acepta una peticin HTTP GET y enva una respuesta bajo la forma de una cadena
de caracteres como, por ejemplo, una respuesta con formato Json.

Android incluye la librera org.json que contiene lo necesario para leer respuestas con
formato Json. Para ms informacin sobre el formato json: http://www.json.org/.

Desde Android 3.0 (API 11), la librera org.json proporciona las nuevas
clases JsonReadery JsonWriter que permiten, respectivamente, leer y escribir de forma
sencilla un flujo Json.

La peticin GET se crea fcilmente con la clase HttpGet y uno de sus constructores recibe como
parmetro la direccin completa del sitio.

Sintaxis

public HttpGet (String uri)

Ejemplo

HttpGet httpGet = new HttpGet("http://...");

La clase AndroidHttpClient permite utilizar un cliente HTTP especficamente adaptado a Android.


Para ello, no hay que instanciarlo directamente sino utilizar su mtodo esttico newInstance que
devuelve una instancia. Este mtodo recibe como parmetro una cadena de caracteres que describe
el agente usuario.

Sintaxis

public static AndroidHttpClient newInstance (String userAgent)

Ejemplo

AndroidHttpClient httpClient =
AndroidHttpClient.newInstance(agenteUsuario);

El envo de la consulta y la recepcin de la respuesta se realizan invocando al mtodo execute del


cliente HTTP. Este mtodo est disponible en distintas formas. Una de ellas, en concreto, recibe como
parmetros la consulta y un objeto que implementa la interfaz ResponseHandler. Puede elevar
excepciones de tipo IOException si ha tenido algn problema o si la conexin ha sido anulada y
176
excepciones de tipo ClientProtocolException su ha habido un error en el protocolo HTTP.

Es preciso, evidentemente, que el dispositivo Android est conectado a la red mediante Wi-Fi o
mediante la red de telefona mvil, por ejemplo, o en caso contrario se elevar una excepcin
de tipo java.net.UnknownHost-Exception, que hereda del tipo IOException.

La clase BasicResponseHandler implementa la interfaz Response- Handler y, en concreto,


su mtodo handleResponse. Este mtodo recibe como entrada la respuesta del servidor bajo la
forma de un objeto de tipo HttpResponse, extrae el contenido de la respuesta y lo devuelve en
forma de cadena de caracteres.

Se elevar una excepcin de tipo HttpResponseException si el cdigo de retorno del servidor es


igual o superior a 300.

Sintaxis

public String handleResponse (HttpResponse response)

De este modo, el mtodo execute devolver la respuesta del servidor en forma de cadena de
caracteres si recibe como parmetro un objeto de tipo BasicResponseHandler, y elevar las
excepciones llegado el caso.

Sintaxis

public abstract T execute (HttpUriRequest request,


ResponseHandler<? extends T> responseHandler)

Ejemplo

String reponse = null;


try {
reponse = httpClient.execute(httpGet,
new BasicResponseHandler());
} catch (HttpResponseException e1) {
int errno = e1.getStatusCode();
procesarExcepcion(e1);
} catch (ClientProtocolException e2) {
procesarExcepcion(e2);
} catch (IOException e3) {
procesarExcepcion(e3);
}

Una vez finalizada la comunicacin, el cliente debe cerrar las conexiones y liberar los recursos
reservados invocando a su mtodo close.

Sintaxis

public void close ()

Ejemplo

try {
...
} finally {
httpClient.close();
}

La llamada a este mtodo podr, en concreto, realizarse en el bloque finally de la gestin


de las excepciones. De este modo, se invocar siempre y los recursos se liberarn, se haya
elevado o no una excepcin.
177
11. Trazas,
depuracin y
pruebas

178
Introduccin
Incluso en las aplicaciones ms sencillas, es raro poder escribir el cdigo sin incurrir en algn error
tcnico o funcional. Tambin puede haberse omitido el procesamiento de algn caso funcional
particular.

Adems, conforme ms compleja es la aplicacin, ms difcil se hace modificarla sin correr el riesgo de
agregar bugs o regresiones funcionales.

Para evitar esto, cada cual tiene su tcnica. Hay quien sigue ciclos de desarrollo en V o en Y, otros
adoptan metodologas de desarrollo ms o menos giles como XP (Extreme Programming) o TDD (Test
Driven Development), y a menudo una mezcla de todas ellas...

No obstante, cada uno define su estrategia particular en cuanto a la realizacin de pruebas unitarias
y/o de integracin y/o de validacin y/o de conformidad funcional. En ocasiones, la estrategia es
simple: no se realizan pruebas, si bien esto no es lo ms adecuado.

Sea cual sea la necesidad del desarrollador, Android proporciona distintas soluciones para ayudar a
mejorar la calidad de su cdigo y eliminar la mayor cantidad de errores.

Comenzaremos estudiando el sistema de registro de eventos. A continuacin, veremos por encima la


depuracin paso a paso de una aplicacin para concentrarnos en la perspectiva Android de
depuracin y de trazas llamada DDMS (Dalvik Debug Monitor Server). Por ltimo, veremos las pruebas
unitarias y las pruebas de integracin.

179
Registro de eventos
Un registro de eventos contiene los logs (trazas de ejecucin de una aplicacin). En Android, existen
varios registros de eventos: uno principal y varios secundarios especficos a un dominio, por ejemplo
los mensajes asociados a la telefona. Estos registros se almacenan en forma de logs circulares.

Cada uno de estos eventos est constituido por los siguientes elementos:

Fecha y hora de la aparicin del evento.

Categora del evento.

Identificador nico del proceso, llamado pid (Process IDentifier), que ha generado el evento.

Una etiqueta, llamada tag, que permite designar el origen del evento: nombre del proceso, del
componente, de la actividad, de la clase

Un mensaje detallando el evento.

Existen varias categoras que permiten clasificar los eventos. He aqu las cinco clases principales en
orden de ms detallada a menos detallada:

Categora Nivel Descripcin

Verboso V Categora ms detallada. Si es muy grande la cantidad de


informacin a mostrar, esta categora puede ralentizar
sensiblemente el funcionamiento de la aplicacin. Por ello,
se recomienda no utilizarla salvo en tiempo de desarrollo.

Depuracin D Normalmente, los elementos de esta categora se muestran


si la aplicacin se ha compilado en modo debug. En modo
release, estos elementos se ignoran y, por tanto, no se
muestran.
No obstante, esta ltima funcionalidad no siempre est
activa en el momento de escribir este libro. Por ello, a da
de hoy, los elementos se muestran siempre, sea cual sea el
modo de compilacin utilizado.

Informacin I Categora con carcter informativo. Es conveniente usarla


con tranquilidad dado que siempre se muestra.

Advertencia W Categora que agrupa las alertas, eventos a los que el


lector debe prestar una atencin especial y tratar de
resolver antes de que se genere un error.

Error E Nivel ms elevado de los cinco presentes. Caracteriza


generalmente un evento que ha generado un error grave y
puesto en peligro el funcionamiento de la aplicacin.

1. Consultar los eventos


En Eclipse, el desarrollador puede consultar el histrico de eventos del registro por defecto as
generado mostrando la vista LogCat. sta ya viene activa en la perspectiva DDMS descrita ms
adelante. Para activarla en la vista Java, he aqu el procedimiento a seguir:

En el men general de Eclipse, seleccione Window - Show View - Other.

Se muestra la ventana Show View.

Abra la carpeta Android.

180
Vista LogCat

Seleccione LogCat y haga clic en el botn OK.

La vista LogCat se agrega a las vistas de Eclipse.

Vista LogCat

En la parte superior derecha de la ventana figuran los filtros preconfigurados que permiten mostrar
nicamente los mensajes de nivel igual o superior al filtro. El uso del botn + permite crear nuevos
filtros.

Tambin es posible obtener los logs directamente en la consola utilizando la herramienta adbseguida
del comando logcat. Es posible usar numerosas opciones, por ejemplo, indicar otro formato de
visualizacin de los eventos o incluso filtrar los eventos que se quieren mostrar segn su etiqueta y
su categora.

Sintaxis
181
adb logcat [opcin] ... [filtro] ...

Para descubrir todas las opciones y formatos de los filtros disponibles, especifique la opcin -
help.

Ejemplo

$ adb logcat

Este comando produce la siguiente visualizacin:

Vista LogCat

Por defecto, la visualizacin contiene la misma informacin que la vista LogCat en Eclipse pero con un
formato ligeramente distinto.

En Eclipse, en ocasiones ocurre que la vista LogCat no muestra los logs. Es necesario reiniciar
Eclipse. Para evitar esto, se puede utilizar la herramienta adb como se ha visto anteriormente
para obtener la visualizacin de los logs en una consola.

2. Escribir eventos
Los eventos registrados en el registro son los del sistema, pero tambin los de las aplicaciones. En
efecto, cualquier aplicacin puede generar tales eventos.

Para ello, el SDK provee la clase Log del paquete android.util. Esta clase contiene como mnimo
dos mtodos para cada una de las categoras de eventos. Estos mtodos reciben como parmetro
una etiqueta y el mensaje. Uno de los mtodos recibe un tercer parmetro de entrada que es un
objeto de tipo Throwable que contiene un complemento de la informacin, principalmente el
mensaje de la pila de llamadas a los mtodos previos a que se provocase el evento.

La categora Advertencia proporciona un tercer mtodo que recibe como parmetros una etiqueta y
un objeto de tipo Throwable.

Sintaxis

public static int v (String tag, String msg)


public static int v (String tag, String msg, Throwable tr)
public static int d (String tag, String msg)
public static int d (String tag, String msg, Throwable tr)
public static int i (String tag, String msg)
public static int i (String tag, String msg, Throwable tr)
public static int w (String tag, String msg)
public static int w (String tag, Throwable tr)
public static int w (String tag, String msg, Throwable tr)
public static int e (String tag, String msg)
182
public static int e (String tag, String msg, Throwable tr)

Es habitual definir una cadena de caracteres constantes propia a cada clase de tipo actividad,
servicio... para usarla como etiqueta en el resto de la clase. Esto permite filtrar y encontrar ms
rpidamente los mensajes en el histrico. De manera recproca, esto permite encontrar fcilmente el
origen de los mensajes.

Ejemplo

public class MiActividadPrincipal extends Activity {


private static final String TAG = "MiActividadPrincipal";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "Desde el mtodo onCreate");
}
}

183
Depuracin
La depuracin es la fase consistente en buscar y corregir los bugs. Para dar soporte a esta tarea,
Eclipse, el plug-in ADT y el SDK Android ponen a disposicin del desarrollador un conjunto de
herramientas.

1. Depuracin paso a paso


La depuracin paso a paso no es especfica de Android. Este modo est disponible en todos los
programas Java en Eclipse. Utiliza una herramienta llamada depurador que ejecuta el programa en un
modo concreto. El desarrollador tiene, entonces, acceso a numerosas funcionalidades como, por
ejemplo: establecer puntos de ruptura en el cdigo fuente, analizar paso a paso el desarrollo del
programa y conocer, entre otros, la pila de llamadas de los mtodos y los valores de las variables.

Supondremos que se maneja bien el uso de este modo de depuracin en Eclipse dado que no es algo
especfico de la plataforma Android sino del desarrollo en Java.

Hasta la versin 9 de las Android SDK tools (herramientas del SDK Android), para permitir este tipo de
depuracin, una aplicacin Android necesitaba poner obligatoriamente
a true el atributo android:debuggable de la etiqueta application del manifiesto, que por
defecto vale false. Sin ello, la ejecucin en modo de depuracin no tena efecto alguno.

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="es.midominio.android.miapli"
android:versionCode="1"
android:versionName="1.0">
<application android:debuggable="true"
android:icon="@drawable/icon"
android:label="@string/app_name">
</application>
<uses-sdk android:minSdkVersion="8" />
</manifest>

Desde la versin 9 de las herramientas del SDK, el desarrollador ya no necesita agregar este atributo
para posicionarlo a true. En Eclipse y el plug-in ADT, esto se realiza automticamente mediante
compilaciones incrementales que se consideran, por defecto, compilaciones de debug. No es sino una
exportacin de una compilacin firmada en modo release que no tendr este atributo.

Esta funcionalidad est, de hecho, incluida en la versin 8, pero un bug impide que funcione
correctamente. Este bug ha sido corregido en la versin 9.

Se recuerda que el desarrollador siempre debe utilizar la versin ms reciente de las


herramientas del SDK.

2. DDMS
El plug-in ADT proporciona una perspectiva Eclipse dedicada especialmente a la depuracin de la
aplicacin Android: la perspectiva DDMS (Dalvik Debug Monitor Server). sta utiliza de forma interna la
herramienta del mismo nombre: ddms. Esta herramienta ofrece bastantes funcionalidades. Vamos a
ver las principales, que se retoman en la perspectiva Eclipse.

184
Observe que si se ejecuta desde una lnea de comandos, esta herramienta ofrece todava ms
funcionalidades avanzadas.

Si la perspectiva DDMS no est visible en la parte superior de la ventana general de Eclipse,


haga clic en el signo para mostrarla.

Perspectiva DDMS

Haga clic en el botn DDMS para mostrar la perspectiva.

185
Perspectiva DDMS

La perspectiva DDMS contiene varias vistas nuevas: Devices, Emulator


Control, Threads, Heap,Allocation Tracker, File Explorer que vamos a descubrir con detalle ms
adelante.

a. Vista Devices

DDMS - Vista Devices

La vista Devices, situada por defecto en la parte superior izquierda, proporciona la lista de
186
emuladores y dispositivos conectados y, para cada uno de ellos, la lista de ciertos procesos
existentes identificados por el nombre del paquete de la aplicacin que los alberga. A continuacin
se indica, en las columnas de la derecha, el identificador del proceso y el puerto de conexin para el
depurador.

La seleccin de un proceso de la lista activa los botones situados en la parte superior derecha
correspondientes a las funcionalidades siguientes, descritas de izquierda a derecha:

Debug the selected process: pone la aplicacin en modo debug. Requiere que el proyecto
correspondiente est abierto en el espacio de trabajo de Eclipse.

Update Heap: activa las actualizaciones de la informacin de ejecucin de la aplicacin. Esta


informacin se indica en la vista Heap descrita ms adelante.

Dump HPROF file: recupera un archivo con formato HPROF. Este archivo es una imagen de
la memoria de la mquina virtual. Permite, en concreto, buscar las fugas de memoria
estudindola con las herramientas especializadas como Mat, jmap, jhat.

Cause GC: fuerza la ejecucin del garbage collector (recolector de basura).

Update Threads: activa la actualizacin de la informacin de los threads de la aplicacin.


Esta informacin est indicada en la vista Thread descrita ms adelante.

Start Method Profiling: el primer clic inicia el registro de informacin asociada a la ejecucin
de los mtodos. El segundo clic detiene el registro y muestra los resultados en una ventana
dedicada.

Stop Process: destruye el proceso y, por tanto, la mquina virtual, seleccionado.

Screen Capture: abre una nueva ventana Device Screen Capture que permite realizar
capturas de pantalla de la aplicacin seleccionada y salvaguardarlas. Un clic sobre el
botnRefresh permite actualizar la copia de pantalla.

187
DDMS - Captura de pantalla

Todava en la vista Devices, en el extremo derecho de las funcionalidades descritas


anteriormente, aparece una flecha verde orientada hacia abajo. Un clic sobre esta flecha
permite descubrir otra funcionalidad indicada debajo de la lista: Reset adb. Esto permite reiniciar
la herramienta adb utilizada por la herramienta ddms para conectarse al emulador o al
dispositivo Android si la situacin exige tener que reiniciar el emulador/dispositivo y/o Eclipse.

b. Vista Emulator Control

188
DDMS - Vista Emulator Control

La vista Emulator Control, situada a la izquierda, debajo de la vista Devices, permite simular el
estado de la red telefnica, las llamadas telefnicas, el envo de SMS y las coordenadas geogrficas
en distintos formatos: manual, GPX y KML.

Las coordenadas geogrficas emuladas se reciben como provenientes exclusivamente del sistema
GPS del dispositivo emulado. No es posible emular posiciones que provengan de la red de telefona
mvil o de redes Wi-Fi. El permiso correspondiente al sistema GPS debe, por tanto, figurar en la
aplicacin (vase el captulo Mapas y localizacin geogrfica - Localizacin geogrfica).

Observe la presencia de un bug en las versiones 2.3.x del emulador que provoca un crash en
el emulador cuando se le proporciona una posicin GPS. Para ms informacin, consulte la
pgina: http://code.google.com/p/android/issues/detail?id=13015

c. Vista Threads

189
DDMS - Vista Threads

La vista Threads, como las siguientes vistas, est situada en la parte derecha.

Para activar esta vista, seleccione una aplicacin en la vista Devices y haga clic en el
botnUpdate threads.

En la parte superior figura, de izquierda a derecha: un identificador nico ID del thread atribuido por
la mquina virtual, el identificador Linux del thread, el estado del thread, el tiempo acumulador
hasta ejecutar el cdigo de usuario, en unidades de 10 ms, y el nombre del thread.

En la parte inferior figura la pila de llamadas de los mtodos del thread seleccionado en la parte
superior.

d. Vista Heap

190
DDMS - Vista Heap

Situada a la derecha de la vista Threads, la vista Heap debe estar activa para recibir informacin.

Para ello, seleccione una aplicacin en la vista Devices y haga clic en el botn Update Heap.

Aparece una indicacin mientras que la vista nos informa de que el refresco de la informacin tendr
lugar tras cada ejecucin del recolector de basura. Un clic sobre el botn Cause GC permite forzar
manualmente la ejecucin del recolector de basura y, por tanto, refrescar la informacin.

En la parte superior figura la informacin general asociada a la memoria: el tamao total, el tamao
alojado, el tamao libre, la proporcin de memoria utilizada y el nmero de objetos alojados.

En la parte central se muestra informacin y datos estadsticos repartidos en diversas categoras.

En la parte inferior se dibuja un grfico que representa el nmero de emplazamientos por tamao.
Si se hace clic con el botn derecho es posible modificar las propiedades, salvaguardar los datos, o
imprimirlos.

e. Vista Allocation Tracker

191
DDMS - Vista Allocation Tracker

Situada a la derecha de la vista Heap, la vista Allocation Tracker proporciona informacin sobre los
elementos alojados en memoria.

Para ello, seleccione una aplicacin en la vista Devices y, a continuacin, haga clic sobre el
botn Start Tracking de la vista Allocation Tracker.

Comienza entonces la recoleccin de datos sobre el consumo de memoria. Cada clic en el botnGet
Allocations refresca los datos de la ventana.

Los datos proporcionan informacin sobre las reservas de memoria realizadas desde el inicio de la
colecta. Haciendo clic en el botn Stop Tracking se detiene la recoleccin de datos.

Es posible ordenar las filas de la tabla haciendo clic sobre el ttulo de la columna.

f. Vista File Explorer

DDMS - Vista
192
File Explorer
Situada en la parte derecha de la vista Allocation Tracker, la vista File Explorer es un explorador
del sistema de archivos del emulador o del dispositivo Android.

Es posible transferir archivos desde o hacia el sistema Android y suprimir archivos en el sistema
Android haciendo clic en los respectivos iconos situados en la parte superior derecha.

193
Pruebas unitarias y funcionales
Las pruebas unitarias en Android estn basadas en la biblioteca JUnit 3. Retoman, por tanto, la misma
filosofa adaptndola a la plataforma Android.

Los API de pruebas en Android no son compatibles con JUnit 4.

Las pruebas tambin pueden crearse y ejecutarse en Eclipse mediante el plug-in ADT, tanto por lnea
de comandos como mediante la consola utilizando las herramientas SDK Android. Recuerde, en este
libro nos concentraremos nicamente en el uso de Eclipse y del plug-in ADT.

Una aplicacin Android se prueba mediante otra aplicacin Android: una aplicacin de pruebas.
Crearemos, por tanto, un proyecto de pruebas, le agregaremos las clases de pruebas que contengan
las propias pruebas y finalizaremos ejecutando estas pruebas.

1. Creacin de un proyecto de pruebas


Existen dos posibilidades para crear un proyecto de pruebas Android en Eclipse. La primera consiste
en crearlo al mismo tiempo que el propio proyecto de la aplicacin Android. La segunda consiste en
crearlo posteriormente, como puede ser el caso para un proyecto que ya existe y que se quiere
probar.

En ambos casos, la ventana Eclipse que se proporciona para crear el proyecto de test es
sensiblemente igual.

Descubramos aqu cmo crear un proyecto de pruebas para un proyecto ya existente.

En la vista Package Explorer (Explorador de paquetes) de Eclipse, haga clic con el botn
derecho sobre el proyecto que quiera probar, a continuacin haga clic sobre Android Tools.

194
Proyecto de pruebas

Seleccione New Test Project.

Aparece la ventana New Android Test Project.

Antes de rellenar uno a uno los campos, seleccione un proyecto a probar y ver cmo se
rellenan automticamente la mayora de los campos.

En la zona Test Target, haga clic en el botn Browse... situado a la derecha del campo An
existing Android project.

Proyecto de pruebas

Seleccione el proyecto a probar y haga clic sobre el botn OK.

Los campos se rellenan automticamente.

195
Proyecto de pruebas

Tambin es posible rellenar los campos de forma manual o modificar los que se han rellenado de
forma automtica. He aqu sus correspondencias:

Test Project Name: nombre del proyecto de pruebas. Si bien el desarrollador tiene total libertad a la
hora de seleccionar este nombre, se recomienda enlazarlo con el nombre del proyecto que se quiere
probar. Para ello, es habitual retomar el nombre del proyecto que se quiere probar y agregarle la
palabra Test. Por ejemplo, si el nombre del proyecto que se quiere probar es MiApli, se
196
utilizar MiApliTest.
Content: permite indicar la ubicacin del proyecto de tests. Se proporciona automticamente una
ubicacin por defecto en el campo Location si la opcin Use default location est marcada. Es posible
especificar otro emplazamiento desmarcando esta opcin. En este caso, utilizaremos la ubicacin por
defecto, lo que tendr como consecuencia disociar fsicamente la ubicacin del proyecto de pruebas
de la del proyecto que se quiere probar.

Para aquellos desarrolladores que prefieran tener el cdigo fuente de las pruebas fsicamente
dentro del proyecto que se quiere probar, es habitual utilizar como carpeta raz del proyecto de
pruebas una carpeta llamada tests situada en la raz del proyecto que se quiere probar. Es
decir, en el mismo nivel que las carpetas src y res.

Test Target: permite indicar el proyecto que se quiere probar, bien el que est seleccionado o bien
otro proyecto Android existente en el espacio de trabajo de Eclipse.

Build Target: como con la creacin de un proyecto Android, es preciso seleccionar la versin del SDK
Android que se va a utilizar.

Application name: nombre de la aplicacin. Este nombre puede incluir espacios.

Package name: nombre del paquete Java. Tambin en este caso, la eleccin es libre. No obstante es
habitual escoger el mismo nombre de paquete que el que tiene el proyecto que se quiere probar y
agregarle .test al final. Por ejemplo, si el proyecto que se quiere probar tiene como nombre de
paquete es.midominio.android.miapli, se utilizar es.midominio.
android.miapli.test.
Min SDK Version: versin mnima del SDK de destino. Corresponde con la versin utilizada en el
campo Build Target. De hecho, el nmero de versin se especifica automticamente en este campo.
Una modificacin en su valor modificar el valor del campo Build Target.

Haga clic sobre el botn Finish.

Si el botn Finish sigue de color gris, es porque uno o varios campos estn mal informados.
Para ayudarle a resolver esto, aparecen indicaciones en la parte superior de la ventana.
Tambin es posible que aparezcan mensajes de advertencia sin por ello bloquear el botn Finish.

Se ha creado y agregado el proyecto al espacio de trabajo. La estructura del proyecto es la misma


que para una aplicacin Android, evidentemente, pues se trata de una aplicacin Android.

No obstante, el manifiesto creado automticamente incluye una serie de


etiquetas suplementarias:instrumentation y uses-library.

Archivo AndroidManifest.xml del proyecto de pruebas

<?xml version="1.0" encoding="utf-8"?>


<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="es.midominio.android.miapli.test"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon"
android:label="@string/app_name">
<uses-library android:name="android.test.runner" />
</application>
<uses-sdk android:minSdkVersion="9" />
<instrumentation
android:targetPackage="es.midominio.android.miapli"
android:name="android.test.InstrumentationTestRunner" />
</manifest>
197
La etiqueta instrumentation incluye dos atributos informados:

android:targetPackage: identifica al paquete de la aplicacin que se quiere probar.

android:name: indica la herramienta, la clase, que ejecuta las pruebas.

Preste atencin, verifique bien que el valor del campo android:targetPackage se


corresponde con el paquete de la aplicacin que se quiere probar y no con el de la aplicacin
de pruebas, es decir que no contiene la terminacin .test. Esto puede ocurrir si se ha escogido
la opcin This project en la zona Test Target durante la seleccin del proyecto que se
quiere probar.

Por defecto, el campo :name contiene la clase bsica del lanzador de


pruebas Android android.test.InstrumentationTestRunner. Esta clase no se incluye en el
cdigo Android; forma parte de la biblioteca compartida android.test.runner. Por ello, es
preciso indicar explcitamente que el proyecto la necesita utilizando la etiqueta uses-library y su
atributo android:name.

2. Creacin de una clase de caso de prueba


Ahora que se ha creado el proyecto, hay que agregarle los casos de prueba mediante la creacin de
clases de casos de prueba. Esta clase extiende de una de las numerosas clases de prueba de
Android. El paquete en el que se crea esta clase de prueba representa un conjunto de pruebas.

Es posible utilizar la clase TestCase de JUnit para realizar pruebas no especficas a Android.

Si no, la clase de caso de prueba especfica Android ms sencilla es la clase AndroidTestCase.


Esta clase extiende de las clases TestCase y Assert de JUnit. Por ello, hereda los mtodos
estndar de asercin de JUnit tales como assertEquals, assertNull, fail Android
proporciona otros mtodos de asercin contenidos en las clases MoreAsserts y ViewAsserts.

La clase AndroidTestCase proporciona los mtodos bsicos que se debe utilizar y/o extender
para realizar las pruebas. Es costumbre definir de forma suplementaria un
mtodo testPreconditions. He aqu su descripcin:

testPreconditions: este mtodo se invoca una nica vez antes de ejecutar cualquier
prueba. Permite verificar que la aplicacin que se quiere probar se ha inicializado
correctamente y est lista para ser probada. Si este mtodo falla, entonces no se pueden
tener en cuenta los resultados de las siguientes pruebas, pasen o no con xito.

setUp: este mtodo se invoca antes de cada una de las pruebas de la clase. Permite
inicializar las variables y el entorno de pruebas y, en especial, arrancar la actividad o el
servicio que se quiere probar, por ejemplo. Este mtodo debe invocar, obligatoriamente, a su
mtodo padre utilizando super.setUp().

tearDown: este mtodo es el simtrico al mtodo setUp. Se invoca desde cada una de las
pruebas. Permite restaurar los parmetros del entorno.

Android proporciona otras clases de casos de prueba a medida para los principales componentes.
Esto permite realizar pruebas especficas a la plataforma Android. Estas clases de prueba permiten
probar especficamente las actividades, los servicios y los proveedores de contenido.

Veamos cmo crear una clase de caso de prueba para una actividad.

En la vista Package Explorer de Eclipse, haga clic con el botn derecho sobre el paquete Java.
En nuestro caso: es.midominio.android.miapli.test. A continuacin, haga clic
sobreNew.

198
Proyecto de pruebas

Seleccione Class.

Aparece la ventana New Java Class.

Informe los siguientes campos:

Name: nombre de la clase de pruebas. Por convencin, se utilizar el nombre de la clase que se
quiere probar y se le agregar la terminacin Test. Por ejemplo,
utilizaremos MiActividadPrincipalTest para probar la clase MiActividadPrincipal del
proyecto principal.

Superclass: clase madre de la clase de prueba. Se corresponde con una clase de caso de prueba
Android que se puede escoger entre las que se proporciona para probar las actividades, los servicios
y los proveedores de contenidos. Pertenecen todas ellas al paquete android.test.

Para mostrarlas, basta con hacer clic en el botn Browse... e introducir android.test. en el
campo Choose a type de la ventana Superclass Selection.

199
Proyecto de pruebas

A continuacin hay que hacer doble clic sobre la clase madre que se desee.

Por ejemplo, se utilizar la clase android.test.Activity-UnitTestCase para probar de


forma aislada una nica actividad. Y se remplazar el parmetro genrico T por el nombre de la clase
que se quiere probar. En nuestro caso, se indicar: android.test.ActivityUnit-
TestCase<MiActividadPrincipal>.
Todos los dems campos pueden dejarse tal cual.

200
Proyecto de pruebas

Haga clic en Finish.

Se crea, a continuacin, la clase correspondiente que hereda de la clase madre especificada.

Aparecen errores de compilacin. En primer lugar, hay que importar la clase que se quiere probar. En
nuestro caso se trata de:

import es.midominio.android.miapli.MiActividadPrincipal;

Si Eclipse no puede resolver la importacin es, sin duda, porque el proyecto que se quiere probar no
se ha seleccionado de forma explcita durante la creacin del proyecto de pruebas. Esto tiene como
consecuencia que no se ha incluido la ruta de este proyecto en la ruta de compilacin del proyecto a
probar. Veamos cmo incluir explcitamente el proyecto a probar en la ruta de compilacin del
proyecto de pruebas:

Haga clic con el botn derecho sobre el proyecto de pruebas en el Explorador de Paquetes y, a
continuacin, seleccione Build Path - Configure Build Path.

Si el proyecto que se quiere probar no figura en la lista, seleccione la pestaa Projects, haga
clic en Add..., seleccione el proyecto que se quiere probar y haga clic en el botn OK.
201
Debera haberse resuelto el import.

Segunda etapa, JUnit requiere un constructor sin parmetro. ste debe invocar en primer lugar al
constructor padre pasndole como nico parmetro la clase que se quiere probar.

Sintaxis del constructor padre

public ActivityUnitTestCase (Class<T> activityClass)

Ejemplo

package es.midominio.android.miapli.test;

import android.test.ActivityUnitTestCase;
import es.midominio.android.miapli.MiActividadPrincipal;

public class MiActividadPrincipalTest extends


ActivityUnitTestCase<MiActividadPrincipal> {

public MiActividadPrincipalTest() {
super(MiActividadPrincipal.class);
}

Llegados a este punto, el proyecto no debera contener ningn error de compilacin.

Veremos, a continuacin, en detalle las particularidades ligadas a las clases de casos de prueba
correspondientes a las actividades, los servicios y los receptores de eventos.

a. Probar una actividad

Por su naturaleza y su buen funcionamiento particular, una actividad no puede probarse nicamente
mediante la clase AndroidTestCase. Es por ello por lo que Android proporciona la clase de caso
de prueba InstrumentationTestCase. sta es la clase bsica de los casos de prueba de una
actividad. Permite, en especial, controlar el ciclo de vida de la actividad que se est probando desde
el arranque, pasando por la pausa, y hasta la destruccin Permite a su vez controlar el entorno de
pruebas creando prototipos (objetos simulados) o incluso simular una interaccin con la interfaz de
usuario. Esta clase extiende de las clases TestCase y Assert de JUnit.

Varias clases extienden de esta clase para especializar todava ms los casos de prueba. He aqu
algunas de ellas:

ActivityUnitTestCase: esta clase de caso de prueba permite probar una nica


actividad en un entorno aislado. Es decir, las pruebas se realizan con objetos de
tipo Context y Application simulados. No es posible enviar objetos de
tipo Intentsimulados a la actividad que se est probando excepto mediante la llamada al
mtodo startActivity(Intent intent).

ActivityInstrumentationTestCase2: esta clase de caso de prueba permite


realizar pruebas funcionales de una o varias actividades en un entorno normal. Es decir,
que las pruebas se realizan con objetos de tipo Context y Application reales. Los
objetos de tipo Intent simulados permiten probar estas actividades.

SingleLaunchActivityTestCase: esta clase permite probar las actividades que se


ejecutan en un modo distinto al modo estndar. Para simular el funcionamiento de estos
otros modos, esta clase invoca a los mtodos setUp y tearDown una nica vez para el
conjunto de las pruebas. Por ello, el entorno de pruebas no cambia entre cada prueba. Por
ltimo, no es posible pasarle ningn objeto simulado: Context, Application, Intent

Los objetos simulados se definen en el paquete android.test.mock.

202
b. Probar un servicio

Por su naturaleza independiente, un servicio puede probarse muy fcilmente de forma aislada
mediante el uso de la clase ServiceTestCase. Esta clase permite, en particular, inyectar objetos
simulados de tipo Context y Application antes incluso de arrancar el servicio.

c. Probar un receptor de eventos

No existen clases de prueba previstas para derivar y probar un receptor de eventos. La razn es
simple: para probarlo, basta con probar el objeto que se comunica con este receptor de eventos
mediante el envo de objetos de tipo Intent.

3. Ejecucin de las pruebas


Como hemos visto a lo largo de la creacin del proyecto de pruebas, es la herramienta indicada en la
etiqueta instrumentation del manifiesto la que va a ejecutar las pruebas. Y son estos casos de
prueba los que van a ejecutar la aplicacin que se quiere probar pasndole objetos simulados o no.

Como para cualquier aplicacin Android, sta slo puede ejecutarse desde su emulador o desde un
dispositivo fsico. En ambos casos, la versin del sistema Android debe ser como mnimo igual a la
versin correspondiente al SDK especificada en la aplicacin de pruebas.

En la vista Package Explorer de Eclipse, haga clic con el botn derecho sobre el proyecto de
pruebas y, a continuacin, haga clic en Run As.

Ejecucin de un proyecto de pruebas

Seleccione Android JUnit Test.

El plug-in ADT ejecuta de forma interna la herramienta adb. Esta herramienta ejecuta el lanzador de
pruebas indicado en el manifiesto. A continuacin, se cargan en memoria la aplicacin de pruebas y la
203
aplicacin que se quiere probar. Una vez cargadas, el lanzador realiza las pruebas.

Los resultados aparecen en la vista JUnit que se encuentra en una pestaa situada junto a la
vistaPackage Explorer.

204
Prueba del mono
Como hemos visto anteriormente, las pruebas unitarias permiten realizar casos de prueba precisos
informados por el desarrollador. Pero, si bien el propio desarrollador habr tenido en cuenta el describir
la mxima cantidad de casos de prueba, en un entorno real, el usuario podr interactuar con la
aplicacin de una forma que no est prevista por el desarrollador. Es en este punto donde interviene el
concepto de prueba del mono para ayudar al desarrollador a reducir el campo de interacciones de
usuario que no se hayan probado.

La prueba del mono es una prueba aleatoria de la aplicacin mediante su interfaz grfica. Esta prueba
simula un uso de la interfaz grfica de usuario mediante la pulsacin de teclas, realizacin de gestos
tctiles, clics y dems eventos que cualquier usuario puede realizar normalmente de forma
completamente aleatoria. Esto permitir probar numerosos casos de uso en los que el desarrollador no
haya pensado como, por ejemplo, la validacin de un formulario mientras sus campos siguen estando
vacos.

Android pone a disposicin del desarrollador la herramienta Monkey (Mono) para realizar este tipo de
pruebas. Esta herramienta se ejecuta desde el shell de la plataforma Android, emulador o perifrico.

Sintaxis

adb shell monkey [opciones] [n mero!de!eventos]

Para mostrar la lista completa de opciones disponibles, especifique la opcin -help.

Ejemplo

$ adb shell monkey -p es.midominio.android.miapli -v 100


:Monkey: seed=0 count=100
:AllowPackage: es.midominio.android.miapli
:IncludeCategory: android.intent.category.LAUNCHER
:IncludeCategory: android.intent.category.MONKEY
// Event percentages:
// 0: 15.0%
// 1: 10.0%
// 2: 15.0%
// 3: 25.0%
// 4: 15.0%
// 5: 2.0%
// 6: 2.0%
// 7: 1.0%
// 8: 15.0%
:Switch:
#Intent;action=android.intent.action.MAIN;category=android.intent.
category.LAUNCHER;launchFlags=0x10000000;component=es.midominio.a
ndroid.miapli/.MiActividad;end
// Allowing start of Intent { act=android.intent.action.MAIN
cat=[android.intent.category.LAUNCHER]
cmp=es.midominio.android.miapli/.MmiActividad } in package
es.midominio.android.miapli
:Sending Pointer ACTION_MOVE x=-4.0 y=2.0
:Sending Pointer ACTION_UP x=0.0 y=0.0
:Sending Pointer ACTION_DOWN x=47.0 y=122.0
:Sending Pointer ACTION_UP x=29.0 y=129.0
:Sending Pointer ACTION_DOWN x=255.0 y=259.0
:Sending Pointer ACTION_UP x=255.0 y=259.0
:Sending Pointer ACTION_DOWN x=295.0 y=223.0
:Sending Pointer ACTION_UP x=290.0 y=213.0
:Sending Pointer ACTION_MOVE x=-5.0 y=3.0
:Sending Pointer ACTION_MOVE x=0.0 y=-5.0
// Rejecting start of Intent { act=android.intent.action.MAIN
205
cat=[android.intent.category.HOME]
cmp=com.android.launcher/com.android.launcher2.Launcher } in
package com.android.launcher
:Sending Pointer ACTION_DOWN x=74.0 y=41.0
:Sending Pointer ACTION_UP x=74.0 y=41.0
:Sending Pointer ACTION_MOVE x=3.0 y=-2.0
:Sending Pointer ACTION_UP x=0.0 y=0.0
:Sending Pointer ACTION_MOVE x=-4.0 y=2.0
Events injected: 100
:Dropped: keys=0 pointers=0 trackballs=0 flips=0
## Network stats: elapsed time=1061ms (0ms mobile, 0ms wifi,
1061ms not connected)
// Monkey finished

En este ejemplo, la herramienta ha ejecutado la aplicacin identificada mediante el


paquete es.midominio.android.miapli, le ha enviado 100 eventos mostrando la progresin de
los resultados.

Sin una indicacin especfica por parte del usuario de las opciones correspondientes, la herramienta
Monkey se detendr cuando ocurra un problema tal como una excepcin no capturada, el bloqueo de la
aplicacin o un crash.

La herramienta Monkey permite reproducir de forma idntica y varias veces la misma prueba, la
misma secuencia de eventos, pasndole el mismo nmero (semilla) como entrada mediante la
opcin -s. Esto permite verificar la correccin de un error descubierto antes por la misma prueba.

206
12. Publicar una
aplicacin

207
Introduccin
Publicar una aplicacin consiste en ponerla a disposicin de terceros. Puede ser de carcter privado
como, por ejemplo, la publicacin de una aplicacin interna de una empresa para su uso en los
smartphones y tabletas tctiles de sus empleados. O puede ser de carcter pblico.

Esta aplicacin puede distribuirse de forma gratuita y, en este caso, todos los medios de distribucin
son buenos: sitios de venta de aplicaciones, como el Android Market de Google y lugares de venta
alternativos implementados por ciertos operadores, o incluso sitios web que proporcionan la descarga
directa del archivo apk.

La aplicacin tambin puede ponerse a la venta a una tarifa fija. Incluso en este caso, existe una gran
cantidad de puntos de venta para vender aplicaciones. Con el objetivo de protegerse frente a la copia
ilegal, la aplicacin tendr que usar algn sistema de proteccin (vase el captulo Funcionalidades
avanzadas - Proteger las aplicaciones de pago).

En este captulo detallaremos nicamente la publicacin en el Android Market, el lugar de venta de las
aplicaciones Android. El Android Market, del lado del cliente, es una aplicacin instalada por defecto en
la mayora de sistemas Android que permite al usuario descargar e instalar aplicaciones gratuitas y de
pago.

La publicacin de una aplicacin requiere una preparacin previa. Es necesario, como requisitos
previos:

Especificar un nmero de versin.

Agregar, llegado el caso, un Contrato de Licencia de Usuario Final o CLUF especfico a la


aplicacin. Este contrato detalla la responsabilidad de cada uno, el desarrollador y el usuario.
Permite, por tanto, proteger al desarrollador y sus derechos de autor. Este contrato se
muestra, por lo general, al usuario durante la primera ejecucin de la aplicacin. ste debe leer
y aceptar los trminos del contrato para poder continuar y utilizar la aplicacin.

Utilizar, llegado el caso, el sistema de licencia de aplicacin provisto por el Android Market. ste
permite, en el caso de las aplicaciones de pago, verificar si la aplicacin es una copia legal o no,
es decir, si realmente la ha comprado el usuario en el Android Market. Si no fuera el caso, el
desarrollador puede modificar el comportamiento de la aplicacin y, en particular, impedir su
uso al usuario.

Suprimir los logs de la aplicacin durante la compilacin de la versin final y, llegado el caso,
borrar, o poner a false si estuviera explcitamente informado a true,
el atributo android:debuggable de la etiqueta application especificada en el
manifiesto.

La documentacin oficial de Android indica que los mensajes que utilizan la clase Log se
compilan pero no se utilizan durante la ejecucin de la aplicacin final. Desgraciadamente, ste
no es el caso en el momento de escribir este libro, pero lo ser en breve. Para ms
informacin:http://code.google.com/p/android/issues/detail?id=14015

Probar la aplicacin final lo ms exhaustivamente posible (vase el captulo Trazas, depuracin


y pruebas - Pruebas unitarias y funcionales y Prueba del mono). Es muy importante probar la
aplicacin, de forma prioritaria, sobre dispositivos Android fsicos en condiciones de uso reales.
Por defecto, o para configuraciones de hardware especiales, el emulador ser una gran ayuda
complementaria.

Retomando algunas de estas etapas, descubriremos en primer lugar cmo especificar un nmero de
versin de aplicacin. A continuacin, detallaremos el procedimiento a seguir para proteger, llegado el
caso, las aplicaciones de pago utilizando el sistema de licencia de aplicacin provisto por el Android
Market. Compilaremos, a continuacin, la aplicacin en versin final y la firmaremos digitalmente. Para
terminar, publicaremos la aplicacin en el Android Market.

208
Preliminares
Antes de realizar el empaquetado final de la aplicacin, hay que verificar algunos puntos tales como la
versin de la aplicacin y los filtros configurados en la aplicacin que permiten ponerla a disposicin
solamente de aquellos dispositivos compatibles.

1. Versin de la aplicacin
Es costumbre, en informtica, adjuntar un nmero de versin a todo software. Este nmero de
versin debe ser un identificador nico, de otro modo no tendra mucho inters.

En Android, existen dos campos en el manifiesto que tienen como objetivo determinar este nmero
de versin:android:versionCode y android:versionName

a. android:versionCode

android:versionCode es un nmero entero. Este nmero no se muestra al usuario. Permite a


las dems aplicaciones y al Android Market poder comparar dos versiones de la aplicacin y saber
cul de las dos corresponde con la actualizacin, a saber, la que tenga un nmero de versin
mayor.

Es habitual comenzar la numeracin por 1 e incrementar el valor con cada actualizacin oficial de la
aplicacin, sea mayor o menor.

El sistema Android no verifica este valor, y deja va libre al desarrollador a la hora de


especificar este valor. Por ello, es responsabilidad del desarrollador velar por que la ltima
versin disponible posea, siempre, el valor mayor.

Sintaxis

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="entero" >
...
</manifest>

Ejemplo

<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="es.midominio.android.miapli"
android:versionCode="42" >
</manifest>

b. android:versionName

android:versionName es el nmero de versin que se muestra al usuario en el Android Market.


Es un elemento clave de carcter informativo que sirve tanto al desarrollador como al usuario.

Para el desarrollador, este nmero de versin permite especificar las versiones mayores, las
versiones menores, las versiones correctoras Permite a su vez, cuando la aplicacin se ha
publicado bajo diversas versiones, asociar bugs a tal o cual versin. Por ltimo, permite conversar
con los usuarios y conocer la versin que utilizan llegado el caso.

Para el usuario, el nmero de versin permite verificar que se est utilizando la ltima actualizacin
de la aplicacin. Le permite juzgar la conveniencia de una actualizacin segn la importancia del
cambio de versin, mayor o menor. Por ltimo, le permite tambin distinguir la versin en las
conversaciones con otros usuarios o con el desarrollador.
209
El desarrollador tiene libertad en cuanto a la sintaxis que quiera adoptar para la numeracin de las
versiones. El valor debe ser una cadena de caracteres.

Este nmero de versin debe ser nico, como mnimo, con cada publicacin de la aplicacin.
En caso contrario nadie sabr de qu variante de la aplicacin se trata.

Sintaxis

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionName="cadena de caracteres" >
...
</manifest>

Ejemplo

<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="es.midominio.android.miapli"
android:versionName="13.3.7" >
</manifest>

En este ejemplo, la sintaxis utilizada respeta la siguiente


convencin:nmero_mayor.nmero_menor.nmero__build.

2. Filtros para el mercado


Pensemos, por ejemplo, en una aplicacin de fotografa que, por definicin, requiere la presencia de
una cmara fotogrfica instalada en el dispositivo Android. Si esta aplicacin se le propusiera a un
usuario cuyo dispositivo Android no poseyera cmara, podra no funcionar correctamente.

En este caso, el usuario podra publicar su descontento en forma de comentario y de nota


mediocre, los cuales son pblicos en el Android Market y pueden ser consultados por los dems
usuarios antes de decidirse a la hora de instalar una aplicacin. Es, por tanto, muy importante no
permitir la instalacin de la aplicacin sobre un dispositivo incompatible.

Para evitar este tipo de disgustos, el Android Market filtra las aplicaciones para proponer solamente
aquellas que son compatibles con el dispositivo del usuario. Para hacer esto, se basa en la
informacin proporcionada por la aplicacin indicando las caractersticas de hardware y software de
las que depende la aplicacin.

Esta informacin se provee en el manifiesto en las etiquetas uses-feature y uses-


configuration.

Esta informacin tiene un carcter meramente informativo. El sistema Android no las utiliza, ni
siquiera para filtrar la instalacin de una aplicacin o para autorizar su uso en el dispositivo. Se
utilizan, principalmente, en programas especficos como el Android Market para filtrar los
dispositivos compatibles. No reemplazan, en ningn caso, a las solicitudes de permisos necesarios
para utilizar algn hardware o componente de software.

El Android Market utiliza tambin la etiqueta uses-sdk y


su atributo android:minSdkVersion, las etiquetas uses-library y la
etiqueta supports-screen para filtrar las aplicaciones compatibles con el dispositivo del
usuario.

210
a. uses-feature

La etiqueta uses-feature permite indicar las caractersticas de hardware y software de las que
depende la aplicacin. Se recomienda informarlas todas. Los valores son
de tipo android.hardware.* y android.software.*.

El atributo android:required permite indicar si la caracterstica correspondiente es obligatoria o


no. Por defecto, lo es. No obstante, puede ser interesante que la aplicacin gestione el caso en que
la caracterstica no est presente. Esto permite abrir la aplicacin a ms usuarios, en concreto a
aquellos que utilicen tabletas tctiles y que no dispongan, necesariamente, de las mismas
capacidades de hardware que, por ejemplo, los telfonos mviles.

El Android Market utiliza las declaraciones de permisos requeridos por la aplicacin para
verificar la lista de caractersticas requeridas obligatoriamente y completarla
automticamente. Por ejemplo, si una aplicacin solicita el permiso ACCESS_FINE_LOCATION,
el Android Market deducir
las caractersticas android.hardware.location yandroid.hardware.location.gps y,
por tanto, la presencia de un componente de hardware de localizacin GPS, con carcter
obligatorio.

Sintaxis

<uses-feature android:name="cadena de caracteres"


android:required="booleano"
... />

Ejemplo

<uses-feature android:name="android.hardware.location" />


<uses-feature android:name="android.hardware.wifi"
android:required="false" />

En el caso en que la caracterstica no se requiera obligatoriamente, la aplicacin debe probar


dinmicamente si el dispositivo la posee o no, de modo que pueda adaptar su comportamiento.
Para ello, es preciso usar el mtodo hasSystemFeature de la clase PackageManager cuya
instancia devuelve el mtodo getPackageManager. Este mtodo recibe como parmetro la
caracterstica que se quiere probar como cadena de caracteres y devuelve un valor booleano.

Sintaxis

public abstract boolean hasSystemFeature (String name)

Ejemplo

boolean gpsPresent = getPackageManager()


.hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);

b. uses-configuration

La etiqueta uses-configuration permite, a su vez, indicar las combinaciones de hardware


requeridas por la aplicacin. Cada uso de esta etiqueta corresponde con una combinacin de
hardware y software compatible.

Esta etiqueta incluye varios atributos, dos de los cuales describimos a continuacin. Por ejemplo,
elatributo android:reqHardKeyboard permite especificar si la aplicacin requiere un teclado
fsico o no. El atributo android:reqTouchScreen permite indicar si la aplicacin requiere una
pantalla tctil.

Por defecto, en ausencia de esta etiqueta, se considera que la aplicacin no requiere ni teclado
211
fsico, ni pantalla tctil.

Sintaxis

<uses-configuration android:reqHardKeyboard="booleano"
android:reqTouchScreen="[finger|notouch|stylus|undefined]"
/>

Ejemplo

<uses-configuration android:reqHardKeyboard="true" />

212
Firma digital de la aplicacin
Toda aplicacin Android debe estar firmada digitalmente para poder instalarse y ejecutarse sobre un
sistema Android, bien sea sobre un emulador o sobre un dispositivo Android. Esto permite, en
particular, identificar al desarrollador de la aplicacin.

La aplicacin se distribuye bajo la forma de un archivo con formato apk (Android Package).

El archivo .apk es un archivo de formato zip que contiene toda la aplicacin: los archivos Java
compilados como .class, los archivos de recursos y los archivos xml compilados con
formatowbxml (wap binary xml).

Durante la fase de desarrollo de una aplicacin, el desarrollador puede compilarla, instalarla y


ejecutarla numerosas veces. Esto supone firmar cada una de estas compilaciones, sin lo cual no es
posible instalarlas sobre el sistema Android. No obstante, hasta aqu, no se ha requerido ninguna
solicitud de firma digital y todas las compilaciones de las aplicaciones han podido instalarse sin
problema sobre el emulador o sobre un dispositivo Android. Lo que contradice los principios expuestos.

La razn es sencilla. Para no entorpecer el trabajo del desarrollador solicitndole firmar cada una de
las compilaciones, el proceso de firma difiere segn el modo de compilacin usado.

1. Compilacin en modo debug


Es el modo de compilacin usado por defecto en Eclipse con el plug-in ADT durante la fase de
desarrollo de la aplicacin. Durante la compilacin de una aplicacin en este modo, el plug-in ADT crea
automticamente un almacn de claves y crea una clave privada especficamente dedicada a la
depuracin (debug).

Esta clave se utiliza a continuacin para firmar automticamente el archivo apk, optimizarlo e
instalarlo sobre el sistema Android. Todas estas fases se realizan de forma totalmente transparente
para el desarrollador. Esto le permite, por tanto, no tener que preocuparse de este aspecto y
centrarse en el desarrollo de la aplicacin.

La aplicacin firmada de esta forma no puede distribuirse en el Android Market.

2. Compilacin en modo release


Una vez terminada la aplicacin, sta debe compilarse en modo release (final). Este modo, a
diferencia del modo debug (depuracin), no firma automticamente la aplicacin. Esto permite firmar
la aplicacin con la clave privada de la cuenta de desarrollador. La aplicacin firmada con esta clave
podr, a continuacin, ser publicada y distribuida a terceros.

La firma de una aplicacin final se realiza mediante un certificado digital auto-firmado cuya clave
privada pertenece nicamente al desarrollador de la aplicacin. Las etapas de creacin de esta clave
privada y del almacn de claves que las contiene hay que hacerlas slo la primera vez. Las
compilaciones siguientes podrn, en lo sucesivo, utilizar la clave creada anteriormente.

Es posible utilizar una nica clave por aplicacin y por versin. No obstante, se recomienda no utilizar
ms que una sola clave para firmar todas las aplicaciones con el fin de:

Permitir una actualizacin rpida y sencilla de la aplicacin a los usuarios existentes. Una
actualizacin de una misma aplicacin requiere obligatoriamente el uso de una misma clave,
sin lo cual la actualizacin se considerar como una nueva aplicacin completa, sin vnculo
alguno con la versin anterior. Y, dado que esta nueva aplicacin utiliza el mismo nombre de
paquete, no estar autorizada a instalarse.

Poder ejecutarlas en el mismo proceso de sistema si desean compartir los mismos datos
propios de la aplicacin como archivos de preferencias. Esta funcionalidad permite, por
213
ejemplo, instalar por separado la aplicacin principal, gratuita, y los mdulos suplementarios
independientes, de pago.

La clave utilizada deber, por tanto, tener una fecha de validez lo suficientemente extensa como para
permitir cubrir todas las aplicaciones y todas las duraciones de sus actualizaciones. La validez de esta
fecha se verificar nicamente en la fase de instalacin de la aplicacin sobre el sistema Android.

El desarrollador debe proteger y guardar el almacn y la clave secreta, as como las


contraseas asociadas, bajo el riesgo de que le roben su identidad. Sin ello, la seguridad de
las aplicaciones y de los datos de usuario asociados no estar garantizada.

a. Proteccin del cdigo

Proguard es una herramienta que permite, entre otros, reducir, optimizar y ofuscar el cdigo Java
compilado, sin modificar su funcionamiento. Esto permite, a la vez, optimizar el tamao del archivo
binario y hacer que la aplicacin sea ms complicada de estudiar.

Para ello, Proguard toma en cuenta nicamente el cdigo Java utilizado y deja de lado el cdigo no
utilizado. Renombra las clases, los mtodos y los campos utilizando nombres cortos sin significado
alguno. Por ltimo, optimiza el archivo binario generado.

De este modo, resulta muy difcil comprender el cdigo Java de un programa binario producido
mediante la herramienta Proguard que se haya podido descompilar.

El uso de la herramienta Proguard es opcional. Est indicada para aquellos desarrolladores que
quieran proteger el cdigo de sus aplicaciones y se recomienda encarecidamente cuando la
aplicacin utiliza la librera de verificacin de licencias para reforzar la seguridad de la clave del
dispositivo.

El sistema de compilacin de Android gestiona el uso de la herramienta de forma automtica y


transparente al desarrollador. La herramienta se utiliza solamente para las compilaciones en modo
release.

Por defecto, un proyecto Android no utiliza la herramienta Proguard. Para activar el uso de esta
herramienta, hay que agregar la propiedad proguard.config en
el archivo default.properties que se encuentra en la raz del proyecto. Esta propiedad debe
especificar la ruta y el nombre del archivo de configuracin destinado a la herramienta Proguard.
Existe un archivo de configuracin por defecto, proguard.cfg, que se provee en la raz del
proyecto y es apropiado para la mayora de los proyectos.

Sintaxis

proguard.config=/carpetas/proguard.cfg

Ejemplo

proguard.config=proguard.cfg

El ejemplo utiliza el archivo proguard.cfg que se provee por defecto.

Una vez ejecutada, la herramienta crea varios archivos en la carpeta proguard del proyecto. Esos
archivos son dump.txt, mapping.txt, seeds.txt y usage.txt. Permiten, en particular,
convertir las trazas de excepcin ofuscadas con los nombres de las clases, de los mtodos y de los
miembros originales.

Las compilaciones siguientes borrarn estos archivos. Se recomienda, por tanto,


salvaguardarlos, as como el proyecto completo, para cada aplicacin publicada.

214
Es posible que sea necesario parametrizar Proguard para que no modifique los nombres de
los mtodos especificados en los atributos android:onClick de los widgets con el
objetivo de mantener funcionales estas relaciones.

b. Firmar la aplicacin

He aqu cmo compilar y firmar una aplicacin en modo release en Eclipse:

En la vista Package Explorer de Eclipse, haga clic con el botn derecho sobre el proyecto y, a
continuacin, haga clic en Android Tools - Export Signed Application Package...

Aparece la ventana Export Android Application.

Firma de la aplicacin

Verifique que el proyecto est presente en el campo Project. Si no fuera el caso, haga clic en
el botn Browse... para seleccionar el proyecto.

Haga clic en el botn Next > y seleccione Create new keystore para solicitar la creacin de un
nuevo almacn de claves. Haga clic sobre el botn Browse... para especificar la ubicacin y el
nombre del archivo de almacn que se crear. Introduzca una contrasea con seis caracteres
como mnimo en el campo Password y confrmela introducindola de nuevo en el
campoConfirm.

Esta contrasea debe memorizarse bien pues se le solicitar con cada compilacin en modo
release. Se recomienda encarecidamente escoger una contrasea segura para proteger el
almacn.

215
Firma de la aplicacin

Haga clic en el botn Next.

La etapa siguiente consiste en crear la clave privada.

Informe la clave privada en el campo Alias. Indique una contrasea de seis caracteres como
mnimo en el campo Password y confrmela introducindola de nuevo en el campo Confirm.

Esta contrasea debe memorizarse bien pues se le solicitar con cada compilacin en modo
release. Por motivos de seguridad evidentes, se recomienda utilizar una contrasea distinta a
la del almacn de claves, y que a su vez sea segura.

Indique a continuacin el nmero de aos durante los cuales ser vlida esta clave, entre uno
y mil aos.

La publicacin en el Android Market requiere obligatoriamente una fecha de fin de validez


superior al 22 de octubre de 2033. Puesto que no cuesta nada, no dude en especificar una
fecha lo suficientemente lejana.

Finalice la etapa especificando la identidad del creador de la clave.

Esta informacin tienen un carcter meramente informativo limitado a la clave. No se utiliza


posteriormente, por ejemplo en el Android Market.

216
Firma de la aplicacin

Haga clic sobre el botn Next.

Introduzca la ubicacin y el nombre del archivo .apk que quiere crear y firmar con esta clave
privada.

Firma de la aplicacin

Haga clic en el botn Finish.


217
La clave se genera y almacena en el nuevo almacn. El proyecto se compila en modo release. El
archivo .apk se crea, a continuacin, en la ubicacin indicada anteriormente, optimizado y firmado
con la clave privada.

c. Instalar la aplicacin

Antes de distribuir el archivo .apk del modo release, se recomienda encarecidamente instalarlo y
ejecutarlo sobre el emulador o sobre un dispositivo Android para verificar que el archivo no se ha
corrompido y que la aplicacin funciona correctamente.

Para ello, es necesario suprimir previamente la aplicacin compilada en modo debug del sistema
Android puesto que las claves utilizadas por los archivos .apk, debug y release no son idnticas. El
sistema Android lo detectar y denegar la instalacin del nuevo archivo apk.

Desinstale la aplicacin compilada en modo debug del sistema Android. Bien utilizando el men
del sistema Android, o bien utilizando la herramienta adb por lnea de comandos
especificndole el paquete que desea borrar.

Sintaxis

adb uninstall [opciones] paquete

La opcin -k indica que no se borren los datos de la aplicacin y la cach de la aplicacin.

Ejemplo

$ adb uninstall es.midominio.android.miapli


Success

El sistema Android no contiene ms trazas de la aplicacin, y podemos instalar la aplicacin final.

Para ello, utilizaremos de nuevo la herramienta adb por lnea de comandos especificndole el
archivo apk a instalar.

Sintaxis

adb install [opciones] archivo.apk

La opcin -r es til para realizar una actualizacin. Permite conservar los datos ya instalados por la
versin anterior.

La opcin -s permite instalar la aplicacin sobre el almacenamiento externo del dispositivo en lugar
de sobre su almacenamiento interno.

Ejemplo

$ adb install /Users/seb/dev/MiApli.apk


475 KB/s (13404 bytes in 0.027s)
pkg: /data/local/tmp/MiApli.apk
Success

218
Publicacin de la aplicacin en el Android Market
Una vez compilada la aplicacin final, firmada con la clave privada de la cuenta del desarrollador, y
probada en un entorno real, puede ser publicada.

Existen numerosos lugares de venta donde puede publicarse la aplicacin. La que contiene ms
aplicaciones es el Android Market, gestionado por la compaa Google. Describiremos a continuacin
las distintas etapas para publicar una aplicacin en el Android Market.

1. Inscripcin
El Android Market es el lugar de venta de aplicaciones Android que provee la empresa Google. Este
lugar de venta permite, por un lado, a los desarrolladores publicar sus aplicaciones y, por otro lado,
a los usuarios descargarlas e instalarlas directamente sobre sus dispositivos Android. El usuario
puede instalar estas aplicaciones bien utilizando la aplicacin dedicada Android Market disponible
en su dispositivo, o bien surfeando en la web del Android Market disponible en la
direccinhttps://market.android.com/.

La apertura de una cuenta de desarrollador en el Android Market es de pago. Aquel desarrollador


que quiera publicar aplicaciones gratuitas o de pago debe abonar la tasa de $25 US una nica vez
durante su inscripcin.

El desarrollador que quiera publicar una aplicacin en el Android Market debe, en primer lugar, tener
una cuenta de Google.

La cuenta de Google puede ser una cuenta de Gmail o una cuenta de Google Apps.

Esta cuenta permite crear una cuenta de desarrollador utilizada para gestionar la publicacin de las
aplicaciones. La direccin de correo electrnico as como la dems informacin de la cuenta de
Google no se divulgarn a los usuarios de las aplicaciones. Tras cada publicacin de la aplicacin, es
posible especificar una direccin de correo electrnico especfica que se comunicar a los usuarios
para que puedan ponerse en contacto con el desarrollador.

Abra un navegador de Internet e introduzca la direccin: http://market.android.com/publish

Se producir una redireccin sobre la pgina de autenticacin de Google.

Introduzca la direccin de correo electrnico y la contrasea de la cuenta Google que se


utilizar para crear y administrar el acceso al Android Market. Si fuera necesario, puede crear
una cuenta de Google haciendo clic en Create an account now.

219
Inscripcin en el Android Market

Haga clic en el botn Sign in.

Primera etapa de creacin de la cuenta de desarrollador en el Android Market: la creacin del perfil
de desarrollador. Indique aqu los datos de la cuenta de desarrollador, teniendo en cuenta que
algunos de ellos se divulgarn a los usuarios. Es posible modificar posteriormente esta informacin.

Introduzca el nombre del desarrollador o el de la empresa desarrolladora. Este nombre se


mostrar al usuario de forma complementaria al nombre de cada una de las aplicaciones.

Introduzca la direccin de correo electrnico y de soporte indicada por defecto a los usuarios.

Introduzca, llegado el caso, la direccin del sitio de Internet relacionado con la actividad o las
aplicaciones de esta cuenta. Esta direccin es la direccin que se muestra por defecto a los
usuarios.

Introduzca un nmero de telfono que Google podr utilizar para ponerse en contacto con el
desarrollador en lo relativo a la publicacin de aplicaciones si esto fuera necesario. Este nmero
de telfono es privado y no se proporciona a terceros.

Por ltimo, marque, si fuera necesario, la opcin que permite recibir correos relativos al Android
Market.

220
Inscripcin en el Android Market

Haga clic en el botn Seguir.

221
Inscripcin en el Android Market

Segunda etapa: el pago de la tasa de inscripcin de la cuenta Android Market por importe de $25
US. La cuenta Android Market debe estar asociada obligatoriamente a una cuenta de Google
Checkout, el sistema de pago en lnea de Google. Es sobre esta cuenta donde Google abonar las
eventuales ganancias producto de la venta de sus aplicaciones. A continuacin estas ganancias se
le transferirn mensualmente a su cuenta bancaria.

Se recomienda leer bien las clusulas del Contrato relativo a la distribucin en Android Market, bien
de inmediato siguiendo el enlace de hipertexto indicado, o bien ms adelante durante el proceso de
inscripcin.

Este contrato podr consultarse en cualquier momento haciendo clic en el enlace de hipertexto
provisto a pie de pgina sobre cada una de las pginas del sitio.

Este contrato est traducido al castellano en la siguiente


direccin:http://www.android.com/es/developer-distribution-agreement.html

Haga clic en el botn Continuar.

222
Inscripcin en el Android Market

Rellene todos los campos para crear la cuenta de Google Checkout y proceder al pago de la
tasa de inscripcin. Observe que es obligatorio indicar el nmero de una tarjeta bancaria a la
cuenta de Google Checkout.

Siga las distintas etapas de pago para finalizar.

Una vez validado el pago, se le permite continuar con la inscripcin en el Android Market. A
continuacin, se muestra la pantalla de aceptacin del contrato relativo a la distribucin en el
Android Market.

223
Inscripcin en el Android Market

Lea y acepte las clusulas del contrato marcando la opcin y haciendo clic a continuacin en el
botn Acepto. Continuar .

Se muestra a continuacin la pantalla principal del Android Market, confirmando que la inscripcin se
ha realizado con xito.

224
Inscripcin en el Android Market

En lo sucesivo es posible publicar aplicaciones gratuitas.

Para publicar aplicaciones de pago o aplicaciones gratuitas con compras integradas o In-app Billing,
es preciso convertir la cuenta Google Checkout en cuenta mercantil.

Para ello, vaya al final de la pgina y haga clic en el enlace Configurar cuenta de comerciante y
siga las distintas etapas...

2. Publicacin
Si todava no lo ha hecho, conctese a su cuenta de desarrollador del Android Market.

225
Publicacin en el Android Market

Haga clic en el botn Subir aplicacin.

226
Publicacin en el Android Market

Es necesario proveer numerosa informacin relativa a la aplicacin antes de poder publicarla.


Mientras no se haya validado el formulario haciendo clic en el botn Publicar, ste se guarda en
modo borrador para poder completarlo ms tarde.

Una vez validado el formulario y publicada la aplicacin, es posible modificar la mayora de los
elementos del formulario. Es posible que exista cierto retardo a la hora de propagar las
modificaciones en el Android Market.

Veamos, a continuacin, la informacin solicitada.

Para cada uno de los archivos que se proveen en el formulario es preciso, una vez
seleccionado el archivo, hacer clic en el botn Importar correspondiente para cargarlo en el
servidor.

a. Archivo .apk

Archivo .apk de la versin preliminar de la aplicacin: archivo binario con formato apk de la
aplicacin compilada en modo release.

Recuerde, el nombre del paquete utilizado por la aplicacin es el identificador nico de la


aplicacin en el Android Market. Una vez cargado, este nombre puede no modificarse ni
reutilizarse para otra aplicacin.

b. Recursos

Esta seccin permite proveer los elementos grficos que se utilizarn para promocionar la
aplicacin en el Android Market y, eventualmente, otros soportes.

Capturas de pantalla: capturas de pantalla de la aplicacin respetando los formatos indicados.


Estas capturas de pantalla se mostrarn al usuario cuando consulte la ficha de la aplicacin en el
Android Market. Se requiere, como mnimo, adjuntar dos copias de pantalla. Es posible agregar
seis ms si fuera necesario.

Ms que la descripcin de la aplicacin detallada ms adelante, las capturas de pantalla son,


sin duda, el mejor medio de hacer que el usuario desee descargar la aplicacin. Es preciso,
por tanto, seleccionarlas cuidadosamente.

Icono de aplicacin de alta resolucin: icono de la aplicacin en alta resolucin de 512 x 512
pxeles. Este icono se utiliza para promover la aplicacin en el Android Market. Debe tener una
apariencia relacionada con la de la aplicacin.

Grfico promocional, Grfico de funciones y Enlace de vdeo promocional: imgenes y vdeos


opcionales utilizados en el Android Market para promover la aplicacin. Esto afecta, por lo general,
a las aplicaciones ms populares.

Encontrar ms informacin en la
direccinhttps://market.android.com/support/bin/answer.py?answer=1078870. Si la pgina
no se muestra en castellano, es posible cambiar el idioma en la parte inferior de la pgina.

Marketing desactivado: si la opcin est marcada, la aplicacin se promocionar nicamente en el


227
Android Market y otros sitios gestionados por Google. Si la opcin est desmarcada, la aplicacin
podr promocionarse en cualquier otro soporte tales como anuncios publicitarios en TV, carteles
Las modificaciones posteriores de esta opcin se tendrn en cuenta con un retardo mnimo de
sesenta das.

c. Informacin sobre la aplicacin

Esta seccin permite describir la aplicacin en distintos idiomas, clasificarla e indicar,


eventualmente, un precio. Todos estos elementos pueden modificarse posteriormente.

Idioma: por defecto, las reseas de la aplicacin deben proveerse, como mnimo, en ingls.
Haciendo clic sobre agregar idioma es posible agregar otras lenguas complementarias.

De forma similar a la traduccin de la aplicacin, se recomienda encarecidamente traducir la


descripcin de la aplicacin en la mayora de idiomas posibles; y, como mnimo, en las mismas
lenguas en las que est soportada la aplicacin.

Ttulo: nombre de la aplicacin utilizado en el Android Market. Dos aplicaciones distintas no pueden
tener el mismo nombre. Es la ley del primero en llegar la que se lleva el nombre. Por el contrario,
es posible especificar un nombre distinto en cada idioma.

Descripcin: texto que describe la aplicacin. El usuario podr descargar la aplicacin. Es preciso,
por tanto, tratar de hacerla atractiva aqu.

Cambios recientes: texto que describe los cambios que aporta la ltima versin de la aplicacin
tales como nuevas funcionalidades, correcciones de bugs

Texto promocional: texto que figura junto a los elementos grficos promocionales Grfico
promocional vistos anteriormente.

Cuando el usuario realiza una bsqueda de texto en el Android Market, ste utiliza los datos
de los campos ttulo y descripcin para componer la lista de aplicaciones correspondientes. Es
preciso, por tanto, pensar bien los trminos empleados.

Tipo de aplicacin y Categora: toda aplicacin debe clasificarse en una categora. Esto permite al
usuario poder consultar las aplicaciones disponibles en cada una de las categoras.

La descripcin detallada de cada una de las categoras est disponible en la


direccinhttp://market.android.com/support/bin/answer.py?answer=113475.

d. Opciones de publicacin

Proteccin contra copias: hace referencia a un antiguo mtodo de proteccin de las aplicaciones
contra la copia ilegal. ste ha sido reemplazado por el nuevo mtodo LVL estudiado ms adelante.
Es preferible utilizar el mtodo LVL y dejar esta opcin Desactivada.

Categora de contenido: La aplicacin debe clasificarse segn su contenido y su uso. Existen


cuatro niveles. Se muestran a continuacin, en el orden del ms restrictivo al ms permisivo:

Nivel 1 - Estricto (Nivel de madurez alto)


Nivel 2 - Moderado (Nivel de madurez medio)
Nivel 3 - Amplio (Nivel de madurez bajo)
Todos (Para todos los pblicos).
228
El nivel debe escogerse teniendo en cuenta las referencias al alcohol, al tabaco, a las drogas, a los
juegos de azar y apuestas, a la incitacin al odio...

Es responsabilidad del desarrollador escoger la categora correspondiente. Por ejemplo, una


aplicacin que utilice los datos de localizacin del usuario requerir un nivel superior o igual al
nivel 3. Para ms informacin acerca de los criterios y de las clasificaciones correspondientes,
dirjase a la direccin http://www.google.com/support/androidmarket/bin/answer.py?
answer=188189

Pas/Tarifas: la aplicacin puede publicarse de forma gratuita o de pago. El desarrollador puede


seleccionar el pas donde se distribuir la aplicacin. En el caso de una aplicacin de pago, y en la
medida de lo posible, el precio de la aplicacin estar indicado en la divisa local del usuario. El
desarrollador puede bien fijar libremente la tarifa local de la aplicacin, o bien utilizar el
botnConversin automtica para dejar que el Android Market realice las conversiones
automticamente segn el cambio de divisa actual. Esta conversin automtica se produce con un
simple clic en este botn. Una vez definida, cada tarifa se fija hasta la prxima modificacin por
parte del desarrollador.

Si la aplicacin se publica de forma gratuita, jams podr ser de pago en un futuro. En este
caso, ser preciso volver a publicarla como si fuera una nueva aplicacin. Esto implica que la
aplicacin debe cambiar su nombre de paquete, su publicacin utilizar un nombre distinto Es
preciso, por tanto, definir previamente la estrategia comercial que se quiere utilizar.

En el momento de fijar la tarifa, el desarrollador debe tener en cuenta que el Android Market
deduce un 30% del coste sobre cada una de las transacciones. De este modo, para una
aplicacin con una tarifa de 10 euros, el desarrollador recibir 7 euros brutos de los que tendr
que descontar a continuacin eventuales impuestos y tasas hasta obtener la ganancia neta.

Dispositivos compatibles: muestra las funcionalidades requeridas por la aplicacin y especificadas


en su manifiesto, como se ha visto al principio de este captulo. Se muestra el nmero de
dispositivos que disponen de estas funcionalidades. Haciendo clic sobre el enlace Mostrar los
dispositivos permite mostrar la lista de dispositivos compatibles. Si fuera necesario, es posible
excluir alguno de forma manual. La aplicacin se publicar nicamente para aquellos dispositivos
que formen parte de la lista final.

e. Coordenadas

Esta parte est relacionada con la informacin de contacto que podrn utilizar los usuarios del
Android Market para ponerse en contacto con el programador. Es informacin pblica. Es preciso
proveer al menos un tipo de contacto de entre los siguientes:

Sitio Web: direccin del sitio de Internet del desarrollador o, mejor todava, de la aplicacin, si
existe.

Direccin e-mail: direccin de correo electrnico en la que los usuarios pueden contactar con el
desarrollador.

Telfono: nmero de telfono en el que los usuarios pueden contactar con el desarrollador.

f. Aceptar

Los trminos del Reglamento del programa Android Market deben aceptarse. Este reglamento define,
entre otros, la poltica de contenidos que debe respetar la aplicacin. Este reglamento est
disponible en castellano en la direccin http://www.android.com/es/developer-content-policy.html.

Por otro lado, es necesario confirmar que la aplicacin respeta las leyes de exportacin
229
americanas, en especial si la aplicacin hace uso directamente o no de la encriptacin.

Una vez completado el formulario, haga clic en el botn Publicar para publicar inmediatamente
la aplicacin en el Android Market o en el botn Guardar para guardar el formulario en el
estado de borrador y retomarlo posteriormente.

La publicacin de la aplicacin en el Android Market es automtica e inmediata. No existe un


control previo de la aplicacin. No obstante, es posible que exista un control a posteriori en
cualquier momento, llevado a cabo por la empresa Google, que le obligue a retirar la aplicacin
del Android Market, lo cual ocurre rara vez y slo afecta a aplicaciones con algn litigio...

3. Y despus?
Tras la publicacin, la aplicacin se agrega a la lista de aplicaciones de la cuenta del desarrollador.
En lo sucesivo, puede gestionar cada una de sus aplicaciones. Para ello, basta con hacer clic en el
nombre de la aplicacin para mostrar su pgina de publicacin. Es posible modificar todos los
campos, excepto el archivo apk.

Para actualizar el binario de la aplicacin, es decir el archivo .apk, hay que hacer clic en el
enlaceImportar la actualizacin que figura en la pgina de publicacin de la aplicacin y cargar el
nuevo archivo binario.

Recuerde, el atributo android:versionCode del manifiesto debe tener un valor superior al


del binario publicado. Y, evidentemente, el nombre del paquete de la aplicacin no deben haber
cambiado.

El botn Anular la publicacin permite retirar la aplicacin de la publicacin y, por tanto, del Android
Market. La aplicacin y su ficha de publicacin se borrarn de la cuenta del desarrollador de forma
que pueda publicarlas de nuevo.

Para cada aplicacin de la lista figura su nombre, su versin, su categora, su nota media reseada
por los usuarios, el nmero total de descargas y el nmero de instalaciones todava efectivas, el
precio y el estado de la publicacin.

Es posible consultar ms informacin haciendo clic en el enlace correspondiente:

Comentarios: enlace que permite consultar los detalles de las notas asignadas por los
usuarios y sus comentarios.

Estadsticas: enlace que permite consultar diversas estadsticas correspondientes a las


instalaciones de la aplicacin. El primer grfico representa el histrico del nmero de
instalaciones acumuladas desde la fecha de publicacin de la aplicacin o, como mximo,
despus de mediados de diciembre de 2010. Los siguientes grficos indican los repartos de
las instalaciones segn:

La versin de los sistemas Android.

El modelo del dispositivo.

El pas del usuario.

El idioma del sistema Android y, por tanto, del usuario.

De forma complementaria figuran, a su vez, los datos correspondientes al conjunto de las


aplicaciones del Android Market repartidas segn los mismos criterios, salvo por el modelo del
dispositivo dado que se trata de un dato sensible.

Productos integrados con la aplicacin: enlace que permite gestionar las ventas integradas
con la aplicacin.
230
Errores: enlace que permite consultar los informes de bloqueos o de crash de la aplicacin
reenviados por los usuarios. Este enlace se muestra solamente si existe al menos un informe.
Cada uno de estos informes proporciona el nombre de la excepcin elevada, el mtodo o la
excepcin que se ha producido, el modelo del dispositivo y la pila de llamadas a los mtodos
que han provocado las excepciones. El usuario puede, tambin, incluir un mensaje en el
informe. Los informes idnticos se agrupan en uno solo.

231
13. Mapas y
localizacin
geogrfica

232
Introduccin
Desde su aparicin, los smartphones han democratizado el uso de la localizacin geogrfica gracias a
la integracin de receptores GPS o sistemas equivalentes en la mayora de ellos.

Otro uso comn en las aplicaciones es mostrar mapas que permitan al usuario situar rpidamente los
lugares, los eventos, las tiendas Explotando la funcionalidades de localizacin geogrfica, es posible
geolocalizarse, es decir, localizarse sobre un plano o mapa.

Se trata de dos funcionalidades que detallaremos en este captulo.

233
Localizacin geogrfica
La localizacin geogrfica, o geolocalizacin, permite localizar al dispositivo Android en un instante
determinado de forma ms o menos precisa proporcionando mltiple informacin y, en particular, sus
coordenadas geogrficas: la latitud y la longitud.

Cualquier aplicacin puede, en lo sucesivo, utilizar la geolocalizacin para localizar al dispositivo y, en


consecuencia, al usuario.

Para respetar la privacidad del usuario, es conveniente prevenir al usuario de que la aplicacin
utilizar sus coordenadas geogrficas. Dejarle la posibilidad de activar y desactivar el sistema de
geolocalizacin en cualquier momento, por ejemplo, mediante una casilla de opcin a marcar, es
todava mejor. Por defecto, esta casilla tendr que estar desactivada para que el propio usuario la
active dando su acuerdo de forma explcita para ser localizado.

Segn el material que equipe al dispositivo Android, el sistema puede apoyarse sobre uno o varios
dispositivos que permiten proveer las coordenadas de localizacin. Este material puede ser un receptor
GPS, la red de telefona mvil asociada, o las redes Wi-Fi circundantes.

Cada uno de estos dispositivos posee sus ventajas y sus desventajas. Por un lado, el sistema GPS
permite obtener coordenadas precisas a cambio de un consumo de batera importante, de un entorno
exterior y de un retardo en la localizacin que puede ser superior al de otros dispositivos.

Por otro lado, el sistema Android utilizar menos batera para captar la red de telefona mvil y las
redes Wi-Fi. Lo har ms rpidamente, incluso en el interior.

El sistema de geolocalizacin de Android permite adaptarse automticamente al material provisto por el


dispositivo y activado por el usuario. Por ello, el desarrollador no debe suponer ningn dispositivo a la
hora de proveer el acceso a la aplicacin salvo en casos particulares. La aplicacin debe adaptarse
automticamente a todos los entornos de hardware.

Por ello, no debe precisarse qu sistema se quiere utilizar sino de qu nivel de precisin desea
disponer. El sistema determinar a continuacin de forma automtica sobre qu componentes de
hardware apoyarse para responder a esta demanda.

1. Permisos
Para poder utilizar el sistema de geolocalizacin, la primera etapa consiste en dotar a la aplicacin del
derecho de localizar el dispositivo. Para ello, es preciso agregar el o los permisos correspondientes en
el manifiesto. Existen dos permisos que permiten esto segn el nivel de precisin deseado.

El permiso android.permission.ACCESS_COARSE_LOCATION solicita permiso para utilizar los


componentes de localizacin que tengan una precisin menor, como por ejemplo la combinacin de
redes de telefona mvil y Wi-Fi.

El permiso android.permission.ACCESS_FINE_LOCATION solicita permiso para utilizar los


componentes de localizacin ms precisos, como el GPS, adems de aquellos de menor precisin.
Este permiso incluye de forma implcita al
permiso android.permission.ACCESS_COARSE_LOCATION.

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


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

2. Gestor de localizacin
234
Android proporciona la clase LocationManager que permite gestionar el servicio del sistema de
geolocalizacin. La instancia de este servicio, el gestor, se recupera utilizando el
mtodo getSystemService y pasndole como parmetro el nombre del servicio deseado. El
nombre del servicio de geolocalizacin est contenido en una
constante: Context.LOCATION_SERVICE.

Sintaxis

public abstract Object getSystemService (String name)

Ejemplo

LocationManager locManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);

En funcin de los permisos de localizacin solicitados en el manifiesto, este gestor de accesos tiene
ms o menos dispositivos de localizacin.

Algunos de estos mtodos solicitan proveer un conjunto de criterios que les sirve para determinar
qu dispositivo de localizacin entre los disponibles responde mejor a estos criterios. Estos criterios
se deben proporcionar en un objeto de tipo Criteria creado utilizando su constructor por defecto.

Sintaxis

public Criteria ()

Ejemplo

Criteria criterios = new Criteria();


criterios.setAccuracy(Criteria.ACCURACY_HIGH);

Otros mtodos permiten indicar explcitamente el nombre del dispositivo que se quiere utilizar, en
forma de cadena de caracteres. Existen varias constantes que sirven para designar a estos
dispositivos:

GPS_PROVIDER: constante que contiene el nombre del sistema de GPS. Este dispositivo
requiere el permiso android.permission.ACCESS_FINE_LOCATION.

NETWORK_PROVIDER: constante que contiene el nombre del sistema de redes de telefona


mvil y Wi-Fi. Este dispositivo requiere el
permiso android.permission.ACCESS_COARSE_LOCATION.

PASSIVE_PROVIDER: constante que designa el sistema que permite recuperar las


actualizaciones de la localizacin solicitada por las dems aplicaciones. Esto permite evitar
solicitudes de localizacin superfluas y mutualizar aquellas recibidas por las aplicaciones. Este
dispositivo, si bien requiere el
permiso android.permission.ACCESS_FINE_LOCATION, no certifica que los valores
de localizacin devueltos tengan una precisin fina.

Observe que una aplicacin puede utilizar uno o varios dispositivos de localizacin, de forma
simultnea o no.

3. Recuperar los datos de localizacin


Es posible adoptar muchas estrategias para recuperar la localizacin del usuario. Es posible que
ciertas aplicaciones requieran localizar al usuario una nica vez; otras a intervalos regulares. Ciertas
aplicaciones no requieren una gran precisin, otras, por el contrario, requieren una precisin muy fina.

235
El desarrollador deber reflexionar sobre la mejor estrategia que se quiere implementar teniendo en
cuenta no slo las necesidades de la aplicacin sino tambin las restricciones de hardware, tratando
de reducir al mximo el consumo energtico.

Un objeto de tipo Location representa una localizacin en un momento dado. Este objeto puede
contener mucha informacin como por ejemplo la latitud, la longitud, la altitud, la precisin de la
posicin, la velocidad instantnea, el dispositivo que la ha enviado

La clase Location proporciona a su vez mtodos utilitarios, en concreto


el mtodo distanceBetween que permite calcular fcilmente la distancia entre dos puntos
GPS o incluso el mtodo distanceTo para calcular la distancia entre el objeto de
tipo Location y otro objeto del mismo tipo.

Preste atencin, una localizacin ms actual no tiene por qu ser ms precisa que otra ms
antigua. Hay que comparar, por tanto, los distintos objetos de tipo Location recibidos para
guardar nicamente la localizacin ms precisa aunque sea ms antigua...

Es posible recuperar la localizacin del usuario desde la cach o buscndola una nica vez de forma
regular.

Para estas dos tcnicas, es preciso indicar la accin a realizar cuando la localizacin se haya
encontrado, lo que puede llevar cierto tiempo, o tras eventos que afecten al dispositivo, como por
ejemplo su activacin o desactivacin. Esto puede realizarse de dos formas.

La primera forma consiste en utilizar un objeto de tipo PendingIntent.


Los datos de localizacin con forma de un objeto de tipo Location se agregarn a los
datos Extra del intent cuando sean conocidos. La clave del valor extra
correspondiente es KEY_LOCATION_CHANGED.
Las claves KEY_PROVIDER_ENABLED y KEY_STATUS_CHANGED seenvan cuando ocurren
respectivamente los eventos de activacin o de desactivacin y se ha modificado el estado del
dispositivo correspondiente.

Ejemplo

Location loc = (Location) intent.getParcelableExtra(


android.location.LocationManager.KEY_LOCATION_CHANGED);

La segunda forma consiste en implementar la interfaz LocationListener y proporcionar o no un


objeto de tipo Looper que permita invocar a los mtodos de la interfaz sobre un thread distinto al
thread por defecto, es decir el thread principal. La interfaz LocationListener incluye cuatro
mtodos que se invocan cuando se encuentra una nueva localizacin, cuando el usuario ha activado
el dispositivo, cuando lo ha desactivado o cundo ha cambiado el estado del dispositivo. Estos
mtodos son, respectivamente: onLocation-
Changed, onProviderDisabled,onProviderEnabled y onStatus-Changed.
Sintaxis

public abstract void onLocationChanged (Location location)


public abstract void onProviderDisabled (String provider)
public abstract void onProviderEnabled (String provider)
public abstract void onStatusChanged (String provider, int status,
Bundle extras)

Ejemplo

LocationListener locListener = new LocationListener() {


public void onLocationChanged(Location location) {
236
Log.d(TAG, "Localizacin recibida: lat="+
location.getLatitude()+" / lon="+location.getLongitude());
}

public void onProviderDisabled(String provider) {


Log.d(TAG, "Dispositivo desactivado: "+provider);
}
public void onProviderEnabled(String provider) {
Log.d(TAG, "Dispositivo activado: "+provider);
}

public void onStatusChanged(String provider, int status,


Bundle extras) {
StringBuffer buf = new StringBuffer(
"Estado modificado: dispositivo="+provider+" / estado=");
switch (status) {
case LocationProvider.AVAILABLE:
buf.append("En servicio");
Integer t = (Integer)extras.get("satellites");
if (t != null)
buf.append("(satellites="+t+")");
break;
case LocationProvider.OUT_OF_SERVICE:
buf.append("Fuera de servicio");
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
buf.append("Temporalmente no disponible");
break;
default:
break;
}
Log.d(TAG, buf.toString());
}
};

a. En cach

El gestor de localizacin provee el mtodo getLastKnownLocation que permite recuperar


inmediatamente, desde una cach, la ltima localizacin enviada por el dispositivo especificado
como parmetro. Este mtodo devuelve un objeto de tipo Location o null si no hay disponible
ninguna localizacin para este dispositivo. Este mtodo tiene la ventaja de ser inmediato dado que
no activa el dispositivo. Es un mtodo simple y poco costoso de obtener una localizacin temporal
mientras se espera a recibir otra ms precisa. En contrapartida, la localizacin devuelta puede ser
muy antigua, poco precisa

Sintaxis

public Location getLastKnownLocation (String provider)

Ejemplo

Location loc =
locManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

b. Una sola vez

Ciertas aplicaciones slo necesitan obtener la localizacin del usuario una nica vez, por ejemplo
para geolocalizar un comentario del usuario. Estas aplicaciones pueden utilizar el
mtodo getLastKnowLocation que hemos visto anteriormente, pero esta ltima posicin puede
ser demasiado antigua, o muy poco precisa...

En este caso, desde Android 2.3 (API 9), es posible utilizar el mtodo requestSingleUpdate. El
retardo en la obtencin del dato de localizacin depende de numerosos factores y puede llevar
237
cierto tiempo.

Para versiones anteriores a Android 2.3 (API 9), el desarrollador puede utilizar
actualizaciones regulares, descritas ms adelante, y detener este procedimiento una vez
haya ocurrido la primera recepcin de los datos de localizacin.

Segn la firma usada, el mtodo requestSingleUpdate recibe como parmetro o bien


directamente el nombre del dispositivo de localizacin que se quiere utilizar o bien un objeto de
tipo Criteria que permite identificar a este dispositivo. Recibe tambin como parmetros un
objeto que implementa la interfaz PendingIntent o un objeto de tipo LocationListener y el
thread asociado segn la solucin escogida para recuperar los datos de localizacin.

Sintaxis

public void requestSingleUpdate (String provider,


PendingIntent intent)
public void requestSingleUpdate (String provider,
LocationListener listener, Looper looper)
public void requestSingleUpdate (Criteria criteria,
PendingIntent intent)
public void requestSingleUpdate (Criteria criteria,
LocationListener listener, Looper looper)

Ejemplo

locManager.requestSingleUpdate(criterios, locListener, null);


locManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,
pendingIntent);

c. Peridicamente

Ciertas aplicaciones requieren obtener peridicamente la localizacin del usuario como, por ejemplo,
una aplicacin que registre el recorrido efectuado por el usuario. O incluso, requieren obtener varios
datos de localizacin para guardar, nicamente, el ms preciso.

En este caso, el desarrollador puede utilizar uno de los mtodos request-LocationUpdates.


Estos mtodos permiten obtener varios datos de localizacin. Reciben como parmetros
un entero minTime que permite especificar el retardo mnimo, en milisegundos, entre dos
notificaciones de localizacin as como un nmero de coma flotante minDistance que permite
especificar la distancia mnima, en metros, que debe haberse recorrido entre dos notificaciones. La
combinacin de estos dos valores permite definir el periodo de actualizacin de los datos de
localizacin.

Si se informan los parmetros minTime y minDistance a 0, es posible obtener


actualizaciones de datos de localizacin lo ms a menudo posible. En contrapartida, la batera
del dispositivo puede consumirse muy rpido. Por ello, para ahorrar batera, se recomienda
especificar un valor de minTime lo ms grande posible, no inferior a los 60 segundos, incluso
aunque de forma interna, el refresco de los datos de localizacin pueda tener lugar con mayor o
menor frecuencia que el valor especificado.

De forma similar a los mtodos requestSingleUpdate, segn la firma utilizada, el


mtodo requestLocationUpdates recibe como parmetro o bien directamente el nombre del
dispositivo de localizacin que se quiere utilizar o bien un objeto de tipo Criteria que permite
identificar a este dispositivo. Recibe, tambin, como parmetros un objeto de
tipo PendingIntent o un objeto que implementa la interfaz LocationListener y el thread
asociado segn la solucin escogida para recuperar los datos de localizacin.

Sintaxis
238
public void requestLocationUpdates (String provider, long minTime,
float minDistance, PendingIntent intent)
public void requestLocationUpdates (String provider, long minTime,
float minDistance, LocationListener listener, Looper looper)
public void requestLocationUpdates (String provider, long minTime,
float minDistance, LocationListener listener)
public void requestLocationUpdates (long minTime, float minDistance,
Criteria criteria, PendingIntent intent)
public void requestLocationUpdates (long minTime, float minDistance,
Criteria criteria, LocationListener listener, Looper looper)

Ejemplo

locManager.requestLocationUpdates(0, 0, criterios, locListener,


null);
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, pendingIntent);

d. Detener las actualizaciones

Para detener la recuperacin de los datos de localizacin realizada mediante los


mtodos requestSingleUpdate y requestLocationUpdates, es preciso utilizar uno de los
dosmtodos removeUpdates pasando como parmetro la accin concreta, es decir, o bien el
objeto de tipo PendingIntent, o bien el objeto que implementa la
interfaz LocationListener.

Sintaxis

public void removeUpdates (PendingIntent intent)


public void removeUpdates (LocationListener listener)

Ejemplo

locManager.removeUpdates(locListener);

239
Google Maps
Otro uso corriente de las aplicaciones es mostrar mapas geogrficos que permiten al usuario situar
rpidamente lugares, eventos, tiendas

Por defecto, el sistema Android no incluye tales posibilidades. La empresa Google proporciona su
biblioteca externa de cartografa com.google.android.maps para agregar tales funcionalidades al
sistema bsico.

La mayor parte de los dispositivos Android disponen de sistemas que incluyen esta biblioteca. Por ello,
permiten a las aplicaciones de terceros mostrar e incorporar tales mapas geogrficos, desde Android
1.5 (API 3).

Si bien esta biblioteca no forma parte de la plataforma Android bsica, s es, a da de hoy, una
funcionalidad que se utiliza de forma tan comn en tantas aplicaciones que resulta evidente
abordar este tema.

1. Implementacin
Adems de la instalacin de la biblioteca Maps, la aplicacin debe declarar el uso de esta biblioteca y
el desarrollador debe obtener autorizacin de uso de esta librera de la empresa Google. Estos temas
se abordan en esta seccin.

a. Instalacin del SDK

Como ya se ha indicado ms arriba, la plataforma Android no incluye por defecto la biblioteca Maps.

Una aplicacin que quiera tener acceso a esta biblioteca debe estar compilada con el SDK que
contenga esta biblioteca. Para ello, es preciso utilizar los mdulos complementarios provistos por
Google que contienen las API de Google correspondientes.

Ejecute la herramienta Android SDK and AVD Manager.

En la lista de la izquierda, seleccione Available Packages y, a continuacin, en la lista de la


derecha, despliegue la carpeta Third party Add-ons y seleccione uno de los mdulos Google
APIs by Google Inc. correspondientes a la versin del SDK Android deseado.

Haga clic en el botn Install Selected.

Finalice la instalacin como hemos visto (vase el captulo El universo Android - Entorno de
desarrollo).

Si se quieren realizar las pruebas en un emulador, hay que tener en cuenta que la imagen de
sistema utilizada por AVD est acompaada por los mdulos complementarios de Google.

b. Configuracin de la aplicacin

Para poder utilizar la biblioteca externa Maps, la aplicacin debe declarar este uso con
la etiqueta uses-library que debe indicarse dentro de la etiqueta application del
manifiesto.

Sintaxis

<uses-library android:name="com.google.android.maps" />

La etiqueta uses-library permite compilar la aplicacin utilizando la biblioteca


240
especificada. Adems, permite asegurar que slo se autoriza la instalacin de esta aplicacin en
sistemas Android que dispongan de esta librera.

Dado que la biblioteca se comunica con un servidor para descargar los mapas geogrficos, la
aplicacin debe incluir la autorizacin para conectarse a Internet. Para ello, hay que agregar el
permiso android.permission.Internet en el manifiesto.

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<manifest ...>
<application ...>
<uses-library android:name="com.google.android.maps" />
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

c. Obtener una clave de uso

Todo usuario del servicio Google Maps debe proveer una clave de uso que permita al servicio
identificarlo.

En concreto, cada una de las vistas MapView de una aplicacin deben proveer esta clave de uso.
Las vistas MapView se describen ms adelante.

Sin esta clave, la aplicacin funcionar correctamente salvo por el detalle de que los mapas
geogrficos no se visualizarn. Las vistas correspondientes estarn vacas o, para ser ms exactos,
contendrn una malla vaca.

Esta clave es gratuita y dependiente del certificado utilizado para firmar la aplicacin. Esto significa
que una nica clave sirve para todas las vistas MapView de una misma aplicacin y, por extensin,
para varias aplicaciones firmadas con el mismo certificado.

Por el contrario, la clave ser diferente para cada uno de los certificados utilizados para firmar la
aplicacin. En concreto, habr una clave para la compilacin en modo debug y otra para la
compilacin en modo release.

Habr que tener presente reemplazar la clave de debug por la clave del modo release en el
cdigo fuente del proyecto antes de realizar la compilacin en modo release que producir la
aplicacin que se publicar.

La generacin de la clave utiliza la firma MD5 del certificado de firma.

Para obtener una clave para el modo debug, hay que recuperar el valor de la firma MD5 del
certificado correspondiente.

El archivo correspondiente al certificado de debug se llama debug.keystore. Est almacenado


en la carpeta .android que figura en la raz de la carpeta del usuario.

Es posible encontrar la ubicacin del archivo buscndola en Preferences de Eclipse, y a


continuacin Android y Build.

La generacin de la firma MD5 del certificado se realiza mediante la herramienta keytool.


Sintaxis

keytool -list -alias nombre_clave -keystore nombre_tienda.keystore

el modo debug son: android.


Las contraseas de la tienda y de la clave para241
Ejemplo

$ keytool -list -alias androiddebugkey -keystore


/Users/seb/.android/debug.keystore
Introduzca la contrasea del Keystore:
androiddebugkey, 31 mayo 2010, PrivateKeyEntry,
Firma del certificado (MD5):
03:DF:AC:D5:10:7A:76:8A:0D:C4:93:B4:6B:07:86:10

Dirjase a continuacin a la direccin: http://code.google.com/android/maps-api-signup.html

Lea los trminos del Servicio Android Maps API que describen, en especial, las condiciones y
restricciones de uso del servicio. Valide la opcin I have read and agree with the terms and
conditions.

Copie y pegue la firma MD5 del certificado en el campo My certificates MD5 fingerprint.

Inscripcin al servicio Android Maps API

Haga clic en el botn Generate API Key.

Se le solicitar conectarse a la cuenta de Google si no lo hubiera hecho ya.

Aparece la siguiente pantalla, que muestra la clave nica generada, asociada a la firma MD5
proporcionada.
242
Generacin de la clave API Google Maps

Guarde la pgina web o, como mnimo, la clave, anotando a qu certificado est asociada. Si
fuera necesario, es posible generar la misma clave varias veces.

El proceso de generacin de la clave para el modo release es completamente idntico al que


se ha descrito aqu para el modo debug. Hay que pasar por las mismas etapas utilizando el
archivo del certificado en modo release en lugar del que se ha utilizado aqu en modo debug.

2. Uso
La visualizacin de un mapa geogrfico se realiza desde una vista dedicada representada por la
clase MapView.

a. Declaracin de la vista

La declaracin de esta vista puede hacerse en un archivo layout. La etiqueta que debe utilizar es el
nombre de la clase MapView: com.google.android.maps.MapView. Deben informarse
varios atributos:

El atributo android:clickable permite indicar si el usuario puede interactuar con la


vista. Para esta vista, esto equivale a indicar si el usuario est autorizado o no a navegar
por el mapa.

El atributo android:apiKey, especfico de esta vista, permite indicar la clave de uso que
se proveer al servidor para autorizar la descarga de mapas.

Sintaxis

<com.google.android.maps.MapView
243
android:clickable="booleano"
android:apiKey="cadena de caracteres"
... />

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.google.android.maps.MapView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:apiKey="0p6cjHRJBqcHwYoP14iUGkGox2vE8hgC5pf4v3g" />
</LinearLayout>

b. MapActivity

La vista MapView la gestiona una actividad derivada de la clase MapActivity.


La clase MapActivity tiene en cuenta el funcionamiento asociado al uso de una vista de
tipo MapView, como la visualizacin del mapa, los threads asociados Es preciso, por tanto, crear
una actividad que herede de la clase MapActivity y pasarle la MapView asociada.

El mtodo isRouteDisplayed debe implementarse. Este mtodo devuelve un valor booleano


que indica si la vista se utiliza para proveer indicaciones de navegacin.

Sintaxis

public class NombreDeClase extends MapActivity

Ejemplo

public class MiActividadMapa extends MapActivity {

@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.mapa);
}

@Override
protected boolean isRouteDisplayed() {
return false;
}

Es posible agregar botones en el mapa que permitan hacer zoom para acercar o alejar la vista. Para
ello, hay que recuperar la instancia de la vista MapView e invocar a
su mtodo setBuiltInZoomControls pasando como parmetro un valor booleano que indique
la activacin de los botones.

Sintaxis

public void setBuiltInZoomControls(boolean on)

Ejemplo

Hay dos modos disponibles para la representacin del mapa: el modo satlite y el modo plano.
244
MapView mapa = (MapView) findViewById(R.id.mapa);
mapa.setBuiltInZoomControls(true);

Elmtodo setSatellite permite utilizar uno u otro de los modos pasndole como parmetro un
valor especificando si se quiere utilizar el modo satlite o no, en cuyo caso se mostrar el modo
plano.

Sintaxis

public void setSatellite(boolean on)

Ejemplo

mapa.setSatellite(true);

c. Geolocalizacin

La clase MyLocationOverlay provee la posibilidad de detectar la posicin actual del dispositivo


y, por tanto, del usuario, y mostrarla en tiempo real sobre el mapa.

Grficamente, aparece un crculo azul parpadeando que indica la posicin actual, envuelto de un
crculo azul semi transparente ms o menos amplio representando el nivel de precisin de la
posicin. Cuando ms amplio sea el crculo, menor ser la precisin, y a la inversa.

Para ello, es preciso crear una instancia de la clase MyLocationOverlay utilizando el


constructor. ste recibe como parmetros el contexto y la vista MapView donde debe mostrarse la
posicin del usuario.

Sintaxis

public MyLocationOverlay(android.content.Context context,


MapView mapView)

Ejemplo

MyLocationOverlay locUsuario =
new MyLocationOverlay(this, mapa);

A continuacin, hay que activar la bsqueda de localizacin y su representacin utilizando


elmtodo enableMyLocation. Este mtodo devuelve un valor booleano que vale verdadero si al
menos un dispositivo de localizacin ha podido activarse, o falso en caso contrario.

Sintaxis

public boolean enableMyLocation()

Ejemplo

locUsuario.enableMyLocation();

Para detener la actualizacin de la localizacin y no mostrar ms la posicin del usuario, hay que
invocar al mtodo disableMyLocation.

La actualizacin de la localizacin en curso supone un consumo de recursos elevado, por ello


hay que tener en cuenta no utilizarlo ms que cuando se est mostrando el mapa. Para ello,
se recomienda invocar al mtodo enableMyLocation en el mtodo onResume de la actividad
y detener la actualizacin invocando al mtodo disableMyLocation en el mtodo onPause.

245
Sintaxis

public void disableMyLocation()

Ejemplo

locUsuario.disableMyLocation();

La clase MyLocationOverlay hereda de la clase Overlay. Todo objeto de tipo Overlaydebe


agregarse a una lista de objetos de este tipo gestionado por el objeto de tipo MapView. ste
utilizar esta lista para mostrar, en orden, los elementos de la lista sobre el mapa. La lista se
recupera utilizando el mtodo getOverlays.

Sintaxis

public final java.util.List<Overlay> getOverlays()

Ejemplo

mapa.getOverlays().add(mLocUsuario);

Tambin es posible mostrar una brjula sobre el mapa representando la orientacin actual del
dispositivo. Para ello, hay que utilizar los mtodos enableCompass y disableCompass de la
misma forma que para los mtodos enableMyLocation y disableMyLocation.

Sintaxis

public boolean enableCompass()


public void disableCompass()

Ejemplo

locUsuario.enableCompass();
procesamiento();
locUsuario.disableCompass();

La bsqueda de la localizacin del usuario puede tomar cierto tiempo. Una vez realizada la primera
localizacin, y mostrada en el mapa, puede ser interesante centrarla sobre el plano y hacer zoom
sobre ella.

Estas acciones pueden realizarse utilizando el objeto de tipo MapController asociado a


la vista MapView. La clase MapController proporciona varios mtodos tiles para navegar sobre
el mapa.

El mtodo getController de la clase MapView permite recuperar este objeto.

Sintaxis

public MapController getController()

Ejemplo

MapController controlador = mapa.getController();

El mtodo animateTo permite centrar el mapa sobre un punto determinado desplazando el mapa
de forma animada. Este mtodo recibe como parmetro un objeto de tipo GeoPoint con las
coordenadas, latitud y longitud, del punto. El punto de tipo GeoPoint correspondiente a la
posicin actual del usuario lo devuelve el mtodo getMyLocation.

246
Sintaxis

public GeoPoint getMyLocation()


public void animateTo(GeoPoint point)

Ejemplo

controlador.animateTo(locUsuario.getMyLocation());

El mtodo setZoom en s mismo permite hacer zoom a un nivel dado.

Sintaxis

public int setZoom(int zoomLevel)

Ejemplo

controlador.setZoom(15);

La clase MyLocationOverlay provee el mtodo runOnFirstFix que recibe como parmetro


un objeto de tipo Runnable, que contiene el cdigo que se ejecutar cuando se encuentre la
primera localizacin. Puede, por tanto, utilizarse para centrar el plano en la localizacin encontrada
y hacer zoom sobre ella.

Sintaxis

public boolean runOnFirstFix(java.lang.Runnable runnable)

Ejemplo

locUsuario.runOnFirstFix(new Runnable() {
public void run() {
MapController controlador = mapa.getController();
controlador.animateTo(locUsuario.getMyLocation());
controlador.setZoom(15);
}
});

Otras clases y mtodos permiten agregar otros elementos en el mapa y permiten al usuario
interactuar con ellos. Se trata, entre otros, de
las clases OverlayItem yItemizedOverlay.

247
14. Funcionalidades
avanzadas

248
Introduccin
Dado que resulta imposible abordar todos los temas referentes a Android, parece necesario
profundizar en dos materias ms antes de dar por concluido este libro.

Aparecido con la versin de Android 1.5 (API 3), el primer tema ha conocido un gran alcance desde su
salida. Y esto debera amplificarse, sin duda, con la llegada de las tabletas tctiles de alta resolucin y
con la versin Android 3.0 (API 11) que las acompaa.

El segundo tema todava no ha encontrado, al parecer, la misma popularidad. Sin duda porque no
tiene que ver con las aplicaciones de pago, o bien porque los desarrolladores no le dedican la
atencin o el tiempo de desarrollo que merece. Y, por tanto, su uso resulta primordial para cualquier
desarrollador que quiera ver retribuido su trabajo.

De este modo, este ltimo captulo est dedicado a los dos temas siguientes: los App Widgets y la
proteccin de las aplicaciones de pago.

249
App Widget
A da de hoy, la mayora de sistemas operativos de los ordenadores personales permiten agregar pequeas
aplicaciones directamente sobre el escritorio del usuario.

Estas aplicaciones, llamadas comnmente widgets, gadgets o con menor frecuencia vietas activas, permiten al usuario
visualizar cierta informacin y le proporcionan cierta funcionalidad asociada a un dominio de uso especfico. Por ejemplo,
existen widgets que muestran los datos meteorolgicos actuales, el progreso de la bolsa, las ltimas novedades de la
actualidad, fotografas y otros que proporcionan funciones de calculadora, de reloj

De forma similar a los sistemas operativos, Android permite agregar tales widgets sobre el escritorio del usuario, es
decir, la pantalla de bienvenida. De hecho, el escritorio es, en s mismo, una aplicacin. Se ejecuta automticamente
tras el arranque del sistema. Por ello, en concreto, Android propone integrar estos widgets en otra aplicacin, por
ejemplo, en este caso, la aplicacin de pantalla de bienvenida.

La interfaz de usuario espaola del sistema Android utiliza el trmino widget tal cual, sin traduccin.

Presionando durante cierto tiempo sobre la zona vaca del escritorio es posible mostrar un men
que nos propone, en concreto, una lista de widgets.

Para el desarrollador, este trmino puede tener otro sentido. En efecto, puede designar a los componentes grficos
estudiados anteriormente (vase el captulo Descubrir la interfaz de usuario - Widgets) tales como los textos, los
botones

Para diferenciar ambos y as evitar confusiones, los widgets destinados a ser agregados en el escritorio se denominan
en Android: App Widget.

1. Creacin
El App Widget es un receptor de eventos especializado de tipo AppWidgetProvider. Esta clase hereda de la
clase BroadcastReceiver y est especializado en el funcionamiento de los App Widgets. Es, por defecto, la clase
madre de todos los App Widgets.

La creacin de un App Widget comienza escribiendo su clase, que hereda, por tanto, de la
clase AppWidgetProvider.

Sintaxis

public class NombreDeClaseDelAppWidget extends AppWidgetProvider {


...
}

Ejemplo

public class MiAppWidget extends AppWidgetProvider {


}

2. Declaracin
Como todo componente de tipo BroadcastReceiver, un App Widget debe declararse en el manifiesto para poder
ser creado por el sistema.

La sintaxis es, por tanto, la misma que se utiliz en los receptores de eventos. El atributo android:name debe
contener el nombre de la clase del componente.

Hay que precisar en el filtro de acciones que el componente desea recibir


la accin android.appwidget.action.APPWIDGET_UPDATE. Tambin hay que agregar una etiqueta meta-data
que permita indicar el archivo XML que incluye los elementos de configuracin del App Widget descritos ms adelante.
Para ello, el atributo android:name debe informar el valorandroid.appwidget.provider y el
atributo android:resource el nombre del archivo XML.

Sintaxis

<receiver android:name="cadena de caracteres" >


<intent-filter>
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
250
android:resource="recurso xml" />
</receiver>

Ejemplo

<receiver android:name=".MiAppWidget" >


<intent-filter>
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/appwidget-config" />

</receiver>

3. Configuracin
Todo App Widget requiere sus elementos de configuracin.

Para ello, es preciso crear un nuevo archivo XML en la carpeta res/xml. El nombre del archivo importa poco. Es el
archivo que se informa en la etiqueta meta-data vista anteriormente. Este archivo debe incluir la etiqueta
principal appwidget-provider.

Sus atributos permiten proveer informacin asociada al App Widget.

Sintaxis

<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="dimensi!n en dp"
android:minHeight="dimensi!n en dp"
android:updatePeriodMillis="entero"
android:initialLayout="recurso layout"
android:configure="cadena de caracteres"
...
/>

Ejemplo

<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="146dp"
android:minHeight="72dp"
android:updatePeriodMillis="3600000"
android:initialLayout="@layout/appwidget_init"
android:configure="es.midominio.android.miapli.Conf
iguracionAppWidgetActividad"
/>

Los atributos android:minWidth y android:minHeight permiten indicar el tamao mnimo del App Widget en
dp, exclusivamente.

Si el App Widget est destinado a mostrarse sobre el escritorio, es preciso saber que ste posiciona los App Widgets
sobre una malla. Para determinar el tamao a informar en estos atributos, se aconseja utilizar la siguiente frmula:

tama"o_en_dp = (n#mero_de_casillas * 74) - 2

Aparecido en Android 3.1 (API 12), el nuevo atributo android:resizeMode permite al


usuario redimensionar el App Widget de forma horizontal, vertical, o ambas.

El atributo android:updatePeriodMillis permite al desarrollador especificar la frecuencia con la que se quiere


actualizar el App Widget mediante la llamada a su mtodo onUpdate. El valor debe especificarse en milisegundos.

Si se encuentra en reposo, el dispositivo se activar para realizar esta actualizacin. Esto


puede causar problemas de consumo de recursos si la actualizacin se realiza con demasiada
frecuencia. Para evitar esto, el sistema fuerza un valor mnimo de 30 minutos en el caso en el que
el desarrollador haya especificado un valor inferior.

251
Para evitar la salida del modo reposo del dispositivo o para especificar un valor de actualizacin inferior a 30 minutos,
es posible utilizar en su lugar una alarma de tipo AlarmManager configurada de tal forma que slo se produzca
cuando el dispositivo est activo.

En este caso, el atributo android:updatePeriodMillis debe valer 0 para desactivarlo. Esta solucin permite
tambin escoger al usuario la frecuencia con la que se quiere actualizar la informacin, por ejemplo en la actividad de
configuracin.

El atributo android:initialLayout permite indicar el layout que se utiliza en la creacin del App Widget hasta
que se actualice con otro layout.

El atributo android:configure es opcional. Permite especificar el nombre completo de la clase que representa la
actividad de configuracin del App Widget; si existe, se ejecutar tras la creacin del App Widget. Esta actividad de
configuracin se describe ms adelante.

A modo de recordatorio, es posible especificar el icono y el texto que se quiere mostrar en la


lista de widgets presentada al usuario. Estos atributos son,
respectivamente, android:icony android:label.

A partir de Android 3.0 (API 11), el nuevo atributo android:previewImage permite


especificar una imagen que representa una captura de pantalla del App Widget en estado de
funcionamiento. Esta imagen permite al usuario previsualizar el App Widget antes de instalarlo. Si
no se especifica este atributo, el App Widget se representar mediante su icono, en lugar de con
su imagen de previsualizacin, en la lista de App Widgets presentada al usuario. La aplicacin
Widget Preview, preinstalada en el sistema Android, del emulador permite crear fcilmente
capturas de pantalla de un App Widget.

4. Ciclo de vida
La clase AppWidgetProvider define mtodos correspondientes a los eventos que debe tratar un App Widget.
Filtra los intents recibidos e invoca a sus mtodos internos correspondientes. Estos mtodos son los
mtodos onUpdate, onDeleted, onEnabled y onDisabled.

a. onEnabled

El mtodo onEnabled permite inicializar los datos comunes a todas los mismos App Widget. Este mtodo se invoca
nicamente tras la primera creacin de un App Widget de un tipo dado. Es decir, si, por ejemplo, el usuario agrega
varios App Widgets del mismo tipo en el escritorio, slo el primero recibir esta llamada. Este mtodo recibe como
parmetro el contexto de la aplicacin.

Sintaxis

public void onEnabled (Context context)

Ejemplo

@Override
public void onEnabled(Context context) {
super.onEnabled(context);
}

b. onDisabled

El mtodo onDisabled es el simtrico al mtodo onEnabled. Es el ltimo momento para poder limpiar lo que es
necesario, borrar datos temporales, cerrar conexiones abiertas... Este mtodo se invoca nicamente cuando el
ltimo App Widget se suprime. Es decir, si, por ejemplo, el usuario agrega varios App Widgets del mismo tipo sobre
el escritorio, slo el ltimo recibir esta llamada cuando se suprima. Este mtodo recibe como parmetro el contexto
de la aplicacin

Sintaxis

public void onDisabled (Context context)

Ejemplo

252
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
}

c. onUpdate

El mtodo onUpdate se invoca una primera vez cuando el App Widget se crea. A continuacin, se invoca a
intervalos regulares definidos por el desarrollador. Si existen varios App Widgets del mismo tipo, este mtodo slo
se invoca una vez para procesar todas estas instancias. Todos estos App Widgets se actualizarn casi al mismo
tiempo. La cuenta del intervalo regular comienza con la creacin del primero de los App Widgets. Este mtodo recibe
como parmetros el contexto de la aplicacin, una instancia de tipo AppWidgetManager as como una tabla de
identificadores nicos de los Widgets existentes.

En teora, existe un caso particular: este mtodo no se invoca cuando se crea el App Widget
si se utiliza una actividad de configuracin, descrita ms adelante. En la prctica, esto no
ocurre. El mtodo onUpdate se invoca de la misma forma, al menos en el momento de escribir
este libro. Yo mismo he declarado este bug. Para ms informacin visite la
pgina:http://code.google.com/p/android/issues/detail?id=3696

Sintaxis

public void onUpdate (Context context,


AppWidgetManager appWidgetManager, int[] appWidgetIds)

Ejemplo

@Override
public void onUpdate(Context context,
AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int appWidgetId : appWidgetIds) {
procesamiento(appWidegtId);
}
}

d. onDeleted

El mtodo onDeleted se invoca cuando se borra el App Widget, por ejemplo cuando el usuario lo lleva a la
papelera. Este mtodo recibe como parmetro el contexto de la aplicacin y la tabla de los identificadores de los App
Widgets suprimidos.

Este mtodo no est nombrado correctamente en Android 1.5 (API 3). Para ms informacin y
una correccin: http://groups.google.com/group/android-developers/msg/e405ca19df2170e2

Sintaxis

public void onDeleted (Context context, int[] appWidgetIds)

Ejemplo

@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
}

5. RemoteViews
De forma similar a una actividad, la apariencia del App Widget se define en un archivo Layout. ste se provee a la
aplicacin, que lo integra en su propio layout, como por ejemplo la aplicacin de escritorio.

Android utiliza un objeto de tipo RemoteViews para contener el layout del App Widget y proveerlo a la aplicacin
host.

Slo algunos componentes grficos pueden utilizarse en un layout de App Widget. Son los
componentes AnalogClock, Button, Chronometer, ImageButton, ImageView,ProgressBar y TextView.
A partir de Android 3.0 (API 11), tambin es posible utilizar
253 nuevos componentes ms interactivos
como GridView, ListView, StackView, ViewFlipper yAdapterViewFlipper. Estos
ltimos pueden actualizar sus vistas automticamente utilizando las nuevas
clases RemoteViewsService y RemoteViewsFactory.

En el curso de su ciclo de vida y de su interaccin con el usuario, el App Widget tendr, sin duda, que cambiar su
apariencia; modificar una imagen, cambiar un texto

La clase RemoteViews provee todo un conjunto de mtodos para modificar los distintos objetos, las distintas vistas,
que representan la interfaz grfica del App Widget.

En primer lugar, hay que crear la instancia de tipo RemoteViews utilizando uno de sus constructores. ste recibe
como parmetros el nombre del paquete que contiene el layout y el identificador nico del layout del App Widget.

Sintaxis

public RemoteViews (String packageName, int layoutId)

Ejemplo

Este objeto
RemoteViews vistas = new RemoteViews(context.getPackageName(), permite, a
R.layout.appwidget); continuacin,
modificar los
atributos de las vistas que contiene utilizando toda una serie de modificadores especficos o no a un tipo de
componente grfico particular. Estos mtodos reciben como parmetros el identificador nico de la vista y los datos a
proveer.

Sintaxis de algunos de estos mtodos

public void setImageViewResource (int viewId, int srcId)


public void setProgressBar (int viewId, int max, int progress,
boolean indeterminate)
public void setTextColor (int viewId, int color)
public void setTextViewText (int viewId, CharSequence text)
public void setViewVisibility (int viewId, int visibility)

Ejemplo

Es posible
vistas.setTextViewText(R.id.appwidget_titulo, "Nuevo t!tulo"); especificar los
intents que se
ejecutarn tras hacer clic sobre una de las vistas del App Widget. Para ello, hay que utilizar el
mtodo setOnClickPendingIntent que recibe como parmetros el identificador nico de la vista y el objeto de
tipo PendingIntent que se quiere ejecutar como respuesta al clic.

Sintaxis

public void setOnClickPendingIntent (int viewId,


PendingIntent pendingIntent)

Ejemplo

Una vez
Intent intent = new Intent(context, MiActividadPrincipal.class); modificado el
PendingIntent pIntent = PendingIntent.getActivity(context, 0, App Widget,
intent, 0); hay que
vistas.setOnClickPendingIntent(R.id.appwidget_icono, pIntent); utilizar el
objeto
de tipo AppWidgetManager recibido como parmetro en el mtodo onUpdate para solicitar la actualizacin del
App Widget. La clase AppWidgetManager provee varios mtodos updateAppWidget que reciben como
parmetros uno o varios identificadores nicos designando el o los App Widgets cuyas vistas se modificarn. La
jerarqua de estas vistas de tipo RemoteViews se pasa como segundo parmetro.

A modo de recordatorio, la lista de los identificadores de los App Widgets se recibe a su vez
como parmetro del mtodo onUpdate y puede utilizarse aqu de manera sencilla.

Sintaxis

public void updateAppWidget (int appWidgetId, RemoteViews views)


public void updateAppWidget (int[] appWidgetIds, RemoteViews views)
254
Ejemplo

@Override
public void onUpdate(Context context,
AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int appWidgetId : appWidgetIds) {
RemoteViews vistas =
new RemoteViews(context.getPackageName(),
R.layout.appwidget);
procesamiento(appWidgetId);
appWidgetManager.updateAppWidget(appWidgetId, vistas);
}
}

Preste atencin, cuando se est utilizando un AVD recin creado, es posible que las
actualizaciones de los App Widgets no se tengan en cuenta. Para ms
informacin:http://code.google.com/p/android/issues/detail?id=8889

6. Actividad de configuracin
Ciertos App Widgets puede que no sean completamente usables hasta que se hayan configurado. Por ejemplo, un
App Widget que muestre el desfase horario con una zona geogrfica solicitar al usuario que elija la zona geogrfica
deseada.

Una solucin consiste en crear el App Widget con una zona por defecto y agregarle unpendingIntent que ejecute
una actividad que permita especificar la zona cuando el usuario haga clic sobre el App Widget. O, directamente,
ejecutar la actividad desde la creacin del App Widget detectando si se trata de una creacin o de una actualizacin...

Para facilitar esta operacin, la aplicacin host se encarga de ejecutar


la accin android.appwidget.action.APPWIDGET_CONFIGURE antes de crear el App Widget. Si existe una
actividad que responda a esta accin, entonces sta se ejecutar, y el App Widget podr, a continuacin, crearse
segn los parmetros de configuracin especificados mediante esta actividad.

En la prctica, el App Widget se crea ANTES que la ejecucin de la actividad de configuracin


porque, recordemos, en este caso se ejecuta su mtodo onUpdate mientras que, en teora,
esto no debera pasar. La ejecucin del mtodo onUpdate se realiza ANTES de ejecutar la
actividad de configuracin.

a. Declaracin

La actividad de configuracin debe indicar que puede responder a la


solicitud android.appwidget.action.APPWIDGET_CONFIGURE agregando esta accin en su filtro de
intenciones que figura en el manifiesto.

Ejemplo

Como
<activity android:name=".ConfigurationAppWidgetActividad"> complemento,
<intent-filter> la actividad
<action deber
android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> declararse en
</intent-filter> el archivo de
</activity>
configuracin
del App
Widget mediante el atributo android:configure descrito anteriormente.

b. Creacin

La actividad de configuracin es una actividad como cualquier otra. No obstante, la ejecuta la aplicacin host que
espera, obligatoriamente, un valor resultado que indique si la etapa de configuracin se ha desarrollado
correctamente o no. De este valor depende el resto de eventos.

Al ejecutar la actividad de configuracin, la aplicacin host proporciona el identificador del App Widget en los
valores Extras del intent mediante la clave AppWidgetManager.EXTRA_APPWIDGET_ID. Es posible utilizar
el valorAppWidgetManager.INVALID_APPWIDGET_ID como valor por defecto que permite detectar la omisin
255
del identificador del App Widget.

Ejemplo

Una vez el
Intent intent = getIntent(); usuario haya
Bundle extras = intent.getExtras(); utilizado la
if (extras != null) { actividad de
mAppWidgetId = configuracin,
extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, si todo
AppWidgetManager.INVALID_APPWIDGET_ID); funciona
}
correctamente,
debe devolver
el valor RESULT_OK. En este caso, la aplicacin host crea el App Widget.

Pero si, por ejemplo, el usuario sale de la actividad sin validar la configuracin del App Widget, sta puede
considerarlo como una anulacin de la configuracin y, por tanto, devolver el valorRESULT_CANCELED. En este
caso, la aplicacin host anular la creacin del App Widget. Si se trata de la aplicacin de inicio, el App Widget no se
mostrar jams.

Se recomienda especificar el valor resultado de RESULT_CANCELED desde la creacin de la


actividad de configuracin de modo que ste sea el resultado que se devuelva, salvo si se
provee explcitamente el valor RESULT_OK.

En ciertos casos particulares, por ejemplo, cuando el usuario hace clic en el


botn Iniciocuando se est mostrando la actividad de configuracin, el
resultado RESULT_CANCELED no se toma en cuenta. El mtodo onDeleted del App Widget
no se invoca. Si bien el App Widget no aparece sobre la pantalla, su creacin no se ha anulado.
Existe sin mostrarse. Es algo as como un App Widget fantasma. Este bug hace que el
desarrollador deba tener en cuenta este caso particular en su cdigo. Para ms
informacin:http://code.google.com/p/android/issues/detail?
id=9362,http://code.google.com/p/android/issues/detail?id=2539. El comentario nmero 15
explica, en particular, una solucin.

En concreto, el resultado se devuelve mediante el mtodo setResult ya estudiado (vase el captulo Los
fundamentos - Actividad). El valor del resultado debe estar acompaado del identificador nico del App Widget que
permite a la aplicacin host saber cul es el App Widget afectado por el resultado. Para ello, hay que crear un intent
y agregar en los datos extras el par clave-valor cuya clave es la
constante AppWidgetManager.EXTRA_APPWIDGET_ID y el valor es el identificador del App Widget recuperado
anteriormente.

Recuerde que el mtodo setResult no finaliza la actividad. Hay que hacerlo explcitamente utilizando el
mtodo finish.

Ejemplo

En teora, en
Intent resultado = new Intent(); el caso de uso
resultado.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, de una
mAppWidgetId); actividad de
setResult(RESULT_CANCELED, resultado); configuracin,
una vez
creado el App
Intent resultado = new Intent(); Widget, el
resultado.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
mAppWidgetId);
setResult(RESULT_OK, resultado);
finish();

mtodo onUpdate no se invoca. Corresponde a la actividad de configuracin refrescar explcitamente las vistas del
App Widget utilizando el mtodo updateAppWidget, como hemos visto anteriormente.

En la prctica, esto no es cierto. El mtodo onUpdate se invoca en cualquier caso.

Para ello, la actividad debe utilizar la instancia del objeto de tipo AppWidgetManager. Esta instancia se recupera
utilizando el mtodo esttico getInstance de la clase AppWidgetManager. Este mtodo recibe como parmetro
el contexto aplicativo.
256
Sintaxis

public static AppWidgetManager getInstance (Context context)

Ejemplo

AppWidgetManager appWidgetManager =
AppWidgetManager.getInstance(context);

257
Proteger las aplicaciones de pago
Como hemos visto, una aplicacin publicada se presenta bajo la forma de un archivo apk. Basta a un
tercero con tener este archivo en posesin suya para que pueda compartirlo con otras personas. Esto
no supone, por lo general, un problema para las aplicaciones gratuitas puesto que el desarrollador
quiere que se distribuyan e instalen lo ms posible, y poco importa el medio. Por el contrario, no ocurre
lo mismo con las aplicaciones de pago. Estas copias ilegales son una prdida de ingresos para el
desarrollador...

Para protegerse contra el uso de copias ilegales de aplicaciones de pago, y nicamente de aplicaciones
de pago, Android provee un sistema de verificacin de licencias de las aplicaciones compradas e
instaladas obligatoriamente a travs del Android Market. Este servicio existe para los sistemas Android
1.5 (API 3) o superiores.

El principio de este sistema es simple y toma el aspecto de una librera llamada LVL (License Verification
Library) o librera de verificacin de licencias. Esta librera permite, mediante la aplicacin Android Market
instalada en el sistema Android, comunicarse con el servidor de licencias en lnea. ste devuelve, de
forma segura, el estado de la licencia propia de la aplicacin para el usuario correspondiente. Es la
aplicacin Android Market quien gestiona la comunicacin en lnea con el servidor. El desarrollador slo
tiene que ejecutar los comandos utilizando la librera y procesar las respuestas.

En funcin del resultado devuelto por la aplicacin Android Market, el desarrollador podr aplicar la
estrategia que prefiera como, por ejemplo: autorizar el uso de la aplicacin durante un cierto periodo
de tiempo, restringir ciertas funcionalidades de la aplicacin, o incluso bloquear por completo el acceso
a la aplicacin.

Este sistema requiere una conexin a la red para comunicarse con el servidor de licencias. Es preciso,
por tanto, prever una alternativa cuando no exista conexin a la red como, por ejemplo, una cach de
la licencia.

1. Instalacin de la LVL
La librera de verificacin de licencias requiere que la aplicacin est configurada para compilarse con
la plataforma Android 1.5 (API 3) o superior. Esta librera se provee bajo la forma de archivos de
cdigo fuente que deben integrarse en el proyecto bien directamente, o bien como librera de
archivos de cdigo fuente que hay que enlazar al proyecto durante la compilacin, de modo que
resulta fcilmente reutilizable. Esta librera no debe integrarse como librera externa, es decir,
compilada de forma separada e integrada en los proyectos como archivo jar.

a. Descarga

La librera LVL se puede descargar como mdulo utilizando el Android SDK and AVD Manager. Este
mdulo contiene, entre otros, los archivos de cdigo fuente de la LVL, una aplicacin que sirve de
ejemplo y la documentacin javadoc.

Ejecute la herramienta Android SDK and AVD Manager.

En la lista de la izquierda, seleccione Available packages y, a continuacin, en la lista de la


derecha, despliegue la carpeta Third party Add-ons y marque Google Market Licensing
package.

258
LVL - Instalacin

Para probar la LVL desde el emulador, el AVD debe estar basado sobre un sistema Google
APIs by Google Inc. Es preciso, por tanto, llegado el caso, marcar la opcin correspondiente
en la pantalla anterior, como es el caso aqu para la versin 11.

Haga clic en el botn Install Selected y finalice la instalacin como ya se ha visto en captulos
anteriores (vase el captulo El universo Android - Entorno de desarrollo).

Los archivos se descargan e instalan en la carpetasdk/extras/google/market_licensing.

b. Integracin de la LVL en el cdigo fuente

La primera forma de integrar el cdigo de la LVL en un proyecto consiste en copiar directamente los
archivos del cdigo fuente. Este es el mtodo ms sencillo y el ms rpido. No obstante, es el
menos productivo a largo plazo si lo que queremos es poder utilizar esta librera y mantenerla en
varios proyectos distintos.

Copie la carpeta library/src/com de la LVL en la carpeta src del proyecto.


En Eclipse, actualice el proyecto para tener en cuenta el
nuevo paquete com.android.vending.licensing y las clases que contiene.

c. Integracin de la LVL como librera

La segunda forma de integrar el cdigo fuente de la LVL en un proyecto consiste en importarla como
librera. Este mtodo es algo ms largo de llevar a cabo la primera vez pero permite mantener un
nico cdigo fuente que puede integrarse, a continuacin, en varios proyectos distintos.

Para poder modificar el mdulo LVL descargado sin miedo a que falle por alguna actualizacin, copie
la carpeta library de la LVL en la carpeta correspondiente al espacio de trabajo de Eclipse. Esta
copia es la que modificaremos y utilizaremos.

En realidad, a da de hoy, copiar la carpeta directamente en el espacio de trabajo hace que


aparezca un problema durante la creacin del proyecto Android, mientras que funciona
correctamente para un proyecto Java. Para 259
solventar este problema, hay que copiar la
carpeta library en una carpeta temporal externa al espacio de trabajo. A continuacin, una
vez creado el proyecto como se describe ms adelante, hay que suprimirlo del espacio de
trabajo sin borrar el proyecto del disco duro. A continuacin, hay que desplazar la
carpeta library en la carpeta del espacio de trabajo para, por ltimo, poder importarlo de
nuevo en Eclipse a travs del men File - Import... - Existing Projects into Workspace.

La creacin del proyecto de librera sigue el mismo principio de creacin que un proyecto Android
clsico aunque utiliza los archivos de cdigo fuente provistos.

En el asistente de creacin del proyecto Android, indique un nombre de proyecto, marque la


opcin Create project from existing source e indique la carpeta library de la LVL.

Seleccione una versin adecuada en el campo Build Target. sta debe ser igual o superior a
Android 1.5 (API 3).

260
LVL - Instalacin

Haga clic en el botn Finish.

Se ha creado el proyecto.

Ahora, hay que indicar al proyecto que contiene la aplicacin que agregue una referencia a este
proyecto de modo que, cuando se compile la aplicacin, los archivos de cdigo fuente de la librera
se agregarn a la compilacin para producir un nico binario.

En Eclipse, abra la ventana de las propiedades del proyecto de la aplicacin Android. Para ello,
haga clic con el botn derecho sobre el nombre del proyecto y, a continuacin, Properties.

Seleccione Android en la lista de la izquierda y despus, en la parte derecha, haga clic en el


botn Add... y seleccione el proyecto correspondiente a la librera.

LVL - Instalacin

Haga clic en el botn OK.

La librera queda enlazada al proyecto y se integrar en cada compilacin como si los archivos de
cdigo fuente formaran parte del proyecto.

2. Uso de la LVL
Una vez descargada la LVL e integrada en su proyecto, hay que definir una estrategia, o poltica, de
verificacin de licencia para adoptar en la aplicacin. Algunas de estas polticas encriptan los datos
que registran de manera local. La verificacin de la licencia puede realizarse a continuacin.
261
a. Poltica

Cada aplicacin puede escoger la estrategia que desea adoptar cuando recibe el resultado de una
verificacin de licencia. Esta poltica a aplicar debe implementarse en la aplicacin.

El desarrollador puede crear sus propias polticas implementando una interfaz Java. Pero, para
ayudarle en esta tarea, Android provee dos polticas por defecto ya implementadas que basta con
instanciar para dar respuesta a los casos ms comunes:

ServerManagedPolicy: es la poltica recomendada y utilizada por defecto. Se trata de


una poltica que utiliza los parmetros de configuracin reenviados por el servidor de
licencia. Esta poltica funciona incluso sin conexin gracias a una cach segura, ofuscada.
Algunos de estos parmetros de configuracin son: fecha y hora de fin de validez de la
cach, nmero mximo de reintentos de verificacin de licencia antes de bloquear el acceso
a la aplicacin Su constructor recibe como parmetros el contexto de la actividad en curso
y un objeto de tipo Obfuscator descrito en el prrafo siguiente.

Sintaxis

public ServerManagedPolicy(Context context, Obfuscator obfuscator)

StrictPolicy: es la poltica ms estricta, que slo autoriza el acceso a la aplicacin si el


servidor indica que la licencia es vlida. La ventaja es que ofrece una mayor seguridad pues
no conserva trazas de la licencia en una cach como hace la poltica anterior. La otra cara
de la moneda es que requiere una conexin de red funcional con cada verificacin, lo cual
puede resultar molesto para un gran nmero de usuarios.

Sintaxis

public StrictPolicy()

b. Ofuscacin

Ciertas polticas, como la poltica ServerManagedPolicy, requieren almacenar los datos


relativos a la licencia en un almacn persistente local. Estos datos deben ser seguros, puesto que
permiten determinar si el usuario tiene acceso o no a la aplicacin.

Para ello, es preciso utilizar un ofuscador de datos. Como ocurre con las polticas, el desarrollador
puede escoger crear su propio ofuscador o bien puede utilizar un ofuscador ya implementado
provisto por Android: el AESObfuscator. Como su propio nombre indica, este ofuscador utiliza la
encriptacin AES para proteger los datos.

Para proteger al mximo los datos, el ofuscador AESObfuscator utiliza valores especficos del
desarrollador, de la aplicacin y del dispositivo Android para generar claves de encriptacin AES lo
ms variadas posibles.

Estos datos son:

una tabla de veinte bytes inicializada con valores tomados al azar. Por ejemplo:

private static final byte[] SALT = new byte[] {


-42, 13, -37, 5, 86, 45, -123, 102, -15, -3,
123, 5, 42, -115, 2, 110, 25, 53, 5, -128
};

una cadena de caracteres identificando a la aplicacin, tpicamente el nombre del paquete


de la aplicacin utilizando el mtodo getPackageName.

una cadena de caracteres identificando el dispositivo Android de la forma ms unvoca


posible como, por ejemplo, el valor de la
constante:android.Settings.Secure.ANDROID_ID

262
La creacin de una instancia AESObfuscator se realiza mediante el uso del ofuscador. ste
recibe como parmetros los datos detallados anteriormente.

Sintaxis

public AESObfuscator(byte[] salt, String applicationId,


String deviceId)

Ejemplo

String deviceId =
Secure.getString(getContentResolver(), Secure.ANDROID_ID);
AESObfuscator obf =
new AESObfuscator(SALT, getPackageName(), deviceId);

c. Verificacin de la licencia

Requisito previo obligatorio para autorizar la aplicacin de la que se quiere verificar la licencia, es
preciso que el proyecto de la aplicacin incluya el permiso de verificacin de la licencia.

Para ello, hay que agregar la lnea siguiente en el manifiesto:

Sintaxis

<uses-permission android:name="com.android.vending.CHECK_LICENSE" />

Ejemplo

<?xml version="1.0" encoding="utf-8"?>


<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="es.midominio.android.miapli"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon"
android:label="@string/app_name">
...
</application>

<uses-permission
android:name="com.android.vending.CHECK_LICENSE" />
</manifest>

El uso de la LVL se realiza mediante una instancia de tipo LicenseChecker que pertenece al
paquete com.android.vending.licensing. El cons-tructor de la
clase LicenseCheckerrecibe como parmetros el contexto de la actividad en curso, la instancia
de la poltica escogida as como la clave pblica de nuestra cuenta de desarrollador. Esta clave se
recupera desde la cuenta de desarrollador del Android Market como se explica ms adelante.

Sintaxis

public LicenseChecker(Context context, Policy policy,


String encodedPublicKey)

Ejemplo

LicenseChecker lc = new LicenseChecker(this, policy, "MIIBI...");

Todo objeto de tipo LicenceChecker debe obligatoriamente invocar a


su mtodo onDestroy en el mtodo onDestroy de la actividad que la ha creado.

263
La fase de verificacin de la licencia se desarrolla en dos etapas. La primera etapa consiste en
iniciar la verificacin de la licencia mediante una llamada al mtodo checkAccess del objeto de
tipo LicenseChecker. Se ejecutar, generalmente, esta llamada en el mtodo onCreate de la
actividad principal de modo que se verifique la licencia desde el inicio de la aplicacin. Este mtodo
recibe como parmetro un objeto que implementa la interfaz LicenseCheckerCallback. Este
objeto se utiliza durante la segunda etapa: la recuperacin del resultado.

Sintaxis

public synchronized void


checkAccess(LicenseCheckerCallback callback)

La interfaz LicenseCheckerCallback permite gestionar todo tipo de resultado tras la


verificacin de la licencia. Est compuesta por los
tres mtodos allow, dontAllow yapplicationError que se invocan respectivamente cuando
la licencia se confirma como vlida, invlida, o cuando el desarrollador ha cometido algn error en la
implementacin de la secuencia de verificacin que impide su buen funcionamiento.

Sintaxis

public void allow()


public void dontAllow()
public void applicationError(ApplicationErrorCode errorCode)

Es responsabilidad del desarrollador realizar, a continuacin, las acciones necesarias en funcin del
resultado. Por ejemplo, en el mtodo dontAllow, el desarrollador podr informar al usuario que
su licencia no es vlida, proponerle adquirir una licencia en el Android Market y, si no lo desea,
forzar a que la aplicacin se cierre.

Los mtodos de la interfaz LicenseCheckerCallback se invocan, generalmente, desde


threads distintos al thread UI principal de la aplicacin, de modo que no bloqueen la aplicacin
durante la fase de verificacin. Por ello, el desarrollador deber tener en cuenta no invocar
directamente los mtodos para actualizar la interfaz de usuario desde los mtodos de la
interfaz LicenseCheckerCallback. En su lugar, podr utilizar un objeto de tipo Handler o el
mtodo runOnUIThread para actualizar la interfaz de usuario en el thread principal.

3. Probar
Para poder probar la LVL, debe poseer una cuenta de desarrollador en el Android Market (vase el
captulo Publicar una aplicacin - Publicacin de la aplicacin en el Android Market).

Tras la creacin de la cuenta de desarrollador en el Android Market, se genera automticamente un


par de claves pblica/privada RSA de 2048 bits que pertenecen al desarrollador y son vlidas para
todas las aplicaciones en pruebas o publicadas con su cuenta.

La clave privada se guarda, de forma secreta y segura, en el Android Market. Permite firmar la
respuesta del servidor de licencias y garantizar la seguridad del resultado de la verificacin. La clave
pblica se provee durante la instanciacin de objetos de tipo LicenseChecker en el cdigo de las
aplicaciones.

Para recuperarlo, el desarrollador debe conectarse sobre su cuenta web en el Android Market.

En la pgina principal de la cuenta, haga clic en Modificar el perfil en la parte superior


izquierda, bajo el nombre y la direccin e-mail del perfil.

En la pgina de edicin del perfil, descienda hasta el final de la pgina.

Aparece la parte correspondiente a las licencias y a las compras integradas llamada Licencias y
facturacin integrada en la aplicacin.

264
LVL - Pruebas

El primer campo Clave pblica contiene la clave pblica codificada de la cuenta de desarrollador. Esta
cadena de caracteres es la que hay que utilizar en el cdigo de la aplicacin.

El campo Cuentas de prueba permite agregar otras direcciones de mensajera electrnica


correspondiente a cuentas de usuario Gmail que recibirn las respuestas de las pruebas de
verificacin de las licencias de las aplicaciones de esta cuenta. Estas respuestas de prueba se
especifican en el campo Respuesta a prueba de licencia.

El campo Respuesta a prueba de licencia permite al desarrollador indicar el resultado de la prueba


que quiera devolver desde el servidor de licencias para probar sus aplicaciones. Slo las cuentas
Gmail del desarrollador y de los usuarios especificados en el campo anterior obtendrn este cdigo de
prueba para las aplicaciones ya transferidas en la cuenta del desarrollador.

Solamente la cuenta del desarrollador podr recibir este cdigo para aquellas aplicaciones que
todava no hayan sido transferidas a la cuenta del desarrollador y que estn, por tanto, en
fase de pruebas.

Un clic en el botn Guardar permite guardar las modificaciones de la pgina y tenerlas en cuenta.

Los valores de los campos Cuentas de prueba y Respuesta a prueba de licencia son vlidos
para todas las aplicaciones de la cuenta del desarrollador.

Las pruebas sobre el dispositivo o emulador requieren que se configure una cuenta de Google en el
sistema Android para poder identificar al usuario y permitir realizar las verificaciones de las licencias
de las aplicaciones.
265
He aqu las etapas que debe seguir para configurar una cuenta de Google:

Desde la pantalla de inicio del sistema Android, presione la tecla Men o abra la lista de
aplicaciones, a continuacin haga clic en Configuracin.

LVL - Pruebas

Seleccione Cuentas y sincronizacin.

266
LVL - Pruebas

Haga clic en el botn Agregar una cuenta.

LVL - Pruebas

267
Haga clic sobre la opcin Google.

LVL - Pruebas

A continuacin, siga las instrucciones indicando los datos, direccin de correo electrnico Gmail y
contrasea asociadas a la cuenta usada para crear la cuenta de desarrollador, o bien a alguna
cuenta de prueba.

268
LVL - Pruebas

a. Probar sobre un dispositivo Android

Para poder probar la LVL sobre un dispositivo Android, es preciso que la versin del sistema sea la
1.5 o superior y que la aplicacin Android Market est presente, pues se comunicar con el servidor
de licencias.

b. Probar sobre un emulador

Es posible probar la LVL sobre un emulador Android a condicin de que el AVD utilice una imagen
que incluya el mdulo complementario Google APIs by Google Inc versin 8 release 2 o superior.
Slo estas imgenes contienen la parte de la aplicacin Android Market que permite conectarse a
los servidores de licencias. Y slo estas imgenes permiten conectarse con una cuenta Google: la
del desarrollador o una de las cuentas de prueba.

Recuerde, la descarga de dicha imagen se ha descrito en el prrafo correspondiente a la


instalacin de la LVL.

Preste atencin, la verificacin de la licencia no funciona sobre un emulador Google API


versin 9 release 2. Esta versin no tiene en cuenta el estado de la licencia seleccionada
sobre el servidor. Para ms informacin: http://code.google.com/p/android/issues/detail?
id=14252

269