Fundamentos de aplicaciones Android

[Fuente: http://developer.android.com/guide/topics/fundamentals.html]

Las aplicaciones Android están escritas en el lenguaje de programación Java. Las herramientas del Android SDK compilan el código. a la vez que otros ficheros de datos y de recursos- en un “package Android” , un fichero con extensión .apk. Todo el código se encuentra en un solo fichero .apk que se le considera una sola aplicación y es el fichero que los dispositivos Android utilizan para instalar la aplicación.

Una vez instalado sobre un dispositivo, cada aplicación Android vive en su propia sandbox de seguridad:

  • El sistema operativo Android es un sistema Linux multi-usuario en el cual cada aplicación es un usuario distinto.
  • Por defecto, el sistema asigna a cada aplicación un ID de usuario único (este ID es utilizado solo por el sistema y es deconocido por la aplicación). El sistema configura permisos para todos los ficheros de una aplicación de forma que que solo el usuario con el ID apropiado puede utilizar los recursos asociados a su aplicación.
  • Cada proceso tiene su propia máquina virtual (VM), asi el código de una aplicación se ejecuta aisladamente de otras aplicaciones.
  • Por defecto, todas las aplicaciones se ejecutan en su propio proceso Linux. Android comienza el proceso cuando cualquiera de los componentes de la aplicación necesita ser ejecutado, entonces apaga el proceso cuando ya no es necesitado o cuando el sistema debe recuperar memoria para otras aplicaciones.De esta forma , el sistema Android implementa el principio de el mínimo privilegio : cada aplicación , por defecto, tiene acceso solo a los componentes que requiere para hacer su trabajo y no más. Esto creo un entorno muy seguro en el cual una aplicación no puede acceder a partes del sistema para los cuales no se le ha dado permiso.

Sin embargo, hay formas para que una aplicación comparta datos con otras aplicaciones y que una aplicación pueda acceder a servicios del sistema:

  • Es posible organizar que dos aplicaciones compartan el mismo Linux user ID, en tal caso las dos pueden acceder a los ficheros de la otra. Para conservar los recursos del sistema, las aplicaciones con el mismo user ID pueden configurarse para ejecutar en el mismo proceso Linux y asi compartir la misma VM (las aplicaciones deben también estar asignadas con el mismo certificado).
  • Una aplicación puede requerir permisos para acceder a datos del dispositivo tales como los contactos del usuario, sus mensajes SMS, el alamacenamiento montable (SD card), cámara , bluetooth, y más. Todos los permisos de las aplicaciones deben ser aceptados por el usuario en tiempo de instalación.

Eso cubre lo que es el funcionamiento básico de cómo una aplicación Android existe dentro del sistema. El resto de este documento introduce los siguientes aspectos:

  • Los componentes del core framework que definen tu aplicación.
  • El fichero de manifest en el que se declaran los componentes y caracteristicas de dispositivos requeridas por tu aplicación.
  • Los recursos que van aparte del código de la aplicación y permiten que tu aplicación optimice su comportamiento para una gran variedad de configuraciones de dispositivos.

Componentes de las aplicaciones

Los componentes de la aplicación son los bloques de construcción esenciales de una aplicacion Android. Cada componente es un punto diferente a través del cual el sistema puede entrar en tu aplicación. No todos los componentes son de hecho puntos de entrada para el usuario y algunos dependen de otros, pero cada uno existe con su propia entidad e interpreta un role especifico- cada uno es un bloque de construcción único que ayuda a definir el comportamiento general de la aplicación.

Hay cuatro tipos diferentes de componentes de aplicación. Cada tipo sirve para un proposito distinto y tiene un ciclo de vida distinto que define como los componentes son creados y destruidos.Los tipos son los siguientes:

Activities

Un activity representa una sola pantalla con un interfaz de usuario. Por ejemplo, una aplicación de email podría tener una actividad que muestre una lista de nuevos emails, otra activity para redactar un email y otra activity para leer emails. aunque las activities trabajan juntas para formar una experiencia de usuario coherente en una aplicación de email, cada una es independiente de las otras. Por tanto, una aplicación diferente puede empezar cualquiera de estas activities (si la aplicación de email lo permite). Por ejemplo, una aplicación que utiliza la cámara puede iniciar la activity de la aplicación de email que se encarga de redactar un nuevo email, para que el usuario pueda compartir una imagen.
Un activity se implementa como una subclase de Activity (para más info consulta la Activities developer guide).

Services

Un service es un componente que ejecuta en segundo plano para realizar operaciones costosas o para realizar trabajos con procesos remotos. Un servicio no tiene interfaz de usuario. Por ejemplo, un servicio puede reproducir musica en segundo plano mientras el usuario está en otra aplicación, o puede recuperar datos de la red sin bloquear la interacción del usuario con el activity.Otro componente, como un activity, puede empezar el servicio y dejarlo ejecutar o engancharlo a él para interaccionar con él.
Un servicio es un subclase de Service y para más info consulta la Services developer guide.

Content providers

Un content provider gestiona un conjunto de datos compartidos entre aplicaciones. Pueden almacenar los datos en el sistema de ficheros, en una BBDD SQLite, en una web, o en cualquier tipo de almacenamiento persistente al que tu aplicacion pueda acceder. A traves del content provider, otras aplicaciones pueden consultar o incluso modificar los datos (si el content provider lo permite).
Por ejemplo, el sistema Android proporciona un content provider que gestiona la información de los contactos del usuario.Por tanto, cualquier aplicaci’on con los permiso apropiados puede consultar parte del content provider (como por ejemplo ContactsContract.data) para leer y escribir info sobre una persona en particular. Los content providers también son útiles para leer y escribir datos que son privados a tu aplicación pero que no van a ser compartidos.Por ejemplo, la aplicación Note Pad utiliza un content provider para almacenar notes.
Un content provider se implementa con la subclase ContentProvider y debe implementar las funciones que le dicta el API que habilitan a otras aplicaciones para realizar transacciones. Para más info, consulta Content Providers developer guide.

Broadcast receivers

Un broadcast receiver es un componente que responde a anuncios del sistema wide broadcasts (de amplia difusión). Muchos broadcasts los origina el sistema- por ejemplo , un broadcast que anuncia que la pantalla se ha apagado, que la bateria esta baja , o que se acabada de tirar una foto con la cámara.
Las aplicaciones pueden también iniciar broadcasts – por ejemplo, para permitir a otras aplicaciones conocer que ciertos datos han sido descargados al dispositivo y están ya disponibles para utilizar.
Aunque los broadcasts receivers no muestran un interfaz de usuario, pueden crear un barra de notificación de estado (create a status bar notification) que alerta al usuario cuando un evento broadcast ocurre. Más frecuente, un broadcast receiver es solo un gateway a otros componentes y se le entiende que tiene que hacer muy poco trabajo.Por ejemplo, pueden iniciar un servicio para realizar alguna tarea de la que depende el evento.
Un broadcast receiver se implementa como una subclase de BroadcastReceiver y cada broadcast es distribuido como un Intentobject. For more information, see the BroadcastReceiver class.

Un aspecto que es único del diseño del sistema Android es que cualquier aplicación puede arrancar un componente de otra aplicación. Por ejemplo, si quieres que el usuario capture una foto con el dispositivo cámara, probablemente hay otra aplicación que hace eso y que tu aplicación puede usar, asi no tienes que programar un activity que haga fotos. No necesitas incorporar ni linkarte al código desde la aplicación de la cámara; en su vez , puedes simplemente arrancar el activity de la aplicación de cámara que captura la foto. Cuando la haya hecho, la foto es devuelta a la aplicación de forma que puedas utilizarla. Para el usuario, parece como si la cámara es de hecho parte de tu aplicación.

Cuando el sistema arranca un componente, comienza el proceso para esa aplicación (si no esta ya ejecutándose) e instancia las clases necesitadas para el componente. Por ejemplo, si nuestra aplicación arranca el activity de la aplicación cámara que captura la foto, esa ativity se ejecuta dentro del proceso que pertenece a la aplicación cámara, no se ejecuta en el proceso de nuestra aplicación. Por lo tanto, a diferencia de la mayoria de las aplicaciones de otros sistemas, las aplicaciones Android no tiene un solo entry point (no hay main()).

Debido a que el sistema ejecuta  cada aplicación en un proceso separado con permisos especificos que restringen el aceso a otras aplicaciones, tu aplicación no puede directamente activar un componente desde otra aplicación. El sistema Android, sin embargo, sí puede. Asi , para activar un componente en otra aplicación, hay que distribuir un mensaje al sistema que especifique la intención (intent) de arrancar un componente en particular. El sistema entonces activa el componente para ti.

Activando componentes

Tres de los cuatro tipos de componentes-activities, services y broadcast receivers- se activan por medio de un mensaje asincrono que llamamos un intent.Los Intents enlazan componentes individuales entre ellos en tiempo de ejecución (se puede pensar en ellos como los mensajeres que solicitan una acción a otros componentes), independientemente de que el componente pertenezca a tu aplicación o a otra.

Un intent es creado con un objeto Intent, que define un mensaje para activar o un componente especifico  o un tipo especifico de componente- un intent puede ser o explicito o implícito , respectivamente.

Para activities y services , un intent define la acción a realizar (por ejemplo, para hacer un “view” o un “send” de algo) y puede especificar la URI de los datos con los que hay que actuar (entre otras cosas que el componente que arranca puede necesitar saber). Por ejemplo, un intent puede hacer una request para un activity para mostrar una imagen o para abrir una página web. En algunos casos, puedes arrancar un activity para recibir un resultado, en tal caso, el activity también retorna el result en un Intent (por ejemplo, puedes hacer in intent para permitir al coger un contacto y devolverlo a tu aplicacion- el return intent incluye un URI apuntando al contacto elegido).

Para los broadcasts receivers. el intent simplemente define el anuncio que se esta difundiendo (por ejemplo , un mensaje broadcast para indicar que la bateria del dispositivo esta baja incluye solo un string action que indica “battery is low”).

El otro tipo de componente , el content provider, no es activado por los intents. Sino que es activado cuando es targeted por una request desde un ContentResolver. El content resolver maneja todas las transacciones directas con el content provider de forma que el componente que esta realizando transacciones con el provider no necesita invocar métodos en el objeto ContentResolver. Esto deja una capa de abstracción entre el content provider y el componente que pide la información (por seguridad).

Hay métodos para activar cada tipo de componente:

Para más información sobre utilizar intents, mira el documento Intents and Intent Filters. Para más información sobre activar componentes específicos consultese los siguientes documentos:ActivitiesServicesBroadcastReceiver and Content Providers.

El fichero Manifest

Antes de que el sistema Android pueda arrancar un componente de aplicación, el sistema debe saber si el componente existe leyendo al archivo AndroidManifest.xml de la aplicación , es decir el archivo manifest de la aplicación. Tu aplicación debe declarar todos sus componentes en este fichero, y debe estar localizado en el raíz del directorio del proyecto de la aplicación.

El manifest hace varias cosas ademas de declarar los componentes de la aplicación, tal como:

  • Identificar cualquier permiso del usuario que la aplicación requiere , tal como el acceso a Internet o acceso de solo lectura a los contacto del usuario.
  • Declarar el API Level mínimo requerido por la aplicación, basándose en los métodos del API que la aplicación utiliza.
  • Declarar las características hardware y software utilizadas o requeridas por la aplicación, tal como una cámara, servicios bluetooth o una pantalla multitouch.
  • Las librerias API que necesita la aplicación para ser linkadas (aparte del Android framework APIs) , tales como Google Maps library.

Declarando componentes

La tarea primera del manifest es informar al sistema sobre los componentes de la aplicación.Por ejemplo, un fichero del manifest puede declarar un activity de la siguiente forma:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:icon="@drawable/app_icon.png" ... >
        <activity android:name="com.example.project.ExampleActivity"
                  android:label="@string/example_label" ... >
        </activity>
        ...
    </application>
</manifest>

En el elemento <application> , el atributo android:icon apunta a recursos para un icono que identifique la aplicación.

En el elemento <activity> , el atributo android:name especifica el fully qualified class name de la subclase Activity y el  android:label especifica una string que hace de label visible al usuario de esa actividad.

Debes declarar todos los componentes de la aplicación de esta forma:

Activities, services, y content providers que incluyes en tu código pero no declaras en el manifest no son visibles al sistema y, consecuentemente, nunca pueden ejecutarse. Sin embargo, los broadcast receivers pueden ser o declarados en el manifest o creados dinámicamente en el código (como objetos BroadcastReceiver) y registrados en el sistema invocando registerReceiver().

Para más información de cómo estructurar el fichero manifest de tu aplicación. ver The AndroidManifest.xml File documentation.

Declarando capacidades de los componentes

Como se ha discutido arriba , en el apartado de Activando Components, podemos utilizar un Intent para arrancar activities, services y broadcast receivers. Puedes hacerlo asi por medio de nombrar el component target (utilizando el component class name) en el intent. Sin embargo , el potencial real de intents yace en el concepto de los actions de intent.Con los intent actions, tu simplemente describes el tipo de action que quieres realizar (y opcionalmente, los datos con los cuales te gustaría realizar el action) y dejas que el sistema encuentre un component en el dispositivo que puede realizar el action y arrancarlo.Si hay varios components que pueden realizar el action descrito por el intent, entonces el usuario selecciona cuál utilizar.

La forma en la que el sistema identifica los components que pueden responder al intent es por comparación de el intent recibido con los intent filters proporcionados por el fichero manifest de otras aplicaciones del dispositivo.

Cuando declaras un component en el manifest de tu aplicación, puedes opcionalmente incluir intent filters que declaran las capacidades del component de forma que pueda responder a intents de otras aplicaciones. Puedes declarar un intent filter para tu component añadiendo el elemento <intent-filter> como un hijo del elemento de declaracion del component.

Por ejemplo, una aplicación de email con un activity para redactar un nuevo email podría declarar in intent filter en su manifest entry para decir qie responde “send” intents (es decir los que piden enviar un email). Un activity de tu aplicación puede entonces crear un inent con la action “send” (ACTION_SEND), entonces el sistema busca correspondencia con la aplicación de email , busca su activity “send” y lanza dicho activity cuando lo invoquemos con el método startActivity().

Para más información sobre cómo crear intent filters , ver Intents and Intent Filters document.

Declarando requerimientos de aplicación

Hay una gran variedad de dispositivos que llevan Android y no todos proporcionan las mismas características y capacidades. Para prevenir tu aplicación de ser instalada en dispositivos que carecen de características necesitadas por tu aplicación, es importante que definas un perfil claro de los tipos de dispositivos que tu aplicación soporta declarando requerimientos tanto software como de dispositivo en el fichero manifest.La mayoría de estas declaraciones son solo informaciones y el sistema no los lee, pero servicios externos como el Android Market los leen para hacer un filtro para los usuarios que buscan aplicaciones desde su dispositivo.

Por ejemplo, si tu aplicación requiere un cámara y utiliza APIs introducidos por Android 2.1 (API Level 7), deberias declarar estos como requerimientos en el fichero manifest. De esa forma, los dispositivos que no tienen cámara y tienen una versión Android más baja de la 2.1 no pueden instalar tu aplicación desde el Android Market.

Sin embargo, puedes también declarar que tu aplicación utiliza la cámara, pero no es un requisito indispensable. En ese caso, tu aplicación debe realizar un check en tiempo de ejecución de si el dispositivo tiene una cámara y deshabilitar cualquier caracter´sitca que utiliza la cámara si esta no está disponible.

Aqui son algunas de las características importantes de dispositivos que debes considerar cuando diseñas y desarrollas tu aplicación:

Tamaño y densidad de la pantalla

Para categorizar los dispositivos por el tamaño de pantalla, Android define dos características de cada dispositivo:
– Tamaño de pantalla (las dimensiones fisicas de la pantalla)
– Densidad de pantalla (la densidad fisica de los pixels de la pantalla , o dpi – puntos por pulgada)
Para simplificar todos los tipos distintos de configuraciones de pantalla, el sistema Android los generaliza en grupos selectos que los hace facil de targetear:
– Los tamaños de pantalla son: small, normal, large, and extra large.
– Las densidades de pantalla son: low density, medium density, high density, and extra high density.
Por defecto, tu aplicacion es compatible con todos los tamaños de pantalla y densidades, debido a que el sistema Android hace los ajustes apropiados a los recursos de tu UI layout y de imagenes. Sin embargo, debes crear layouts especializados para ciertos tamaños de pantalla y proporcionar imagenes especializadas para ciertas densidades, utilziando recursos de layout alternativos, y declarando en el manifest exactamente qué tamaño de pantallas tu aplicación soporta con el elemento <supports-screens>.For more information, see the Supporting Multiple Screens document.
Configuración de entrada de datos
Many devices provide a different type of user input mechanism, such as a hardware keyboard, a trackball, or a five-way navigation pad. If your application requires a particular kind of input hardware, then you should declare it in your manifest with the <uses-configuration> element. However, it is rare that an application should require a certain input configuration.
Características de dispositivo
There are many hardware and software features that may or may not exist on a given Android-powered device, such as a camera, a light sensor, bluetooth, a certain version of OpenGL, or the fidelity of the touchscreen. You should never assume that a certain feature is available on all Android-powered devices (other than the availability of the standard Android library), so you should declare any features used by your application with the <uses-feature> element.
Versión de Plataforma
Different Android-powered devices often run different versions of the Android platform, such as Android 1.6 or Android 2.3. Each successive version often includes additional APIs not available in the previous version. In order to indicate which set of APIs are available, each platform version specifies an API Level (for example, Android 1.0 is API Level 1 and Android 2.3 is API Level 9). If you use any APIs that were added to the platform after version 1.0, you should declare the minimum API Level in which those APIs were introduced using the<uses-sdk> element.

It’s important that you declare all such requirements for your application, because, when you distribute your application on Android Market, Market uses these declarations to filter which applications are available on each device. As such, your application should be available only to devices that meet all your application requirements.

For more information about how Android Market filters applications based on these (and other) requirements, see the Market Filters document.

Recursos de aplicación

An Android application is composed of more than just code—it requires resources that are separate from the source code, such as images, audio files, and anything relating to the visual presentation of the application. For example, you should define animations, menus, styles, colors, and the layout of activity user interfaces with XML files. Using application resources makes it easy to update various characteristics of your application without modifying code and—by providing sets of alternative resources—enables you to optimize your application for a variety of device configurations (such as different languages and screen sizes).

For every resource that you include in your Android project, the SDK build tools define a unique integer ID, which you can use to reference the resource from your application code or from other resources defined in XML. For example, if your application contains an image file named logo.png (saved in the res/drawable/ directory), the SDK tools generate a resource ID named R.drawable.logo, which you can use to reference the image and insert it in your user interface.

One of the most important aspects of providing resources separate from your source code is the ability for you to provide alternative resources for different device configurations. For example, by defining UI strings in XML, you can translate the strings into other languages and save those strings in separate files. Then, based on a language qualifier that you append to the resource directory’s name (such as res/values-fr/ for French string values) and the user’s language setting, the Android system applies the appropriate language strings to your UI.

Android supports many different qualifiers for your alternative resources. The qualifier is a short string that you include in the name of your resource directories in order to define the device configuration for which those resources should be used. As another example, you should often create different layouts for your activities, depending on the device’s screen orientation and size. For example, when the device screen is in portrait orientation (tall), you might want a layout with buttons to be vertical, but when the screen is in landscape orientation (wide), the buttons should be aligned horizontally. To change the layout depending on the orientation, you can define two different layouts and apply the appropriate qualifier to each layout’s directory name. Then, the system automatically applies the appropriate layout depending on the current device orientation.

For more about the different kinds of resources you can include in your application and how to create alternative resources for various device configurations, see the Application Resources developer guide.