Vous êtes sur la page 1sur 32

1.

Introducción
1.1 ¿Qué es Android?
Android es un nuevo conjunto de herramientas de software de código abierto para
teléfonos móviles que fueron creadas por Google y Open Handset Alliance. La idea de
Android se resume en:
"Android - La imaginación es el límite"
Tanto si es usted un aficionado o un programador profesional, si lo está haciendo por
diversión o con fines de lucro, es el momento para aprender más sobre el desarrollo de
Android. Este manual le ayudará a empezar.

1.2 Historia de Android (Open Handset


Alliance)
Los dispositivos móviles constituyen cada vez más una realidad que ofrece al usuario, en
un mismo y reducido aparato, funciones de comunicación y procesamiento de datos que van
mucho más allá de las simples llamadas telefónicas o la ejecución de aplicaciones básicas. El
gigante de Internet Google ha presentado un nuevo sistema operativo para este tipo de
dispositivos, Android, que busca ser una firme alternativa a otros sistemas, ya ampliamente
extendidos, como Symbian o Windows Mobile. Android es un sistema operativo del móvil que
utiliza una versión modificada del kernel de Linux.
Fué desarrollado inicialmente por Android Inc, una firma más tarde comprada por Google,
y actualmente por el Open Handset Alliance. Se permite a los desarrolladores escribir código
usando el lenguaje Java, y controlar el dispositivo a través de bibliotecas Java.
El descubrimiento de la distribución de Android, el 5 de noviembre de 2007 fué anunciado
por la fundación Open Handset Alliance, un consorcio de 47 empresas de hardware, software
y telecomunicaciones dedicadas al fomento de estándares abiertos para dispositivos
móviles. Google sin embargo, ha sido quien ha publicado la mayoría del código fuente de
Android bajo la licencia de Software Apache, una licencia de software libre y de código abierto
a cualquier desarrollador.

2. Conceptos Generales
2.1 Características
 Marco de aplicación que permite la reutilización y el reemplazo de los componentes.
 Dalvik optimizado para dispositivos móviles.
 Navegador integrado basado en la apertura del motor WebKit.
 Gráficos mejorados con la biblioteca de gráficos 2D; gráficos en 3D basado en la
especificación OpenGL ES 1.0.
 SQLite para el almacenamiento de datos estructurados.
 Soporte para audio, vídeo, y formatos de imagen (MPEG4, H.264, MP3, AAC, AMR,
JPG, PNG, GIF).
 Telefonía GSM (dependiente del hardware).
 Bluetooth, EDGE, 3G, y Wi-Fi (dependiente del hardware).
 Cámara, GPS, brújula, y acelerómetro (dependiente del hardware).
 Entorno de desarrollo muy completo, incluyendo un emulador, herramientas de
depuración, de memoria, perfiles de rendimiento, y un plug-in para el IDE de Eclipse.

2.2. Arquitectura Android

Como ya se ha mencionado, Android es una plataforma para dispositivos móviles que


contiene una pila de software donde se incluye un sistema operativo, middleware y
aplicaciones básicas para el usuario.

En las siguientes líneas se dará una visión global por capas de cuál es la arquitectura
empleada en Android. Cada una de estas capas utiliza servicios ofrecidos por las anteriores, y
ofrece a su vez los suyos propios a las capas de niveles superiores, tal como muestra la
siguiente figura ((c) Google):

 Aplicaciones: Este nivel contiene, tanto las incluidas por defecto de Android como
aquellas que el usuario vaya añadiendo posteriormente, ya sean de terceras empresas
o de su propio desarrollo. Todas estas aplicaciones utilizan los servicios, las API y
librerías de los niveles anteriores.
 Framework de Aplicaciones: Representa fundamentalmente el conjunto de herramientas
de desarrollo de cualquier aplicación. Toda aplicación que se desarrolle para Android,
ya sean las propias del dispositivo, las desarrolladas por Google o terceras compañías,
o incluso las que el propio usuario cree, utilizan el mismo conjunto de API y el mismo
"framework", representado por este nivel.
Entre las API más importantes ubicadas aquí, se pueden encontrar las siguientes:
• Activity Manager: Conjunto de API que gestiona el ciclo de vida de las
aplicaciones en Android.
• Window Manager: Gestiona las ventanas de las aplicaciones y utiliza la librería
Surface Manager.
• Telephone Manager: Incluye todas las API vinculadas a las funcionalidades
propias del teléfono (llamadas, mensajes, etc.).
• Content Provider: Permite a cualquier aplicación compartir sus datos con las
demás aplicaciones de Android. Por ejemplo, gracias a esta API la información de
contactos, agenda, mensajes, etc. será accesible para otras aplicaciones.
• View System: Proporciona un gran número de elementos para poder construir
interfaces de usuario (GUI), como listas, mosaicos, botones, "check-boxes",
tamaño de ventanas, control de las interfaces mediante teclado, etc. Incluye
también algunas vistas estándar para las funcionalidades más frecuentes.
• Location Manager: Posibilita a las aplicaciones la obtención de información
de localización y posicionamiento.
• Notification Manager: Mediante el cual las aplicaciones, usando un mismo
formato, comunican al usuario eventos que ocurran durante su ejecución: una
llamada entrante, un mensaje recibido, conexión Wi-Fi disponible, ubicación en un
punto determinado, etc. Si llevan asociada alguna acción, en Android
denominada Intent, (por ejemplo, atender una llamada recibida) ésta se activa
mediante un simple clic.
• XMPP Service: Colección de API para utilizar este protocolo de intercambio de
mensajes basado en XML.
 Librerías: La siguiente capa se corresponde con las librerías utilizadas por Android.
Éstas han sido escritas utilizando C/C++ y proporcionan a Android la mayor parte de
sus capacidades más características. Junto al núcleo basado en Linux, estas librerías
constituyen el corazón de Android.
Entre las librerías más importantes ubicadas aquí, se pueden encontrar las siguientes:
• Librería libc: Incluye todas las cabeceras y funciones según el estándar del
lenguaje C. Todas las demás librerías se definen en este lenguaje.
• Librería Surface Manager: Es la encargada de componer los diferentes
elementos de navegación de pantalla. Gestiona también las ventanas
pertenecientes a las distintas aplicaciones activas en cada momento.
• OpenGL/SL y SGL: Representan las librerías gráficas y, por tanto, sustentan
la capacidad gráfica de Android. OpenGL/SL maneja gráficos en 3D y permite
utilizar, en caso de que esté disponible en el propio dispositivo móvil, el hardware
encargado de proporcionar gráficos 3D. Por otro lado, SGL proporciona gráficos en
2D, por lo que será la librería más habitualmente utilizada por la mayoría de las
aplicaciones. Una característica importante de la capacidad gráfica de Android es
que es posible desarrollar aplicaciones que combinen gráficos en 3D y 2D.
• Librería Media Libraries: Proporciona todos los códecs necesarios para el
contenido multimedia soportado en Android (vídeo, audio, imágenes estáticas y
animadas, etc.)
• FreeType: Permite trabajar de forma rápida y sencilla con distintos tipos de
fuentes.
• Librería SSL: Posibilita la utilización de dicho protocolo para establecer
comunicaciones seguras.
• Librería SQLite: Creación y gestión de bases de datos relacionales.
• Librería WebKit: Proporciona un motor para las aplicaciones de tipo
navegador y forma el núcleo del actual navegador incluido por defecto en la
plataforma Android.
 Tiempo de ejecución de Android: Al mismo nivel que las librerías de Android se sitúa el
entorno de ejecución. Éste lo constituyen las Core Libraries, que son librerías con
multitud de clases Java y la máquina vistual Dalvik.
 Núcleo Linux: Android utiliza el núcleo de Linux 2.6 como una capa de abstracción
para el hardware disponible en los dispositivos móviles. Esta capa contiene los drivers
necesarios para que cualquier componente hardware pueda ser utilizado mediante las
llamadas correspondientes. Siempre que un fabricante incluye un nuevo elemento de
hardware, lo primero que se debe realizar para que pueda ser utilizado desde Android
es crear las librerías de control o drivers necesarios dentro de este kernel de Linux
embebido en el propio Android.

2.3. Dalvik VM

Dalkiv es el nombre de la máquina virtual que utiliza Android (DalvikVM), la cual está
basada en registro, diseñada y escrita por "Dan Bornstein" y algunos otros ingenieros de
Google. En ella podemos encontrar una gran diferencia con respecto a la máquina virtual Java
(JVM), ya que la máquina virtual de Google no está basada en una pila.
Dalvik.equals(Java) == false
¿Por qué " Dalvik "? Éste nombre fue elegido por Bornstein en honor a Dalvík, un pueblo
de pescadores de Eyjafjörður(Islandia), donde vivieron algunos de sus antepasados.
Dalvik VM es un intérprete que sólo ejecuta los archivos ejecutables con formato .dex
(Dalvik Executable). Este formato está optimizado para el almacenamiento eficiente de la
memoria, lo cual consigue delegando en el kernel la gestión de hilos (multithreading), de
memoria y de procesos.
La herramienta "dx" incluida en el SDK de Android permite transformar las clases
compiladas (.class) por un compilador de lenguaje Java en formato .dex.
La Dalvik VM también ha sido optimizada para correr múltiples instancias con muy baja
huella.
Diferencias con una máquina virtual Java normal

En primer lugar, la máquina virtual de Dalvik toma los archivos generados por las clases
Java y los combina en uno o más archivos ejecutables Dalvik (. dex), los cuales a su vez son
comprimidos en un sólo fichero .apk (Android Package) en el dispositivo. De esta forma,
reutiliza la información duplicada por múltiples archivos .class, reduciendo así la necesidad de
espacio (sin comprimir) a la mitad de lo que ocuparía un archivo .jar.

En segundo lugar, Google ha mejorado la recolección de basura en la máquina virtual de


Dalvik, pero ha preferido omitirjust-in-time (JIT), en esta versión por lo menos. La empresa
justifica esta elección diciendo que muchas de las bibliotecas centrales de Android, incluyendo
las bibliotecas de gráficos, están implementadas en C y C++. Del mismo modo, Android
proporciona una biblioteca de C optimizada para acceder a la base de datos SQLite, pero esta
biblioteca está encapsulada en un nivel superior del API de Java. Dado que la mayoría del
código del núcleo se encuentra en C y C++, Google argumentó que el impacto de la
compilación JIT no sería significativo.

Por último, la máquina virtual de Dalvik utiliza un tipo diferente de montaje para la
generación del código, en el que se utilizan los registros como las unidades primarias de
almacenamiento de datos en lugar de la pila. Hay que señalar que el código ejecutable final de
Android, como resultado de la máquina virtual de Dalvik, no se basa en el bytecode de Java,
sino que se basa en los archivos .dex. Esto significa que no se puede ejecutar directamente
el Bytecode de Java, sino que hay que comenzar con los archivos .class de Java y luego
convertirlos en archivos .dex.
Formato de un fichero .dex

2.4. Aplicaciones en Android

Una aplicación Android corre dentro de su propio proceso Linux, por tanto, una
característica fundamental de Android es que el tiempo y ciclo de vida de una aplicación no
está controlado por la misma aplicación sino que lo determina el sistema a partir de una
combinación de estados como pueden ser qué aplicaciones están funcionando, qué prioridad
tienen para el usuario y cuánta memoria queda disponible en el sistema.
Una aplicación en Android debe declarar todas sus actividades, los puntos de entrada, la
comunicación, las capas, los permisos, y las intenciones a través
de AndroidManifest.xml (ver punto 3.2 Interfaces de Usuario). Es muy importante tener en
consideración cómo estos componentes impactan en el tiempo de vida del proceso asociado
con una aplicación, porque si no son empleados de manera apropiada, el sistema detendrá el
proceso de la aplicación aún cuando se esté haciendo algo importante.

2.4.1 Componentes
 Activity: Sin duda es el componente más habitual de las aplicaciones para
Android. Un componente Activity refleja una determinada actividad llevada a cabo
por una aplicación, y que lleva asociada típicamente una ventana o interfaz de
usuario; es importante señalar que no contempla únicamente el aspecto gráfico, sino
que éste forma parte del componente Activity a través de vistas representadas por
clases como View y sus derivadas. Este componente se implementa mediante la
clase de mismo nombre Activity. La mayoría de las aplicaciones permiten la
ejecución de varias acciones a través de la existencia de una o más pantallas. Por
ejemplo, piénsese en una aplicación de mensajes de texto. En ella, la lista de
contactos se muestra en una ventana. Mediante el despliegue de una segunda
ventana, el usuario puede escribir el mensaje al contacto elegido, y en otra tercera
puede repasar su historial de mensajes enviados o recibidos. Cada una de estas
ventanas debería estar representada a través de un componente Activity, de forma
que navegar de una ventana a otra implica lanzar una actividad o dormir otra.
Android permite controlar por completo el ciclo de vida de los componentes Activity.
Tal y como se puede ver en el siguiente punto, una actividad tiene un ciclo de vida
muy definido, que será igual para todas las actividades. Este ciclo de vida es
impuesto por el SDK de Android. Las actividades tienen cuatro posibles
estados: Activa, pausada, parada y reiniciada.
A la hora de diseñar una aplicación en Android hay que tener en cuenta su ciclo de
vida.
 Intent: Un Intent consiste básicamente en la voluntad de realizar alguna acción,
generalmente asociada a unos datos. Lanzando un Intent, una aplicación puede
delegar el trabajo en otra, de forma que el sistema se encarga de buscar qué
aplicación de entre las instaladas, es la que puede llevar a cabo la acción solicitada.
Por ejemplo, abrir una URL en algún navegador web, o escribir un correo electrónico
desde algún cliente de correo. Los Intents están incluidos en el AndroidManifest
porque describen dónde y cuándo puede comenzar una actividad. Cuando una
actividad crea un Intent, éste puede tener descriptores de lo que se quiere hacer.
Una vez se está ejecutando la aplicación, Android compara esta información del
Intent con los Intents de cada aplicación, eligiendo el más adecuado para realizar la
operación especificada por el llamante.
 Broadcast Intent Receiver: Un componente Broadcast Intent Receiver se
utiliza para lanzar alguna ejecución dentro de la aplicación actual cuando un
determinado evento se produzca (generalmente, abrir un componente Activity). Por
ejemplo, una llamada entrante o un SMS recibido. Este componente no tiene interfaz
de usuario asociada, pero puede utilizar el API Notification Manager para avisar al
usuario del evento producido a través de la barra de estado del dispositivo móvil.
Este componente se implementa a través de una clase de nombre
BroadcastReceiver. Para queBroadcast Intent Receiver funcione, no es necesario
que la aplicación en cuestión sea la aplicación activa en el momento de producirse el
evento. El sistema lanzará la aplicación si es necesario cuando el evento
monotorizado tenga lugar.
 Service: Un componente Service representa una aplicación ejecutada sin interfaz
de usuario, y que generalmente tiene lugar en segundo plano mientras otras
aplicaciones (éstas con interfaz) son las que están activas en la pantalla del
dispositivo. Un ejemplo típico de este componente es un reproductor de música. La
interfaz del reproductor muestra al usuario las distintas canciones disponibles, así
como los típicos botones de reproducción, pausa, volumen, etc. En el momento en el
que el usuario reproduce una canción, ésta se escucha mientras se siguen
visualizando todas las acciones anteriores, e incluso puede ejecutar una aplicación
distinta sin que la música deje de sonar. La interfaz de usuario del reproductor sería
un componente Activity, pero la música en reproducción sería un componente
Service, porque se ejecuta en background. Este elemento está implementado por la
clase de mismo nombre Service.
 Content Provider: Con el componente Content Provider, cualquier aplicación en
Android puede almacenar datos en un fichero, en una base de datos SQLite o en
cualquier otro formato que considere. Además, estos datos pueden ser compartidos
entre distintas aplicaciones. Una clase que implemente el componente Content
Provider contendrá una serie de métodos que permiten almacenar, recuperar,
actualizar y compartir los datos de una aplicación.

Existe una colección de clases para distintos tipos de gestión de datos en el


paquete android.provider. Además, cualquier formato adicional que se quiera
implementar deberá pertenecer a este paquete y seguir sus estándares de
funcionamiento.
No todas las aplicaciones tienen que tener los cuatro componentes, pero cualquier
aplicación será una combinación de estos.

2.4.2 Estado de los procesos


Como se ha mencionado anteriormente, cada aplicación de Android corre en su propio
proceso, el cual es creado por la aplicación cuando se ejecuta y permanece hasta que la
aplicación deja de trabajar o el sistema necesita memoria para otras aplicaciones. Android
sitúa cada proceso en una jerarquía de "importancia" basada en estados, como se puede ver
a continuación:
• Procesos en primer plano (Active process): Es un proceso que aloja una Activity
en la pantalla y con la que el usuario está interactuando (su método onResume() ha
sido llamado) o que un IntentReceiver está ejecutándose. Este tipo de procesos
serán eliminados como último recurso si el sistema necesitase memoria.

• Procesos visibles (Visible process): Es un proceso que aloja una Activity pero no
está en primer plano (su método onPause() ha sido llamado). Esto ocurre en
situaciones dónde la aplicación muestra un cuadro de diálogo para interactuar con el
usuario. Este tipo de procesos no será eliminado en caso que sea necesaria la
memoria para mantener a todos los procesos del primer plano corriendo.

• Procesos de servicio (Started service process): Es un proceso que aloja un Service


que ha sido iniciado con el método startService(). Este tipo de procesos no son
visibles y suelen ser importantes para el usuario (conexión con servidores,
reproducción de música).

• Procesos en segundo plano (Background process): Es un proceso que aloja una


Activity que no es actualmente visible para el usuario (su método onStop() ha sido
llamado). Normalmente la eliminación de estos procesos no supone un gran impacto
para la actividad del usuario. Es muy usual que existan numerosos procesos de este
tipo en el sistema, por lo que el sistema mantiene una lista para asegurar que el
último proceso visto por el usuario sea el último en eliminarse en caso de necesitar
memoria.

• Procesos vacíos (Empty process): Es un proceso que no aloja ningún componente.


La razón de existir de este proceso es tener una caché disponible de la aplicación
para su próxima activación. Es común, que el sistema elimine este tipo de procesos
con frecuencia para obtener memoria disponible.

Según esta jerarquía, Android prioriza los procesos existentes en el sistema y decide
cuáles han de ser eliminados, con el fin de liberar recursos y poder lanzar la aplicación
requerida.
Para los procesos en segundo plano, existe una lista llamada LRU (Least Recently Used). En
función de esta lista se van eliminando los procesos; los primeros que se eliminan son aquellos
que llevan más tiempo sin usarse. Así el sistema se asegura de mantener vivos los procesos
que se han usado recientemente.

2.4.3 Ciclo de vida de una actividad


El hecho de que cada aplicación se ejecuta en su propio proceso aporta beneficios en
cuestiones básicas como seguridad, gestión de memoria, o la ocupación de la CPU del
dispositivo móvil. Android se ocupa de lanzar y parar todos estos procesos, gestionar su
ejecución y decidir qué hacer en función de los recursos disponibles y de las órdenes dadas por
el usuario.
El usuario desconoce este comportamiento de Android. Simplemente es consciente de que
mediante un simple clic pasa de una a otra aplicación y puede volver a cualquiera de ellas en el
momento que lo desee. No debe preocuparse sobre cuál es la aplicación que realmente está
activa, cuánta memoria está consumiendo, ni si existen o no recursos suficientes para abrir una
aplicación adicional. Todo eso son tareas propias del sistema operativo.

Android lanza tantos procesos como permitan los recursos del dispositivo. Cada proceso,
correspondiente a una aplicación, estará formado por una o varias actividades independientes
(componentes Activity) de esa aplicación. Cuando el usuario navega de una actividad a otra, o
abre una nueva aplicación, el sistema duerme dicho proceso y realiza una copia de su estado
para poder recuperarlo más tarde. El proceso y la actividad siguen existiendo en el sistema,
pero están dormidos y su estado ha sido guardado. Es entonces cuando crea, o despierta si ya
existe, el proceso para la aplicación que debe ser lanzada, asumiendo que existan recursos
para ello.
Cada uno de los componentes básicos de Android tiene un ciclo de vida bien definido; esto
implica que el desarrollador puede controlar en cada momento en qué estado se encuentra
dicho componente, pudiendo así programar las acciones que mejor convengan. El
componente Activity, probablemente el más importante, tiene un ciclo de vida como el
mostrado en la siguiente figura.

Ciclo de vida de una actividad


De la figura anterior, pueden sacarse las siguientes conclusiones:
 onCreate(), onDestroy(): Abarcan todo el ciclo de vida. Cada uno de estos
métodos representan el principio y el fin de la actividad.
 onStart(), onStop(): Representan la parte visible del ciclo de vida.
Desde onStart() hasta onStop(), la actividad será visible para el usuario, aunque
es posible que no tenga el foco de acción por existir otras actividades superpuestas
con las que el usuario está interactuando. Pueden ser llamados múltiples veces.
 onResume(), onPause(): Delimitan la parte útil del ciclo de vida.
Desde onResume() hasta onPause(), la actividad no sólo es visible, sino que
además tiene el foco de la acción y el usuario puede interactuar con ella.
Tal y como se ve en el diagrama de la figura anterior, el proceso que mantiene a esta Activity
puede ser eliminado cuando se encuentra en onPause() o en onStop(), es decir, cuando no
tiene el foco de la aplicación. Android nunca elimina procesos con los que el usuario está
interactuando en ese momento. Una vez se elimina el proceso, el usuario desconoce dicha
situación y puede incluso volver atrás y querer usarlo de nuevo. Entonces el proceso se
restaura gracias a una copia y vuelve a estar activo como si no hubiera sido eliminado.
Además, la Activity puede haber estado en segundo plano, invisible, y entonces es despertada
pasando por el estado onRestart().
Pero, ¿qué ocurre en realidad cuando no existen recursos suficientes? Obviamente, los
recursos son siempre limitados, más aun cuando se está hablando de dispositivos móviles. En
el momento en el que Android detecta que no hay los recursos necesarios para poder lanzar
una nueva aplicación, analiza los procesos existentes en ese momento y elimina los procesos
que sean menos prioritarios para poder liberar sus recursos.
Cuando el usuario regresa a una actividad que está dormida, el sistema simplemente la
despierta. En este caso, no es necesario recuperar el estado guardado porque el proceso
todavía existe y mantiene el mismo estado. Sin embargo, cuando el usuario quiere regresar a
una aplicación cuyo proceso ya no existe porque se necesitaba liberar sus recursos, Android lo
crea de nuevo y utiliza el estado previamente guardado para poder restaurar una copia fresca
del mismo. Como se ya ha explicado, el usuario no percibe esta situación ni conoce si el
proceso ha sido eliminado o está dormido.

2.5. Modelo de seguridad

La mayoría de las medidas de seguridad entre el sistema y las aplicaciones derivan de los
estándares de Linux 2.6, cuyo kernel, constituye el núcleo principal de Android.
Cada proceso en Android proporciona un entorno seguro de ejecución, en el que
por defecto, ninguna aplicación tiene
permiso para realizar ninguna operación o comportamiento que pueda impactar
negativamente en la ejecución de otras aplicaciones o del sistema mismo. Por ejemplo,
acciones como leer o escribir ficheros privados del usuario
no están permitidas. La única forma de poder saltar estas restricciones impuestas por
Android, es mediante la declaración explícita de
un permiso que autorice a llevar a cabo una determinada acción habitualmente
prohibida.

La seguridad en Android abarca desde el despliegue hasta la ejecución de la aplicación.


Con respecto a la implementación, las aplicaciones de Android tienen que estar
firmadas con una firma digital para poder instalarlas en el dispositivo. Dicha firma se hace a
través de un certificado, cuya clave privada será la del desarrollador de dicha aplicación.

No es necesario vincular a una autoridad de certificado, el único cometido del


certificado es crear una relación de confianza entre las aplicaciones. Mediante la firma, la
aplicación lleva adjunta su autoría.

Con respecto a la ejecución, cada aplicación Android se ejecuta dentro de un proceso


separado. Cada
uno de estos procesos tiene un ID de usuario único y permanente (asignado en el
momento de la instalación). Esto impone un límite al proceso porque evita que una
aplicación tenga acceso directo a los datos críticos para el correcto funcionamiento del
terminal.

Uno de los beneficios de este requisito es que una solicitud no puede ser actualizada con
una versión que no fue publicada por el autor original.

Para establecer un permiso para una aplicación, es necesario declarar uno o más
elementos <uses-permission> donde se especifica el tipo de permiso que
se desea habilitar. Por ejemplo, si se quisiera permitir que una aplicación pueda monitorizar
mensajes SMS entrantes, en el fichero AndroidManifest.xml se encontraría algo como lo que
sigue:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.app.myapp"
<uses-permission android:name="android.permission.RECEIVE_SMS" />
</manifest>

En la clase "android.Manifest.Permission" se especifican todos los posibles permisos


que se pueden conceder a una aplicación.
El elemento <uses-permission> contempla una serie de atributos que definen y matizan
el alcance el permiso dado:

► android:name: Especificación del permiso que se pretende conceder. Debe


ser un nombre de alguno
de los listados en la clase android.Manifest.Permission.

► android:label: Una etiqueta o nombre convencional fácilmente legible para el


usuario.

► android:permissionGroup: Permite especificar un grupo asociado al permiso.


Los posibles grupos se encuentran listados en la clase android.Manifest.permission_group.

► android:protectionLevel: Determina el nivel de riesgo del permiso, y en


función del mismo influye en como el sistema otorga o no el permiso a la aplicación. Oscila
entre valores desde el 0 hasta el 3.

► android:description: Descripción textual del permiso.

► android:icon: Icono gráfico que puede ser asociado al permiso.

3. Librerías Básicas
3.1 Lista de Librerías
Android ofrece una serie de APIs para el desarrollo de sus aplicaciones. La siguiente lista
proporciona una visión de lo que está disponible.Todos los dispositivos Android ofrecen al
menos estas APIs:
 android.util El paquete básico de servicios públicos contiene las clases de bajo
nivel, como contenedores especializados, formateadores de cadenas, y de análisis
XML de servicios públicos.

 android.os El paquete de sistema operativo permite el acceso a los servicios


básicos como el paso de mensajes, la comunicación entre procesos y funciones de
reloj.

 android.graphics La API de gráficos, es el suministro de las clases de bajo nivel


como lienzos de apoyo, colores y las primitivas de dibujo. También le permite dibujar
sobre lienzos.

 android.text Las herramientas de procesamiento de texto para mostrarlo y


analizarlo.

 android.database Proporciona las clases de bajo nivel necesario para la


manipulación de cursores cuando se trabaja con bases de datos.

 android.content El contenido de la API se utiliza para admirar el acceso a los datos


y a la publicación, proporcionando los servicios para hacer frente a los recursos, los
proveedores de contenido y los paquetes.

 android.view Las vistas son un núcleo de la interfaz de usuario. Todos los


elementos de la interfaz se construyen utilizando una serie de vistas que proporcionan
los componentes de interacción con el usuario.

 android.widget Construido sobre el paquete de Vista, estan las clases widget "aquí
está uno que creamos antes", elementos de la interfaz de usuario para su uso en las
aplicaciones. Se incluyen listas, botones y diseños.

 com.google.android.maps API de alto nivel que proporciona acceso a los controles


de mapas que usted puede utilizar en su aplicación. Incluye el control MapView así
como la superposición y la clase MapController utilizados para anotar y controlar
dichos mapas.

 android.app Paquete de alto nivel que proporciona el acceso al modelo de solicitud.


Este, incluye la actividad de servicios y las API que forman la base de todas sus
aplicaciones.

 android.provider Para facilitar el acceso a los desarrolladores a determinados


proveedores de contenidos estándar, el paquete proveedor ofrece clases para todas
sus distribciones.

 android.telephony Las API´s de telefonía le dan la posibilidad de interactuar


directamente con el dispositivo de Teléfono, permitiéndole realizar,recibir y controlar
las llamadas de teléfono,su estado y mensajes SMS.

 android.webkit Ofrece funciones para trabajar con contenido basado en web,


incluyendo un control WebView para incrustar los navegadores en sus actividades y
un administrador de cookies.
Librerias Avanzadas
Las bibliotecas ofrecen toda la funcionalidad que necesita para comenzar a crear
aplicaciones en Android,pero no pasará mucho tiempo antes de que esté dispuesto a
profundizar en API´s avanzadas que ofrecen una funcionaliad más emocionante.
Android pretende abarcar una gran variedad de equipos móviles, de modo que tenga en
cuenta que la adecuación y aplicación de las siguientes API´s variará en función del dispositivo
a que se apliquen:

 android.location Da las aplicaciones de acceso a la ubicación física del


dispositivo actual. Los servicios de localización ofrecen acceso genérico a información
de localización utilizando cualquier posición de hardware xing-Fi o tecnología
disponible en el dispositivo.

 android.media Las API de los medios de comunicación proporcionan soporte para


reproducción y grabación de audio.

 android.opengl Android ofrece un potente motor 3D que utiliza la API de OpenGL


ES que usted puede utilizar para crear interfaces de usuario en 3D dinámico para sus
aplicaciones.

 android.hardware Cuando sea posible, el hardware de la API expone un sensor


incluyendo la cámara, acelerómetro, sensores y una brújula.

 android.bluetooth, android.net.wifi , android and telephony Proporciona el


acceso a las plataforma hardware, incluyendo Bluetooth, Wi-Fi y el hardware de
telefonía.

3.2. Interfaces de usuario (View, Layouts)

La interfaz de usuario se define en los archivos XML del directorio res/layout. Cada pantalla
tendrá un código XML diferente.
Diseñar una pantalla usando Java puede resultar complejo y poco eficiente, sin embargo,
Android soporta XML para diseñar pantallas y define elementos personalizados, cada uno
representando a un "subclase" especifica de view. Se pueden crear pantallas de la misma
manera que se diseñan ficheros HTML.

Cada fichero describe un layout(una pantalla) y cada layout a su vez puede contener otros
elementos. Para gestionar la interfaz de usuario, Android introduce las siguientes
terminologías:

* View: Una view es un objeto cuya clase es android.view.View. Es una estructura de datos
cuyas propiedades contienen los datos de la capa, la información específica del área
rectangular de la pantalla y permite establecer el layout. Una view tiene: layout, drawing, focus
change, scrolling, etc.
La clase view es útil como clase base para los widgets, que son unas subclases ya
implementadas que dibujan los elementos en la pantalla. Los widgets contienen sus propias
medidas, pero puedes usarlas para construir tu interfaz más rápidamente. La lista de widgets
que puedes utilizar incluye Text, EditText, InputMethod, MovementMethod, Button,
RadioButton, CheckBox, y ScrollView.

* Viewgroups: Un viewgroup es un objeto de la clase android.view.Viewgroup, como su


propio nombre indica, un viewgroup es un objeto especial de view cuya function es contener y
controlar la lista de views y de otros viewgroups. Los viewgroups te permiten añadir
estructuras a la interfaz y acumular complejos elementos en la pantalla que son diseccionados
por una sola entidad.

La clase viewgroup es útil como base de la clase layouts, que son subclases implementadas
que proveen los tipos más comunes de los layouts de pantalla. Los layouts proporcionan una
manera de construir una estructura para una lista de views.

* Árbol estructurado de la interfaz UI: En la plataforma Android tú defines una Activity


del UI usando un árbol de nodos view y viewgroups, como vemos en la imágen de abajo. El
árbol puede ser tan simple o complejo como necesites hacerlo, y se puede desarrollar usando
los widgets y layouts que Android proporciona o creando tus propios views.

Los views y viewgroups deben estar contenidos en los layouts, los cuales contienen otros
elementos presentes en una vista. Dentro de cada layout podemos poner todos los elementos
necesarios, incluidos otros layouts. Así conseguiremos estructurar la pantalla de la manera
deseada. Existen una gran variedad de layouts, en función de su posicionamiento en la
pantalla y se describen a continuación algunos de ellos:

* LinearLayout: Se les conoce como contenedores y sirven para reorganizar los elementos
de nuestra aplicación. Sus hijos son los views, viewgroup u otros layouts. Nos permitirán
alinear sus hijos en una única dirección, ya sea horizontal o vertical como se muestra en las
siguientes imagenes. La orientación predeterminada es horizontal.
* RelativeLayout: En este caso todos los elementos van colocados en una posición relativa
a otro. Aquí podemos jugar con las distancias entre elementos en la pantalla, la cual se
expresa en pixeles.

* Absolute layout: Coloca los elementos en posiciones absolutas en la pantalla, teniendo


en cuenta que la posición (0,0) es el extremo superior izquierdo de la pantalla. A continuación
se puede ver un ejemplo para entender mejor la explicación anterior. El absolute layout
especifica la ubicación exacta de sus hijos.

* TableLayout: permite colocar los elementos en forma de tabla. Se utiliza el elemento


<TableRow> para designar a una fila de la tabla. Cada fila puede tener uno o más puntos de
vista. Cada vista se coloca dentro de una fila en forma de celda.

* FrameLayout: Es un marcador de posición que puede


usarse para mostrar una única vista. Se pueden agregar
múltiples puntos de vista a un FrameLayout pero cada uno
se acumulará en la parte superior izquierda de la anterior.
A continuación mostramos un ejemplo ilustrativo:
* ScrollView: Es un tipo especial de FrameLayout ya que permite a los usuarios
desplazarse por una serie de puntos de vista que ocupan más espacio que el despliegue
físico. El scrollView solo puede contener un viewGroup y suele ser LinearLayout.

3.3. "Content Provider" (SQLite)

Aquí se va a explicar el bloque de construcción “Content Provider”, el cual ha sido


anteriormente nombrado, pero entraremos en detalle dado que ofrece un mecanismo bastante
sencillo para almacenar información y acceder a información de manera compartida. Content
Provider es una superclase para el manejo y almacenamiento de datos. Es la manera de
compartir datos entre procesos y aplicaciones, ya que los datos de cada aplicación se
almacenan por separado.

Una clase de Content Provider implementa un conjunto estándar de métodos para exponer
sus datos de aplicación para ser utilizados, consumidos o creados por otras aplicaciones.
Normalmente, ContentProvider se usa con una base de datos(SQLite), pero puede usarse con
otro medio de compartición de variables, un fichero, ó simplemente un ArrayList.

Por defecto, Android incluye una serie de componentes Content Provider que permiten
publicar todo tipo de datos básicos que pueden resultar útiles entre aplicaciones: información
de los contactos, fotografías, imágenes, vídeos, mensajes de texto, audios, etc. Todos estos
Content Provider ya definidos y listos para utilizar se pueden encontrar en el paquete:
android.provider.

Además, Android ofrece la posibilidad de que el desarrollador pueda crear sus propios
Content Provider. Un Content Provider es un objeto de la clase ContentProvider, ubicada en el
paquete android.content, y que almacena datos de un determinado tipo que pueden ser
accedidos desde cualquier aplicación. Cada elemento Content Provider tiene asociada una
URI única que lo representa y a través de la cual los otros componentes de una aplicación
pueden acceder a él.
Por ejemplo, la cadena “content://contacts/people/” es una URI válida que da acceso a la
información de los contactos del dispositivo; la cadena “content://media/external/images” es la
URI identificativa de otro Content Provider que da acceso a las imágenes de un dispositivo de
almacenamiento externo (tarjeta SD, por ejemplo).

Conocida la URI, cualquier componente puede acceder al correspondiente Content Provider.


En el siguiente ejemplo, se accede a la información de los contactos del dispositivo utilizando
la URI que identifica el Content Provider de los contactos.

La información que se quiere obtener es el ID del contacto, su nombre y su teléfono. Para


hacer una consulta a través de una URI, existen varios métodos disponibles: uno de ellos
es managedQuery(), de la clase Activity. Este método requiere como parámetros la URI que
se consulta, los campos a seleccionar, y otros valores como las cláusulas WHERE u ORDER
BY, como si de una consulta SQL se tratara. El resultado consiste en un conjunto de filas que
se puede recorrer a través del objeto Cursor, clase ubicada en el paquete android.database.

// Columnas a consultar
String[] projection = new String[] {
Contacts.People.NAME,
Contacts.People.NUMBER,
Contacts.People._ID
};
// Establecer URI para acceder a los contactos
Uri contacts = "content://contacts/people/";
// Lanzar consulta
Cursor cursor = managedQuery( contacts, projection, null, null,
Contacts.People.NAME + " ASC");

Para crear un Content Provider, se deben seguir los siguientes pasos:

1. Crear una clase que extienda de ContentProvider.

2. Definir una constante denominada CONTENT_URI donde quede recogida la URI que
identificará a este nuevo Content Provider. Esta cadena siempre ha de comenzar por el prefijo
“content://”, seguida de la jerarquía de nombres que se desee establecer. Por ejemplo
“content://miaplicacion.misdatos”.

3. Establecer el sistema de almacenamiento deseado. Lo habitual es establecer una base de


datos en SQLite, pero se puede utilizar cualquier mecanismo de almacenamiento.

4. Definir también como constantes el nombre de las columnas de datos que pueden ser
recuperadas, de forma que el futuro usuario de este Content Provider puede conocerlas.

5. Implementar los métodos básicos de manipulación de datos. Estos son:


● Query(), debe devolver un objeto Cursor.
● Insert()
● Update()
● Delete()
● GetType()

6. En el fichero “AndroidManifest.xml” de la aplicación debe añadirse, dentro del elemento


<application>, la siguiente etiqueta:

<application>
<provider android:name="nombre_del_content_provider"
android:authorities="uri_asignada"/>
</application>
Ejemplo de Manejo de ContentProvider y de bases de datos con Sqlite

El proyecto consta de dos actividades, una inicial para mostrar los terremotos existentes, y
otra secundaria, la cual se crea cuando el usuario pulsa en el menú la opción de
Preferences. En esta segunda actividad el usuario selecciona las preferencias de la consulta
SQL. Nosotros nos centramos en la clase EarthquakeProvider.

package it.gast.terremotos

//para ContentProvider
import android.content.*;
//para SQLite
import android.database.*;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

public class EarthquakeProvider extends ContentProvider {


public static final Uri CONTENT_URI = Uri.parse
("content://com.paad.provider.earthquake/earthquakes");

//Crear las constantes utilizadas para diferenciar entre las distintas


//solicitudes URI.
private static final int QUAKES = 1;
private static final int QUAKE_ID = 2;
private static final UriMatcher uriMatcher;

//Asignar el objeto UriMatcher, donde una URI corresponde a una petición de todos
//los terremotos,representará una única fila del terremoto .
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.paad.provider.Earthquake", "earthquakes", QUAKES);
uriMatcher.addURI("com.paad.provider.Earthquake", "earthquakes/#", QUAKE_ID);
}
@Override
public boolean onCreate() {
Context context = getContext();
earthquakeDatabaseHelper dbHelper;
dbHelper = new earthquakeDatabaseHelper(context, DATABASE_NAME,
null, DATABASE_VERSION);
earthquakeDB = dbHelper.getWritableDatabase();
return (earthquakeDB == null) ? false : true;
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case QUAKES: return"vnd.android.cursor.dir/vnd.paad.earthquake";
case QUAKE_ID: return "vnd.android.cursor.item/vnd.paad.earthquake";
default: throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[]
selectionArgs, String sort)
{
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(EARTHQUAKE_TABLE);
// Si esto es una consulta de fila, limitar el conjunto de resultados a la
fila.
switch (uriMatcher.match(uri))
{
case QUAKE_ID:
qb.appendWhere(KEY_ID + "=" +uri.getPathSegments().get(1));
break;
default:
break;
}

// Si no especifica nada, se especifica ordenar por fecha / hora


String orderBy;
if (TextUtils.isEmpty(sort)) {
orderBy = KEY_DATE;
} else {
orderBy = sort;
}
// Aplica la consulta a la base de datos subyacente
Cursor c = qb.query(earthquakeDB, projection, selection, selectionArgs,
null, null, orderBy);
//Registro de los contextos ContentResolver
// El resultado del cursor cambia.
c.setNotificationUri(getContext().getContentResolver(), uri);
//Devuelve un cursor en el resultado de la consulta
return c;
}
@Override
public Uri insert(Uri _uri, ContentValues _initialValues) {
//Insertar la nueva fila, devolverá el número de fila en caso de éxito.
//mismo funcionamiento que una sentencia insert de SQL
long rowID = earthquakeDB.insert(EARTHQUAKE_TABLE, "quake", _initialValues);
//Actualiza la URI de la fila recién insertada con éxito
if (rowID > 0) {
Uri uri = ContentUris.withAppendedId(CONTENT_URI, rowID);
getContext().getContentResolver().notifyChange(uri, null);
return uri;
}
throw new SQLException("Failed to insert row into " + _uri);
}
@Override
//delete update
// . . . .
}

Los métodos delete y update son muy similares a los anteriores. La ejecución de la
aplicación es la siguiente. Primero nos aparece un listado de todos los terremotos existente
en la base de datos sin especificar su frecuencia ni su magnitud. Entonces pulsamos la tecla
Menu y tenemos la opción de Preferencias para actualizar el listado de los terremotos:

Pulsamos en Preferences y tenemos la siguiente pantalla para modificar el listado. Entonces


filtramos con frecuencia mínima de terremoto de 5 minutos y magnitud mínima de terremoto
de nivel 5:
Entonces damos a OK, y el listado de los terremotos se actualiza de la siguiente manera.
3.4. Multimedia (Media APIs)

Android ofrece una biblioteca multimedia capaz de reproducir y grabar una amplia gama de
formatos de medios de comunicación, proporcionando una amplia funcionalidad para
multimedia, incluyendo grabación y reproducción de audio y vídeo.

Multimedia

Android tiene diversas librerías para aplicaciones multimedia, nosotros vamos a centrarnos
en SensorManager, la cual sirve para manejar el sensor de orientación, y el acelerómetro. La
razón de explicar esta api en concreto es porque el uso de cualquier otra librería de multimedia
es muy parecido a la librería SensorManager, pero también se puede encontrar información
acerca de las librerías: MediaPlayer y TelephonyManager en el libro “Professional Android
Application Development(wrox)”.

La librería SensorManager se utiliza para administrar el hardware y los sensores disponibles


en un dispositivo de Android. Para obtener una referencia al Servicio de sensor tenemos que
usar getSystemService como se muestra a continuación:

String service_name = Context.SENSOR_SERVICE;


SensorManager sensorManager = (SensorManager)getSystemService(service_name);

Ahora explicaremos como utilizar el Administrador de sensores para controlar la orientación y


la aceleración. La forma que se muestra aquí se puede utilizar para controlar cualquier sensor
de hardware disponible:

SensorListener mySensorListener = new SensorListener() {


public void onSensorChanged(int sensor, float[] values) {
// Cambios del Valor del Sensor
}
public void onAccuracyChanged(int sensor, int accuracy) {
// Método auxiliar
}
};

La interfaz de SensorListener se utiliza para obtener el valor del sensor y los cambios de
precisión. El método o evento onSensorChanged reacciona a los cambios de valor. El
parámetro sensor es el identificador del sensor que activa el evento, mientras que la matriz
contiene los nuevos valores detectados por ese sensor.

El evento onAccuracyChanged se produce cuando hay cambios en la precisión de un


sensor. El parámetro sensor, de nuevo es el identificador del sensor que activa el evento,
mientras que el parámetro accuracy indica la nueva precisión del sensor usando una de las
siguientes constantes:

 SensorManager.SENSOR_STATUS_ACCURACY_HIGH: Indica que el sensor tiene la


precisión más alta posible.
 SensorManager.SENSOR_STATUS_ACCURACY_LOW: Indica que el sensor tiene
la precisión más baja posible y necesita ser calibrado.
 SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM: Indica que los datos del
sensor tienen precisión media, y que puede mejorar la calibración de las lecturas.
 SensorManager.SENSOR_STATUS_UNRELIABLE: Indica que los datos del sensor no
son fiables,lo que significa que se requiere calibración o lecturas que no son posibles
en ese momento.

El Administrador de sensores incluye constantes para ayudar a identificar el sensor que


disparó el evento de cambio. La siguiente lista incluye los sensores para los que las
constantes están defidas. Algunos o todos de estos sensores estarán disponible para las
aplicaciones en función del hardware disponible en el dispositivo:

 SensorManager.SENSOR_ACCELEROMETER: Es un sensor acelerómetro que


devuelve la corriente de aceleración a lo largo de tres ejes en (m/s2).
 SensorManager.SENSOR_ORIENTATION: Es un sensor de orientación que devuelve la
orientación actual en tres ejes y se mide en grados.
 SensorManager.SENSOR_LIGHT: Es un sensor de luz ambiental que devuelve un valor
único para describir la iluminación ambiental.
 SensorManager.SENSOR_MAGNETIC_FIELD: Sirve para determinar la corriente
magnética medida en microteslas (μT) a lo largo de tres ejes.
 SensorManager.SENSOR_PROXIMITY: Es un sensor de proximidad que devuelve un
valor único y describe la distancia entre el dispositivo y el objeto de destino en metros
(m).
 SensorManager.SENSOR_TEMPERATURE: Es un sensor de temperatura que devuelve
la temperatura ambiente en grados Celsius (° C).

Para recibir notificaciones de los cambios en un sensor en particular, hay que crear un
SensorListener, y registrarlo con elSensorManager especificando el sensor y la velocidad a
la que el sensor se debe actualizar,como se muestra a continuación:

sensorManager.registerListener(mySensorListener,
SensorManager.SENSOR_TRICORDER,
SensorManager.SENSOR_DELAY_FASTEST);

El SensorManager incluye las siguientes constantes, las cuales permiten seleccionar una
frecuencia de actualización adecuada:

 SensorManager.SENSOR_DELAY_FASTEST: Especifica la
frecuencia más rápida posible de actualización del sensor.
 SensorManager.SENSOR_DELAY_GAME: Selecciona una
tasa de actualización adecuada para su uso en el control
de juegos.
 SensorManager.SENSOR_DELAY_NORMAL: Especifica la
tasa de actualización por defecto.
 SensorManager.SENSOR_DELAY_UI: Especifica un índice
adecuado para la actualización de las características de
interfaz de usuario.

La tasa que usted seleccione no es tan relevante ya que


el SensorManager puede devolver resultados más rápido o más
lento de lo que usted especifique, aunque tiende a ser más rápido.
Para minimizar el coste de los recursos asociados al utilizar el sensor en su aplicación, usted
debe tratar de seleccionar la velocidad minima adecuada.

Existe una aplicación muy simple en iPhone,"Can Moo", la cual está desarrollada también
para Android, utiliza el APISensorManager , y para las pruebas usa el SensorSimulator. Esta
aplicación funciona de la siguiente manera. En el momento en que el usuario mueva el sroll
del móvil, es decir, cuando el usuario mueva la imagen, se escucha el sonido de una vaca.
Parace una aplicación muy tonta pero se puede ver fácilmente el uso de la interfaz
SensorManager.

La interfaz de la aplicación en android es algo parecido a lo siguiente:

Si está interesado en el uso de la interfaz SensorManager, consulte la siguiente página:


http://java.dzone.com/articles/sensor-management

3.4. Bluetooth (Media APIs)

En este punto, usted aprenderá a interactuar directamente con dispositivos Bluetooth. El uso
de Bluetooth junto con otros dispositivos dentro del alcance, incluye la inicialización de
un RFCOMMSocket, para transmitir y recibir flujos de datos desde o para sus aplicaciones. El
servicio de Bluetooth está representado por la clase BluetoothDevice.

Bluetooth es un servicio del sistema al cual se accede mediante el


método getSystemService. Tienes que obtener una referencia de BluetoothDevice pasando
por parámetro el contexto (Context.BLUETOOTH_SERVICE) el cual representa el nombre del
servicio. Se explica a continuación:

String context = Context.BLUETOOTH_SERVICE;


final BluetoothDevice bluetooth = (BluetoothDevice)getSystemService(context);

Para utilizar el servicio de Bluetooth, su aplicación debe tener el permiso de


Bluetooth como se muestra en el siguiente fragmento de código:

<uses-permission android:name=”android.permission.BLUETOOTH”/>

Los métodos enable y disable permiten habilitar o deshabilitar el adaptador Bluetooth. El


método getName y el métodosetName te permiten modificar el nombre del dispositivo, y el
método getAddress puede ser usado para determinar la dirección del dispositivo local.

El siguiente código permite que el adaptador Bluetooth pueda cambiar el nombre del
dispositivo y establecer el modo a"discoverable":

bluetooth.enable(new IBluetoothDeviceCallback.Stub() {
public void onCreateBondingResult(String _address, int _result) throws RemoteException
{
String friendlyName = bluetooth.getRemoteName(_address);
}
public void onEnableResult(int _result) throws RemoteException {
if (_result == BluetoothDevice.RESULT_SUCCESS) {
bluetooth.setName(“BLACKFANG”);
bluetooth.setMode(BluetoothDevice.MODE_DISCOVERABLE);
}
}
});

Para hacer una aplicación que conecte con un dispositivo Bluetooth, por ejemplo con el
Manos Libres del Coche, se requiere el uso de las interfaces BluetoothHeadset,
RfcommSocket y la interfaz Bonding. Nos centraremos en la primera de ellas, la cual
proporciona servicios especializados para interactuar con los auriculares Bluetooth, manos
libres o cualquier dispositivo de manos libres. Para el manejo de las otras dos interfaces se
puede consultar de nuevo el libro: “Professional Android Application Development(wrox)”.

Para utilizar el API BluetoothHeadset, tenemos que crear un objeto de BluetoothHeadset


nuevo en el contexto de aplicación, como se muestra en el siguiente fragmento de código:

BluetoothHeadset headset = new BluetoothHeadset(this);

Android sólo admite una única conexión de los auriculares a la vez, pero usted puede
cambiar el auricular conectado utilizando esta API. Esto se hace llamando al
método connectHeadset, pasando por parámetro la dirección del dispositivo.

headset.connectHeadset(address, new IBluetoothHeadsetCallback.Stub() {


public void onConnectHeadsetResult(String _address, int _resultCode) throws RemoteException {
if (_resultCode == BluetoothHeadset.RESULT_SUCCESS) {
// Connected to a new headset device.
}
}
});
El Servicio Headset no está garantizado para ser conectado a un auricular en todo
momento, así que es una buena práctica utilizar el método getState para confirmar una
conexión válida antes de realizar cualquier acción, como se muestra a continuación:

if (headset.getState() == BluetoothHeadset.STATE_CONNECTED) {
// TODO Perform actions on headset.
}

Cuando haya acabado de interactuar con el auricular, usted siempre debe crear un objeto
BluetoothHeadset para permitir cerrar el servicio. Se muestra a continuación:

BluetoothHeadset headset = new BluetoothHeadset(this);


// headset actions
headset.close();

3.4. Wi-Fi (Media APIs)

El increíble crecimiento de los servicios de Internet y los dispositivos móviles ha hecho el


acceso a Internet una característica cada vez más frecuente en los teléfonos móviles.

La velocidad, fiabilidad y el coste de la conexión a Internet depende de la tecnología de red


que se utilicen (Wi-Fi, GPRS, 3G), permitiendo a las aplicaciones manejar estas conexiones
para garantizar que se ejecuten eficientemente.

Android proporciona acceso al estado de la red mediante los "broadcasting Intents" para
notificar a la aplicación de los cambios en la conectividad de red y ofreciendo un control sobre
la configuración de red y de las conexiones.

La creación de redes Android es manejado principalmente mediante el


API ConnectivityManager, un servicio que permite monitorizar el estado de conexión,
configurando la conexión de red preferida, y administrando la conectividad.

Más tarde, usted aprenderá cómo utilizar el WifiManager para el control del dispositivo Wi-Fi
específicamente. El WifManager le permite ver y modificar las redes Wi-Fi, gestionar la
conexión activa, y llevar a cabo exploraciones del punto de acceso.

ConnectivityManager

El ConnectivityManager representa el servicio de conectividad de red. Se utiliza para


controlar el estado de las conexiones de red y la configuración de conmutación. Para acceder
al ConnectivityManager, tenemos que llamar al método getSystemService, pasando por
parámetro Context.CONNECTIVITY_SERVICE que representa el nombre del servicio, como
se muestra a continuación:

String service = Context.CONNECTIVITY_SERVICE;


ConnectivityManager connectivity = (ConnectivityManager)getSystemService(service);

Antes de utilizar el ConnectivityManager, su aplicación necesitrá leer y escribir el estado de


la red, y acceder a los permisos de acceso que se añade en AndroidManifest.xml, como se
muestra a continuación:

<uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE”/>
<uses-permission android:name=”android.permission.CHANGE_NETWORK_STATE”/>

Una de las funciones más útiles del ConnectivityManager es notificar las solicitudes de
cambios en la conectividad de red. Para controlar dicha conectividad, tiene que crear su propio
"Broadcast Receiver" que atiende a los Intents de
ConnectivityManager.CONNECTIVITY_ACTION. Los "Intents" incluyen varios extras/detalles
adicionales sobre el cambio en el estado de la conectividad. Son los siguientes:

 ConnectivityManager.EXTRA_IS_FAILOVER: Es un booleano que devuelve true si la


actual conexión es el resultado de una conmutación de una red preferida.
 ConnectivityManager.EXTRA_NO_CONNECTIVITY: Es un booleano que devuelve true
si el dispositivo no está conectado a ninguna red.
 ConnectivityManager.EXTRA_REASON: Si se produce un error de conexión, esta
cadena incluye una descripción de por qué el intento de conexión ha fallado.
 ConnectivityManager.EXTRA_NETWORK_INFO: Esto devuelve un objeto NetworkInfo
que incluye detalles de la red relacionados con el evento de la conectividad actual.
 ConnectivityManager.EXTRA_OTHER_NETWORK_INFO: Después de una desconexión
de red, este valor devolverá un objeto NetworkInfo con los detalles de la red de
conmutación con los posibles errores de conexión.
 ConnectivityManager.EXTRA_EXTRA_INFO: Contiene especificaciones adicionales de
la red, detalles de la conexión.

WifiManager

El WifiManager representa el servicio de conectividad Wi-Fi. Puede ser utilizado para


configurar conexiones de red Wi-Fi, gestionar la conexión Wi-Fi, buscar puntos de acceso, y
hacer un seguimiento de los cambios en la conectividad Wi-Fi.

Al igual que con el ConnectivityManager, el acceso a WifiManager se hace mediante el


método getSystemService, pasando por parámetro la constante Context.WIFI_SERVICE,
como se muestra en el siguiente fragmento de código:

String service = Context.WIFI_SERVICE;


final WifiManager wifi = (WifiManager)getSystemService(service);

Para usar la conexión Wi-Fi Manager,su aplicación debe tener permisos para usos de
lectura/escritura
del Estado Wi-Fi, es decir, hay que incluir en el fichero AndroidManifest.xml lo siguiente:

<uses-permission android:name=”android.permission.ACCESS_WIFI_STATE”/>
<uses-permission android:name=”android.permission.CHANGE_WIFI_STATE”/>

Usted puede utilizar el Wi-Fi Manager para habilitar o deshabilitar el hardware Wi-Fi
utilizando el método setWifiEnabled y la petición del estado de la conexión Wi-Fi utilizando los
métodos getWifiState o isWifiEnabled como se muestra en el siguiente fragmento de código:

if (!wifi.isWifiEnabled())
if (wifi.getWifiState() != WifiManager.WIFI_STATE_ENABLING)
wifi.setWifiEnabled(true);

Los Broadcasts Intents de Wi-Fi Manager para el estado de la conectividad, es decir,


información acerca de los cambios en la red Wi-Fi, se obtiene con las siguientes acciones:

• WifiManager.WIFI_STATE_CHANGED_ACTION: Indica que el estado del


hardware Wi-Fi ha cambiado, moviendose entre permitido, habilitado, desactivado,
discapacitado, y desconocido. Incluye dos valores adicionales introducidos en
EXTRA_WIFI_STATE y EXTRA_PREVIOUS_STATE que proporcionan nuevos y
viejos estados Wi-Fi.

• WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION: Este intento se


difunde cada vez que cambia el estado de la conexión con el suplicante (punto de
acceso). Es fi rojo cuando una nueva conexión se ha establecido o una conexión
existente se pierde con el EXTRA_NEW_STATE Boolean que devuelve cierto en el
caso anterior.

• WifiManager.NETWORK_STATE_CHANGED_ACTION: El estado de la red de


difusión es de color rojo cada vez que cambia el estado de la conectividad Wi-Fi. Este
intento incluye dos extras: el primero EXTRA_NETWORK_INFO incluye un objeto
NetworkInfo que detalla el estado actual de la red, mientras que el segundo incluye
EXTRA_BSSID el BSSID del punto de acceso al que está conectado.

• WifiManager.RSSI_CHANGED_ACTION: Usted puede monitorizar la intensidad


de la señal actual de la red Wi-Fi a la que está conectado escuchando
RSSI_CHANGED_ACTION. Este intento de difusión incluye un entero extra,
EXTRA_NEW_RSSI, que mantiene la intensidad de la señal actual. Para utilizar esta
fuerza de la señal, debe utilizar el método calculateSignalLevel estática en el
Administrador de Wi-Fi para convertirlo en un valor entero a una escala que usted
especifique.
4. Aplicación Hola Mundo

La mejor forma de empezar a comprender las características de cualquier nuevo entorno de


desarrollo es mediante la creación de un ejemplo sencillo. En este caso, y
como viene siendo habitual, se creará una aplicación que mostrará por pantalla el
mensaje “Hola Mundo”. Para ello debemos realizar los siguientes pasos:
1. Crear un Proyecto
La creación de un nuevo proyecto de Android no representa mayor dificultad que crear
cualquier otro tipo de proyecto en Eclipse. Una vez abierto este entorno de desarrollo, deben
realizarse los siguientes pasos:
1. Crear el proyecto
Pulsamos sobre el menú File > New > Project...

Seleccionamos Android Project y pulsamos sobre Next.

2. Especificar las propiedades


A continuación se muestra una ventana donde es necesario detallar algunas
propiedades del proyecto. En concreto, se precisa asignar un valor para:
● Project name: Es el nombre del proyecto. En la práctica, será el nombre que
reciba la carpeta donde se guardará todo lo relativo al presente proyecto, dentro del
workspace. Por ejemplo, “HolaMundo”.
● Package name: Nombre del paquete bajo el cual será desarrollado todo el código. Por
ejemplo, se le puede asignar el valor “com.android.hola”.
● Activity name: Representa al nombre de la clase Activity que será creada de forma
automática por el plug-in. Esta clase Activity simplemente es una clase ejecutable, capaz
de realizar alguna tarea, y es imprescindible en la mayoría
de las aplicaciones para Android. Por ejemplo, póngase el nombre “HolaMundo”.
● Application name: Nombre de la aplicación que se va a desarrollar.
Constituye el nombre visible para el usuario del dispositivo móvil. Por ejemplo, “Saludo al
Mundo”.
Debe introducir todos los datos citados anteriormente en la pantalla:

Pulsamos sobre Finish. Tras hacerlo, Eclipse mostrará en el explorador de paquetes los
elementos que conforman el actual proyecto.

2. Añadir una interfaz de Usuario


Android nos ofrece la posibilidad de crear la “fachada” de la aplicación mediante ficheros
XML.De esta forma nos podemos centrar en el aspecto funcional (código java) o puramente
estético(código XML).
Para continuar con el ejemplo, debe desplegarse en el explorador de paquetes la carpeta
denominada “src”. En esta carpeta existirán dos ficheros: “HolaMundo.java” y “R.java”.
Ambos constituyen hasta el momento los dos únicos ficheros fuente del proyecto.
El objetivo es crear una simple interfaz de usuario que permita mostrar el mensaje
“Hola Mundo”. Para ello, el código ha de ser el siguiente:
package com.android.holaimport;
import android.widget.TextView;
public class HolaMundo extends Activity
{
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
TextView tv = new TextView(this);
tv.setText("Hola Mundo");
setContentView(tv);
}
}
En Android, la interfaz de usuario está compuesta de una jerarquía de clases llamadas
"Views”. Una "View" es simplemente un objeto que puede ser pintado en la pantalla, tal como
una animación o un botón. El nombre específico para la subclase de "View" que manipula
texto es "TextView" cuya sintaxis para crear objetos de este tipo es:

TextView tv = new TextView(this);

El argumento que se le pasa al constructor de "TextView" es una instancia de "Context".


Un "Context" es simplemente un enlace hacia el sistema y es lo que provee el acceso a
recursos como el acceso a bases de datos o la configuración de ciertas características
de la aplicación.
La clase "Activity" hereda de "Context" y debido a que nuestra aplicación es un subclase
de "Activity", entonces también lo es de Context", de ese modo, la clase
HolaMundo también es un contexto válido en Android y podemos referenciarla
usando "this" como argumento del constructor "TextView".
Una vez creada la etiqueta de texto, para asignarle un valor simplemente se llam
a al método setText() con la cadena “Hola Mundo” como argumento.

tv.setText("Hello, Android");

Como paso final, deben vincularse los elementos visuales que se hayan creado (las “v
istas”, como TextView) con la pantalla que la aplicación mostrará al usuario. Este
paso se realiza mediante el método setContentView() de la clase “Activity”, que indica al
sistema que “View” debe ser asociada con la UI de la "Activity". Si una "Activity" no llama a
este método ninguna UI será presentada y el sistema simplemente mostrará una pantalla en
blanco.
setContentView(tv);

3. Ejecutar la Aplicación
Antes de lanzar y probar la aplicación, debe crearse una configuración específica para la
ejecución. En esta configuración se debe indicar el proyecto a ejecutar, la “Activity” que
iniciará la ejecución, las opciones del emulador y otros valores opcionales.
1. Seleccione la pestaña Run > Run Configurations. Se abrirá una nueva ventana.
2. En el panel de la izquierda, hay que localizar "Android Application" y pulsar el icono
con la leyenda "New launch configuration".

3. Asignar un nombre para esta configuración. Por ejemplo, “Hola Mundo”.

4. En la etiqueta Android, pulsar el botón Browse para localizar el proyecto “HolaMu


ndo” y seleccionar la opción "Launch" para localizar la actividad “com.android.hola.Hol
aMundo”.
5. Pulsar el botón Run.

Esto lanzará el emulador de Android. La primera vez que se lanza, puede tardar unos
segundos en arrancar. Es recomendable no cerrar el emulador mientras se esté editando y
probando un proyecto, para evitar así tener que repetir siempre el proceso de carga.
Si se muestra un error parecido a “Cannot create data directory”, es necesario acudir
a Run Configurations > pestaña Target, y buscar el campo "Additional Emulator
Command Line Optiones". En dicho campo, introducir la orden “-datadir C:\” si, por
ejemplo, se desea crear los ficheros imagen del emulador en el directorio C:\.
La apariencia del emulador debe ser algo similar a:

Vous aimerez peut-être aussi