Beruflich Dokumente
Kultur Dokumente
de Sistemas
Trabajo Teórico POO
marzo, 2010
DESARROLLO DE APLICACIONES EN
ANDROID
1.1. Historia
La historia de este S.O. comienza en Junio del 2005, momento en el cual Google compró una
pequeña compañía cuya finalidad era el desarrollo de aplicaciones para dispositivos móviles:
Android Inc. Uno de los cofundadores de aquella compañía, Andy Rubin, pasaría
posteriormente a ser el director de la división de plataformas móviles de Google. Aquella
empresa era desconocida para el mundo de las tecnologías en aquellos años, a pesar de lo cual el
grupo de fundadores tenía gran experiencia en plataformas web, telecomunicaciones y
aplicaciones móviles.
-1-
Desarrollo de aplicaciones en Android
Su lanzamiento inicial fue el 21 de Octubre de 2008 con la versión 1.0. Tras varias
correcciones y nuevas implementaciones el sistema se encuentra en su versión 2.1 a fecha del 17
de Marzo de 2010. La siguiente gráfica obtenida de la web “Android Developers” muestra el
porcentaje de dispositivos Android que utilizan una determinada
versión:
Por cada nueva versión de la plataforma se ha ido añadiendo un nivel más a la API, estando
dividida en Abril del 2010 en siete niveles.
1.2. Mercado
Con el avance de las nuevas tecnologías se han incrementado las posibles funcionalidades del
móvil en relación a las nuevas formas de comunicación lo que ha conllevado al desarrollo de
nuevos sistemas operativos para smartphones. A continuación se observa un gráfico que
muestra el panorama actual de los diferentes S.O. según el uso que hacen del tráfico de red:
Ilustración 4 – Gráfico de los S.O. para smartphones según el uso de la red de datos
A pesar de que Symbian –propiedad de Nokia - es el líder respecto a las ventas de móviles,
no lo es en cambio en el uso de Internet, campo en el que domina iPhone OS, que en principio
se plantea como el principal obstáculo de Android. Sin embargo, el hecho de que Android se
haya creado con el objetivo de poder correr sobre terminales de distintos fabricantes abre un
nuevo panorama en el mercado de las aplicaciones para móviles.
Además, el hecho de la existencia del Android Market; un espacio para la distribución y
venta de aplicaciones, abierto a todos los desarrolladores y sin intermediarios, permitirá la
posibilidad de hacer un buen negocio apostando por esta plataforma. Es por ello que como se
observa en la siguiente gráfica el número de aplicaciones para Android sigue creciendo, a pesar
de que a fecha de escritura de este texto el número de terminales con S.O.Android no es todavía
suficientemente elevado y las empresas no están aun obteniendo los beneficios esperados.
1.3. Arquitectura
El sistema operativo Android está formado principalmente por los siguientes componentes:
1.3.1 Aplicaciones
Android suministra un amplio espectro de aplicaciones para que el usuario pueda satisfacer sus
necesidades, además de la posibilidad de añadir nuevas mediante el ya mencionado Android
Market. Por defecto se incluye un cliente de correo electrónico, programa de SMS, calendario,
mapas, navegador, contactos, etc…
1.3.3 Librerías
Incluye un conjunto de librerías C / C + + usadas por diversos componentes del sistema.
Algunas son: System C Library ( implementación de la biblioteca C Standard ), bibliotecas de
medios, bibliotecas de gráficos, bibliotecas 3D, SQLite, etc…
1.4. Paquetes
Android reutiliza a una gran cantidad de paquetes ya existentes como son los del lenguaje Java (
java.util, java.net, etc… ), pero a la vez también añade una gran cantidad de paquetes
propios que aportan mayores posibilidades a las aplicaciones que sean desarrolladas mediante su
uso. Estos son algunos que se han considerado relevantes:
• android: contiene las clases correspondientes a los recursos ( imágenes, modelos
de IG, atributos… ) utilizados por las aplicaciones.
• android.app: proporciona clases que encapsulan el modelo general de una
aplicación. Algunas de las clases más importantes – activity, application
o service – se encuentran en este paquete.
• android.bluetooth: clases para el manejo de la tecnología bluetooth.
• android.database: contiene clases para explorar los datos devueltos por un
proveedor de contenidos.
• android.database.sqlite: posee las clases necesarias para el manejo de
bases de datos SQLite. Este es un sistema de gestión de bases de de datos que no está
basado en el modelo cliente-servidor en el que el SGBD es un proceso independiente,
sino que la biblioteca SQLite se enlaza con la aplicación pasando a ser parte integral
de la misma. Este es el sistema comúnmente usado a la hora de instalar bases de datos
locales en un dispositivo Android.
• android.graphics: proporciona herramientas gráficas de bajo nivel tales como
filtros de color, puntos, o rectángulo, que permiten dibujar en la pantalla.
• android.hardware: provee soporte para dispositivos hardware que pueden no
estar presente en todos los teléfonos móviles ( por ejemplo la cámara ).
• android.media: clases para controlar las diferentes interfaces de audio y video.
• android.net.wifi: gestión de la funcionalidad wifi del dispositivo.
2.1. IDEs
El IDE que acapara casi la totalidad de los productos desarrollados para Android es Eclipse, y
por ello la mayor parte de la documentación que se puede encontrar en webs y manuales hace
referencia a este entorno de desarrollo. Eclipse es multiplataforma y de código abierto y soporta
varios lenguajes de programación. El paquete Eclipse IDE for Java Developers (descargable a
través de http://www.eclipse.org/downloads/) incluye las herramientas esenciales para la
programación en Java y se puede usar por tanto para desarrollar aplicaciones para Android en
conjunción con el SDK de Android y el plugin ADT ( Android Development Tools ) for Eclipse.
Toda la información relativa a estos dos elementos se puede encontrar en la web Android
Developers.
También existe la posibilidad de programar con otros IDEs, pero estos cuentan con un uso
y apoyo mucho menores, y en consecuencia menor es la documentación al respecto siendo más
complicado resolver los problemas que surjan a la hora de configurar el entorno y
desarrollar aplicaciones. El IDE NetBeans es el segundo en importancia – a mucha distancia
de Eclipse - y es posible encontrar información sobre su configuración para Android en la
siguiente dirección: http://wiki.netbeans.org/IntroAndroidDevNetBeans
-7 -
Desarrollo de aplicaciones en Android
Además se ha desarrollado un plugin para el IDE Eclipse llamado ADT, el cual facilita
mucho la depuración de programas para esta plataforma.
2.2.1 Emulador
Imita todo el hardware y software de un dispositivo móvil típico, aunque pueda tener algunas
limitaciones. El emulador de Android proporciona una buena variedad de métodos de
navegación: las teclas de control, que puede "presionar" con el ratón simulando el apuntador de
un dispositivo móvil o el teclado para generar eventos para su aplicación. También ofrece una
pantalla en la que se muestran las aplicaciones desarrolladas, junto con las otras aplicaciones
Android, así como varias capacidades de depuración que permiten simular el recibimiento de
llamadas telefónicas, mensajes de texto o conexiones mientras la aplicación se ejecuta. Durante
el desarrollo de una aplicación, el emulador de Android puede iniciarse como una aplicación
independiente desde una línea de comandos ( útil cuando quiera establecer los parámetros de la
simulación ) o puede usarlo como parte de su entorno de desarrollo Eclipse, donde existen otros
métodos de configuración.
Las únicas limitaciones que el emulador presenta en su versión actual ( Android SDK 2.1 )
son:
• No hay soporte para hacer o recibir llamadas de teléfono reales. Se puede simular
llamadas telefónicas ( realizadas y recibidas ) a través del emulador de la consola.
• No hay soporte para las conexiones USB ni Bluetooth.
• No hay soporte para cámara de captura de video ( entrada ).
• No hay soporte para los auriculares del dispositivo.
• No hay soporte para determinar el nivel de carga de la batería y el estado de carga de
CA.
• No hay soporte para determinar que se ha insertado/expulsado una tarjeta SD.
A pesar de todo está en constante mejora y muchas de estas limitaciones serán eliminadas.
3.1. Funcionamiento
Dalvik es una máquina virtual intérprete que ejecuta archivos en el formato Dalvik Executable
(*.dex), un formato optimizado para el almacenamiento eficiente y ejecución mapeable en
memoria. Su objetivo fundamental es el mismo que cualquier máquina virtual, permite que el
código sea compilado a un bytecode independiente de la máquina en la que se va a ejecutar, y la
máquina virtual interpreta este bytecode a la hora de ejecutar el programa. El hecho de no
utilizar la máquina virtual de Java (aparte de posibles aspectos legales y de propiedad) es la
necesidad de optimizar al máximo los recursos y enfocar el funcionamiento de los programas
hacia un entorno de escasos recursos en cuanto a memoria, procesador y almacenamiento.
La máquina virtual Dalvik ( DalvikVM, Dalvik virtual machine ) está basada en registros y
puede ejecutar clases compiladas por un compilador Java y que posteriormente han sido
convertidas al formato nativo usando la herramienta “dx”. La máquina virtual corre por encima
de un kernel Linux 2.6, sobre el cual delega las tareas relacionadas con la gestión de hilos y
memoria a bajo nivel. La DalvikVM ha sido también optimizada para que haya múltiples
instancias suyas funcionando con un coste muy bajo de memoria. El hecho de usar varias
máquinas virtuales protege las aplicaciones, de forma que el fallo o cierre inesperado de una de
ellas no afecte para nada a las demás.
El hecho de funcionar sobre un núcleo Linux implica que es posible escribir aplicaciones
en C/C++ que funcionen directamente sobre el kernel. Aunque es posible hacer esto, solo en
ciertas ocasiones es ventajoso.
3.3. Optimización
Es capaz de reducir bastante el tamaño del programa buscando información duplicada en las
diversas clases y reutilizándola. La “recogida de basura” (liberar el espacio de objetos ya no
accesibles) ha sido perfeccionada a fin de mantener siempre libre la máxima memoria posible.
-9 -
Desarrollo de aplicaciones en Android
Android hace un uso extenso del XML como forma de definir las interfaces gráficas y otros
elementos. Los archivos XML tienen que ser linkeados igualmente a la hora de compilar y son
convertidos igualmente a bytecode para mejorar el rendimiento.
4.1. Activity
Las actividades son probablemente el elemento más común en una aplicación para Android.
Una actividad se puede definir como una única pantalla o interfaz dentro de una aplicación. Las
actividades mostrarán una interfaz de usuario basada en vistas ( Views ) y responderá a
eventos. En un sentido estricto, es posible construir una actividad sin interfaz de usuario, sin
embargo no es lo apropiado ya que tenemos los Services y Content Providers destinados
-11-
Desarrollo de aplicaciones en Android
a esa finalidad. De cualquier forma hay que remarcar que la actividad es responsable de mostrar
la interfaz gráfica, sin embargo ésta no forma parte de la actividad. Todos los elementos gráficos
y visuales se definirán dentro de una vista, View. Ésto garantiza la separación del aspecto
funcional del aspecto visual, facilitando en gran medida el desarrollo posterior.
Cada actividad se implementa como una única subclase que hereda de la clase
android.app.Activity. De esta forma, no necesitamos preocuparnos de muchos de los
aspectos relacionados con el funcionamiento de las actividades ya que por herencia nuestra
actividad contendrá ya esa funcionalidad. De nuevo estamos reaprovechando código común a
una familia de objetos haciendo uso de la herencia.
Normalmente una aplicación constará de varias actividades, por ejemplo una aplicación
que gestiona mensajes puede tener una pantalla de configuración, otra para escribir mensajes,
una tercera para elegir el contacto al cual se desea enviar el mensaje y otra más para navegar por
los mensajes enviados y recibidos. Cada una de estas pantallas estará implementada por una
actividad diferente. Una actividad puede iniciar otra actividad, por ejemplo al pulsar un botón.
De esta forma iremos navegando por las distintas pantallas de la aplicación, siendo cada una de
ellas una actividad.
Como se vio anteriormente una actividad puede iniciar otra dentro de la misma aplicación.
De la misma forma puede iniciar otra de una aplicación externa. Si nuestra actividad necesita
hacer uso de una posición en un mapa por ejemplo, podemos recurrir a otra actividad que
gestiona mapas y posiciones, solo necesitamos hacer uso de los Intents, que veremos
posteriormente. De esta forma estaremos haciendo uso de actividades externas que para el
usuario aparecerán como integradas en nuestra aplicación.
4.1.2 Tareas
Una tarea es lo que el usuario percibe como una aplicación. Es una pila de actividades que se
han ido llamando sucesivamente, algunas de ellas posiblemente fuera de la aplicación original.
No es posible reordenar o navegar por la pila de actividades, al igual que en cualquier pila solo
podemos acceder y cerrar la actividad superior o crear una nueva encima.
El sistema Android permite iniciar varias tareas. Cuando el usuario pulsa el botón HOME o
BACK, toda la tarea es minimizada mientras el usuario ejecuta otras aplicaciones. Al volver,
toda la tarea se restaura y de nuevo la última actividad de la pila pasa a estar activa y accesible
para el usuario.
En este ejemplo la actividad desea ver los datos de contacto de la persona con ID 123 para
lo cual lanza el Intent correspondiente, con los campos indicados anteriormente.
Cuando una actividad lanza un Intent, normalmente se trata de una invocación implícita.
La actividad indica la tarea que desea realizar y el sistema asigna el Intent a la aplicación
más apropiada. Otra forma de proceder es que la actividad indique explícitamente el destinatario
del Intent, en este caso se tratará de una invocación explícita. Sin embargo esto no es
recomendable ya que estamos creando una dependencia innecesaria, y el hecho de desinstalar el
paquete del destinatario provocará errores en la aplicación emisora del Intent.
4.3. Service
Un servicio es un proceso cuyo periodo de ejecución se extiende durante un tiempo largo y que
carece de interfaz gráfica. Un buen ejemplo sería un reproductor de música. La interfaz y el
proceso de elegir y activar una lista de reproducción estaría manejado por una actividad, sin
embargo la reproducción en si estaría manejado por un servicio, ya que el usuario espera que la
música siga sonando aunque lance nuevas actividades. En cualquier momento una actividad
puede asociarse a un servicio para modificar su comportamiento o detenerlo. En el ejemplo
anterior, el usuario podría regresar a la actividad que gestiona el reproductor para saltar la
canción que está sonando.
Los servicios pueden ser clasificados en locales y remotos. Un servicio local solo puede ser
accedido por la aplicación que lo contiene. En el ejemplo anterior el servicio probablemente
sería local ya que no tenemos ningún interés en que otras aplicaciones puedan detener la
reproducción o pasar canciones.
Un servicio remoto permite a otras aplicaciones asociarse con él mediante el método
bindService() para de esta forma tomar el control. Si por ejemplo estuviéramos
interesados en que sonara una canción en concreto cuando iniciamos el lector de mensajes el
servicio de reproducción de música sería remoto.
Como ya hemos dicho, un servicio carece de interfaz gráfica, sin embargo tiene la
capacidad de lanzar notificaciones para informar al usuario.
4.6. Otros
Hemos mencionado, al hablar de las Actividades, que poseen una interfaz gráfica hacia el
usuario y sin embargo la codificación del aspecto gráfico no se realiza dentro del objeto
Actividad. Esto es así porque poseen la función setContentView(View) mediante la cual
muestran la interfaz almacenada en un objeto de tipo View.
No vamos a entrar en detalles sobre la composición e implementación de las diversas
opciones gráficas en View pero queremos remarcar esta separación entre el aspecto funcional
de la aplicación, la actividad; y el aspecto gráfico contenido en View. Esta separación es un
elemento básico de la programación orientada a objetos, cada objeto es responsable de una única
tarea y se comunica con los demás mediante funciones establecidas. En cualquier momento
podremos modificar cualquier aspecto de la actividad o de la vista sin afectar a la otra parte,
siempre que respetemos los canales de comunicación.
5.1. Manifiesto
Es un archivo XML que describe e indica los componentes de la aplicación que se
esté desarrollando. Se encuentra en el directorio fuente del proyecto, siendo estas sus
principales nodos ( etiquetas ) y propósitos:
-19-
Desarrollo de aplicaciones en Android
• <manifest>: Es el nodo padre o raíz, que contendrá al resto. Indica el nombre del
paquete que el desarrollador crea para su aplicación.. Se usa también para guardar el
número de versión de la aplicación si existiesen varias, y así poder saber cual es la más
reciente ( versionCode ), lo cual es muy importante en el desarrollo de un proyecto
software. Este no es sin embargo el número de versión que se muestra a los usuarios de la
aplicación, sino el indicado en versionName.
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="android.miaplicacion"
android:versionCode="1" android:versionName="1.0" >
• <uses-permission>: Declara los permisos que la aplicación. necesita ( algunos
ejemplos son INTERNET, READ_CONTACTS, CAMERA…). Por seguridad serán
presentados al usuario durante la instalación por si quisiese denegarlos, ya que sino se
podría dar el caso de que una aplicación maligna tuviese permiso SEND_SMS y se
dedicase a mandar mensajes de texto a otros terminales sin el conocimiento del usuario.
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" >
• <permission>: Define nuevos permisos que otras aplicaciones requerirán para poder
acceder a partes restringidas de esta. A dichos permisos se les podrá asignar un nivel de
protección ( normal, dangerous, … ) para saber si durante la ejecución se pueden
conceder con directamente o mediante una nueva confirmación del usuario e incluso se
podrán agrupar varios dentro de un mismo grupo. Para esto se creará un
<permission-group> al que se dará un nombre, y después se asignará dicho
nombre a la propiedad android:permissionGroup de <permission>. Las
otras aplicaciones harán uso de cada permiso o de un grupo entero mediante <uses-
permission>.
• <uses-sdk>: El desarrollo de la plataforma Android hace que vaya aumentando el
número de niveles de la API, proveyendo estos nuevas clases y/o paquetes, e incluso
reemplazando partes que se han mejorado y quedan ahora obsoletas ( aunque la política
empleada es la de mantener ambas partes para evitar la incompatibilidad de antiguas
aplicaciones en nuevas versiones ). En ocasiones también se incluyen nuevos nodos y
propiedades para el manifiesto. Es por esto que mediante tres propiedades de esta
etiqueta se controlan sobre que versiones de la plataforma puede ejecutarse una
aplicación. android:minSdkVersion especifica el nivel mínimo de la API en el
que puede funcionar ( si no se cumple la aplicación no comenzará a ejecutarse ) y posee
el valor 1 por defecto y android:maxSdkVersion: el máximo ( aunque es habitual
no declarar valor máximo ). Por su parte, android:targetSdkVersion indica el
nivel de la API sobre el cual está diseñado para ejecutarse la aplicación ( nivel óptimo ).
Ocurre que a veces la aplicación pueda usar elementos o comportamientos de dicho
nivel, en lugar de limitarse a los existentes en el nivel mínimo que limitan al programa.
• <application>: Indica mediante sus propiedades ciertos metadatos de la aplicación
como el título e icono. Es el nodo padre de <activity>, <services>,
<provider> y <receiver> ( y estos a su vez contienen definiciones de <intent-
filters> entre otros datos ). Este nodo especifica también si se está en modo debug o
no, da nombre al proceso sobre el que correrá la aplicación o asigna un tema visual
común a todas las actividades.
Por supuesto existen otras muchas expresiones para describir la aplicación, incluso algunas
usadas únicamente para el desarrollo y testeo de la aplicación, siendo sin embargo las aquí
mencionadas las de uso más común.
5.2. Layout
Aunque es posible usando el lenguaje Java instanciar y posicionar widgets a nuestra
activity, la forma más común de realizar dicha tarea será usar un fichero XML denominado
Layout ( pueden crearse varios, lo suyo es uno por cada activity ). El principal motivo para
hacer esto es que facilita la utilización de herramientas específicas de creación de modelos de
GUI, en las que el usuario va disponiendo los widgets sobre la pantalla según le parezca y con
las propiedades que desee, todo ello sin tener que programar puesto que el código sería
simultáneamente generado por la herramienta usada. Además el hecho de crear la interfaz
apartada de las funcionalidades permite facilitar la separación de la vista y el modelo de datos.
En la imagen superior se observa que se ha creado una interfaz con tres widgets ( botón,
texto y reloj ) que posee como fondo una imagen añadida por el usuario a los recursos. Para
modificar la interfaz durante la ejecución necesitaremos del archivo R.java que corresponde
a una clase no heredable y autogenerada. Esta contiene otras clases estáticas ( una por
tipo de recurso ) con identificadores para cada recurso ( layouts y widgets entre ellos ),
permitiendo acceder a ellos desde el código Java de la aplicación.
5.2.1 Contenedores
Existen unos elementos llamados contenedores ( también denominados layouts, pero no
deben confundirse con los archivo Layout ) que ayudan a posicionar y agrupar los
widgets dentro de ellos. Dichos contenedores pueden contener a su vez a otros. Así pues
en cada archivo xml usado para definir un modelo de interfaz gráfica se suelen incluir
diferentes contenedores ( normalmente por lo menos uno que ocupe toda la pantalla y
que contenga al resto ) que ajusten totalmente lo que aparece en la ventana respecto a lo
que quiere el diseñador. Estos son los más comunes:
• LinearLayout: Alinea a los widgets uno detrás de otro vertical u horizontalmente
( según se especifique en la propiedad android:orientation. ). Permite
además configurar el tamaño de estos: cada widget dentro de un contenedor posee .las
propiedades android:layout_width y android:layout_height que
especifican su anchura y altura. Estas propiedades pueden tomar tres valores: un valor
numérico que indica los píxeles exactos; wrap_content que hace que el widget
ocupe justo el tamaño que necesite; o fill_parent para que el widget se expanda
para ocupar todo el espacio que quede disponible en el contenedor. Se puede ajustar
también la distancia del widget a cada uno de los cuatro bordes del layout ( mediante
las propiedades padding ).
• RelativeLayout: dispone a cada widget basándose en su relación con el resto, p.
ej si quisiesemos a un widget A debajo y a la izquierda de otro B, y encima de C.
• TableLayout: permite crear una tabla invisible. . A su vez, este contenedor se
compone de varios TableRow ( filas ) El número de filas será especificado por el
programador, mientras que el número mínimo de columnas será igual al número de
widgets de la fila más larga, siendo posible que un widget ocupe varias celdas de una
misma fila.
5.2.2 Widgets
Como ya se ha visto, el SDK de Android proporciona una colección de widgets, todos ellos con
su correspondiente etiqueta XML y su clase, yendo estos desde los más simples hasta algunos
más complejos como las galerías de imágenes. A continuación se listan algunos de los más
comunes con ejemplos ilustrativos de código:
• TextView: una etiqueta de texto no editable por el usuario. Se suele usar para
identificar widgets adyacentes. La clase TextView posee los diferentes métodos para
su modificación. En el siguiente ejemplo se observa como se procedería si se
quisiese cambiar el texto “HELLO” de la Ilustración 10 por otro durante la
ejecución:
TextView texto = (TextView)findViewById(R.id.TextView01);
texto.setText("HOLA");
En la primera línea se observa como el método findViewById(), de la clase Activity,
permite instanciar cualquier elemento de IG declarado en la carpeta de recursos,
siendo necesario hacer un casting a la clase correspondiente. Ya en la segunda línea se
ejecuta el cambio de texto haciendo uso de la instancia creada.
• Button: es un botón del cual se pueden modificar todos los aspectos de su
apariencia. Su objetivo es realizar una acción al ser pulsado. Para ejemplificar esto se
va a mostrar como se haría para que al pulsar un botón se pase de la activity
actual a otra distinta. Este sería el código de la acción a realizar:
private OnClickListener accionBoton = new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(Actividad.this, NuevaActividad.class);
startActivity(intent);
finish();
}
};
Este código realiza el cambio mediante un intent, iniciando la nueva actividad y
finalizando la actual. Para que sea esto lo que se ejecute al pulsar el botón es necesario
añadir lo siguiente en la actividad: boton.setOnClickListener(accionBoton);
Hay que resaltar además que Button hereda de TextView, lo que le permite usar
los métodos de esta.
• EditText: es una clase derivada de TextView empleada como texto editable. En
el Layout se puede configurar mediante diversas propiedades para que actúe como el
diseñador quiera: android:capitalize para poner o automáticamente la
primera letra en mayúscula, android:autoText para obtener ayuda ortográfica,
android:singleLine para controlar si el texto editable es de una o varias
líneas, etc…
• CheckBox: casilla de verificación con dos estados: marcado y sin marcar. Su clase
tiene un método, isChecked(), para comprobar su estado. Hereda indirectamente
de Button a través de CompoundButton.
• RadioButton: hereda también de CompoundButton y se suelen usar en grupo
mediante RadioGroup ( subclase de LinearLayout ). Esta última clase permite
conocer cuál de todos los botones que agrupa es el que está marcado (
getCheckedRadioButtonId() ), así como desmarcar todos ( clearCheck () ).
• Image View: permite instar imágenes. Estas pueden corresponden a los recursos,
pero también se puede establecer basándose en el contenido de una URI, usando el
método SetImage().
5.2.3 Reutilización
A pesar de que Android ofrece una buena variedad de widgets con la posibilidad de poderlos
modificar a gusto del diseñador, muchas veces esto no es suficiente. Sería más útil poder
reutilizar una interfaz compleja con alguna utilidad concreta que se suela repetir comúnmente en
las aplicaciones, por ejemplo un diálogo de identificación o login que cuente con un una
etiqueta, un texto editable, un botón y una barra de progreso. Esta necesidad ha sido satisfecha
en los Layouts de Android mediante el uso del nodo <include>, que requiere que se le
indique una referencia al Layout que se quiere incluir dentro de otro, e incluso hacer alguna
modificación sobre él. Esto también es útil cuando existen varios Layouts con el mismo
propósito pero diferentes estilos, pudiéndose incluir varios y hacer la elección de uso durante la
ejecución.
La reusabilidad de la funcionalidad de dichas interfaces suele ir de la mano de la
Activity creada ( heredada ) para dicho propósito, que tendrá su propio fichero .java,
volviéndolo a usar cuando se use dicha interfaz gráfica en otra aplicación.
6.1.1 MapView
Representa un mapa gracias a la información que obtiene del servicio del Google Maps. Esta
clase hereda de android.view.ViewGroup y puede ser añadida al Layout.
Posee métodos para realizar los siguientes cometidos:
• Controlar el modo de vista: setTraffic(boolean), boolean
isSatellite(), setStreetView(boolean)…
• Mostrar diferentes controles para hacer uso del mapa:
setBuiltInZoomControls(boolean), displayZoomControls()…
• Guardar su estado: onSaveInstanceState(android.os.Bundle)
• Control de eventos: onSizeChanged(...), onTouchEvent(...), …
6.1.2 MapActivity
Es la clase principal que contendrá el código con el que se haga uso de los diferentes servicios
ofrecidos por Google Maps. Es una subclase de Activity, por lo que sus métodos y manejo
es idéntico: creando una subclase a la medida de lo que necesite el desarrollador.
La clase MapView anteriormente comentada solo puede ser instanciada en una
MapActivity que se haga cargo de la gestión de sus servicios y su eliminación. Esto se debe
a que depende de varios hilos para acceder a la red y el sistema de archivos en segundo plano, y
dichos hilos deben ser guiados en conjunción con el ciclo de vida del MapActivity.
Únicamente se admite un MapActivity por proceso, en caso contrario se pueden
obtener resultados inesperados.
6.1.3 MapController
Gestiona el manejo de un mapa, como desplazamientos o zoom. Se obtiene como valor de
retorno de MapView.getController(). Estos son algunos de sus métodos:
-25-
Desarrollo de aplicaciones en Android
6.2. Ejemplo
Se presenta ahora un sencillo ejemplo en el cual se va a obtener un mapa sobre la ciudad de
Salamanca , pintandose dos círculos concéntricos encima de esta ( se omiten del código los paquetes
importados ).
Para esto es necesario conocer la existencia de la clases Overlay del paquete de GMaps.
Esta permite dibujar elementos sobre el mapa y gestionar los eventos que sobre el dibujo
acontezcan. El modo de uso es por herencia: se debe de hacer una subclase y crear las instancias
de esta que sean necesarias. Posteriormente serán añadidas al mapa insertándolas en la lista
devuelta por MapView.getOverlays(). Para su instanciación requiere de un objeto gráfico
de la clase android.graphics.Canvas que será el que sea pintado en el MapView. Para
el ejemplo propuesto este sería el código del Overlay:
public class Simbolo extends Overlay {
}
}
Se explica brevemente: se instancia un objeto Paint para cada círculo, se obtiene el centro del
mapa y se traduce a píxeles, para posteriormente proceder a dibujar los dos círculos sobre dicho
centro mediante el objeto Canvas pasado por parámetro.
Ese código serviría para pintar sobre el mapa. Ahora solo queda proceder a la creación del
mapa dentro de un MapActivity:
vistamapa.getOverlays().add(simb);
}
}
Este sería el resultado obtenido:
7.1. Location
Es el paquete que provee las clases necesarias para el manejo de GPS en Android. Para poder
usarlo es necesario otorgar el permiso ACCESS_FIND_LOCATION a la aplicación. Sus
elementos más relevantes son:
• Location: clase que representa una localización geográfica en un tiempo concreto.
• LocationManager: clase para gestionar el dispositivo de localización. Permite
actualizaciones periódicas de la situación geográfica del dispositivo, o disparar un
evento específico cuando el dispositivo entra en la proximidad de una zona
geográfica determinada. Así por ejemplo para conocer la situació actual se utiliza
LocationManager.getLastKnownLocation("gps").
• Geocoder: clase que permite traducir entre direcciones físicas y coordenadas en
latitud y longitud, y viceversa.
• LocationListener: interfaz que permite implementar una clase que captura los
eventos asociados al dispositivo de localización.
Tiene múltiples utilidades, como pintar la posición del usuario en un mapa o transmitirla a
otros dispositivos. Además es posible simular un GPS NMEA-compatible en el emulador, dado
que la consola proporciona un comando que permite establecer la posición geográfica actual. Su
sintaxis es la siguiente: geo <fix|nmea>, donde el primer parámetro sirve para especificar
la longitud y latitud en grados, e incluso la altitud en metros si fuese necesario; mientras que el
segundo permite enviar sentencias NMEA 0183.
7.2. Telephony
No conviene que nos olvidemos que el S.O. Android en la mayoría de los casos se
ejecutará sobre un teléfono móvil. Esto puede suponer ciertos problemas:
• Si la aplicación hace uso de un alto porcentaje de CPU sería un impedimento de cara
a que se puedan recibir llamadas.
• Que las aplicaciones desarrolladas no colaboren convenientemente con el resto de
aplicaciones y el S.O, por ejemplo no desvaneciéndose a segundo plano cuando hay
una llamada entrante.
• No optimizar los recursos de forma que se agote la batería en poco tiempo ( el usuario
no podría seguir usando el teléfono ), o que haya fugas de memoria que bloqueen el
teléfono completamente, etc…
Pero no todo es malo, puesto que ese hecho le añadirá más funcionalidad: los usuarios
pueden enviar y recibir llamadas, pero ahora además también podrán ser ayudados a ello.
Supongamos por ejemplo que un empresario necesita una aplicación de gestión en su móvil.
Dicha aplicación podría incorporar la posibilidad de poder llamar o mandar un mensaje
directamente desde esta a los clientes y/o proveedores, con un solo click y sin tener que
abandonar la aplicación.
Es por esto que Android incorpora un paquete, android.telephony, que permite
controlar la información del servicio telefónico y su manipulación: acceder a los contactos,
-29-
Desarrollo de aplicaciones en Android
dividir un texto en varios SMS para que puedan ser enviados, gestionar el envío y recepción de
mensajes, realizar llamadas, etc…
El paquete en cuestión contiene varias clases para realizar dichas operaciones, aunque la
que se encarga de regular y controlar el dispositivo es TelephonyManager. La forma de
obtener un objeto de esta clase es la siguiente:
TelephonyManager telefono=(TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
Esta forma es similar a la usada para el GPS o el servicio wifi. Teniendo en cuenta además
que se trata de un servicio, habrá que hacer la correspondiente adición en el manifiesto.
Una vez instanciada, podremos hacer uso de sus numeros métodos. Por ejemplo
getLine1Number() retorna el número de teléfono propio,
getNetworkOperatorName() devuelve el nombre del operador de telefonía utilizado,
etc… Pero el método más importante es getCallState(). Este devuelve una constante que
indica el estado de llamada del dispositivo, valor que deberá tenido en cuenta antes de realizar
otras operaciones. Puede ser:
• CALL_STATE_IDLE: El teléfono no está en uso.
• CALL_STATE_RINGING: Llamada solicitada.
• CALL_STATE_OFFHOOK: Llamada en progreso.
A pesar de todo, el emulador no está preparado aun para simular muchas de las opciones
del paquete, aunque provee un comando sms para simular envío de mensajes hacia el emulador.
-31-
Bibliografía
• Murphy, Mark. L ( 2009 ): Beginning Android
• Hashimi, Sayed Y. y Komatineni , Satya ( 2009 ): Pro Android
• Meier, Reto ( 2009 ): Professional Android Application Development
• Burnette, Ed ( 2008 ): Hello Android
• Gramlich, Nicolas: AndBook
• Android Developers: http://developer.android.com/
• Wikipedia: http://es.wikipedia.org/
• Kronox: http://kronox.org/
• Androlib: http://www.androlib.com/
• Eliax: http://eliax.com/index.cfm?post_id=4563
• Google Mobile: http://www.google.com/mobile/maps/
• OpenIntents: http://code.google.com/p/openintents/w/list
• Package com.google.android.maps: http://code.google.com/intl/es-ES/android/add-
ons/google-apis/reference/com/google/android/maps/package-summary.html
-33-