Sie sind auf Seite 1von 57

Introducción a Android

Para aprender cómo funcionan las apps, comienza con Aspectos fundamentales
de apps.

Para comenzar con la codificación de inmediato, lee Crear tu primera app.

Android ofrece un completo framework de aplicaciones que te permite crear apps y


juegos innovadores para dispositivos móviles en un entorno de lenguaje Java. Los
documentos que se indican en la barra de navegación izquierda proporcionan
detalles acerca de cómo crear apps usando diferentes API de Android.

Si recién te inicias en el desarrollo de Android, es importante que comprendas los


siguientes conceptos fundamentales acerca del framework de apps de Android:

Las apps proporcionan varios puntos de entrada

Las apps de Android se compilan como una combinación de diferentes


componentes que se pueden invocar de manera individual. Por ejemplo, una
actividad individual proporciona una sola pantalla para una interfaz de usuario y
un servicio realiza tareas de manera independiente en segundo plano.

Desde un componente puedes iniciar otro componente con una intent. Incluso
puedes iniciar un componente en otra app, como una actividad en una app de
mapas para mostrar una dirección. Este modelo proporciona varios puntos de
entrada para una app y permite que cualquier app se comporte como
“predeterminada” de un usuario para una acción que otras apps pueden invocar.

Obtén más información:

 Aspectos fundamentales de apps


 Intents y filtros de intents
 Actividades

Las apps se adaptan a diferentes dispositivos

Android proporciona un framework de apps adaptable que te permite ofrecer


recursos exclusivos para diferentes configuraciones de dispositivos. Por ejemplo,
puedes crear diferentes archivos de diseño XML para diferentes tamaños de
pantalla y el sistema determina qué diseño aplicar en función del tamaño de
pantalla del dispositivo actual.

Puedes consultar la disponibilidad de funciones del dispositivo en tiempo de


ejecución para averiguar si alguna función de la app requiere hardware específico,
como una cámara. Si fuera necesario, también puedes declarar funciones que
requiera tu app para que los mercados de apps como Google Play Store no
permitan su instalación en dispositivos que no admitan esas funciones.

Obtén más información:

 Compatibilidad con dispositivos


 Información general de recursos
 Información general acerca de la interfaz de usuario
Aspectos fundamentales de la
aplicación
Las aplicaciones de Android se escriben en lenguaje de programación Java. Las
herramientas de Android SDK compilan tu código, junto con los archivos de
recursos y datos, en un APK: un paquete de Android, que es un archivo de
almacenamiento con el sufijo .apk. Un archivo de APK incluye todos los
contenidos de una aplicación de Android y es el archivo que usan los dispositivos
con tecnología Android para instalar la aplicación.

Una vez instalada en el dispositivo, cada aplicación de Android se aloja en su


propia zona de pruebas de seguridad:

 El sistema operativo Android es un sistema Linux multiusuario en el que cada aplicación


es un usuario diferente.
 De forma predeterminada, el sistema le asigna a cada aplicación una ID de usuario de
Linux única (solo el sistema utiliza la ID y la aplicación la desconoce). El sistema
establece permisos para todos los archivos en una aplicación de modo que solo el ID de
usuario asignado a esa aplicación pueda acceder a ellos.
 Cada proceso tiene su propio equipo virtual (EV), por lo que el código de una aplicación
se ejecuta de forma independiente de otras aplicaciones.
 De forma predeterminada, cada aplicación ejecuta su proceso de Linux propio. Android
inicia el proceso cuando se requiere la ejecución de alguno de los componentes de la
aplicación, luego lo cierra cuando el proceso ya no es necesario o cuando el sistema debe
recuperar memoria para otras aplicaciones.

De esta manera, el sistema Android implementa el principio de mínimo privilegio.


Es decir, de forma predeterminada, cada aplicación tiene acceso solo a los
componentes que necesita para llevar a cabo su trabajo y nada más. Esto crea un
entorno muy seguro en el que una aplicación no puede acceder a partes del
sistema para las que no tiene permiso.

Sin embargo, hay maneras en las que una aplicación puede compartir datos con
otras aplicaciones y en las que una aplicación puede acceder a servicios del
sistema:

 Es posible disponer que dos aplicaciones compartan la misma ID de usuario de Linux


para que puedan acceder a los archivos de la otra. Para conservar recursos del sistema,
las aplicaciones con la misma ID de usuario también pueden disponer la ejecución en el
mismo proceso de Linux y compartir el mismo EV (las aplicaciones también deben estar
firmadas con el mismo certificado).
 Una aplicación puede solicitar permiso para acceder a datos del dispositivo como los
contactos de un usuario, los mensajes de texto, el dispositivo de almacenamiento (tarjeta
SD), la cámara, Bluetooth y más. El usuario debe garantizar de manera explícita estos
permisos. Para obtener más información, consultaCómo trabajar con permisos del
sistema.

Esto cubre los aspectos básicos sobre cómo una aplicación de Android existe en
el sistema. El resto de este documento te presenta lo siguiente:

 Los componentes del framework central que define tu aplicación.


 El archivo de manifiesto en el que declaras los componentes y las funciones necesarias
del dispositivo para tu aplicación.
 Los recursos independientes del código de la aplicación y que permiten que tu aplicación
optimice correctamente su comportamiento para una variedad de configuraciones de
dispositivos.

Componentes de la aplicación

Los componentes de la aplicación son bloques de creación esenciales de una


aplicación para Android. Cada componente es un punto diferente a través del cual
el sistema puede ingresar a tu aplicación. No todos los componentes son puntos
de entrada reales para el usuario y algunos son dependientes entre sí, pero cada
uno existe como entidad individual y cumple un rol específico; cada uno es un
bloque de creación único que ayuda a definir el comportamiento general de tu
aplicación.

Hay cuatro tipos diferentes de componentes de una aplicación. Cada tipo tiene un
fin específico y un ciclo de vida diferente que define cómo se crea y se destruye el
componente.

Aquí te mostramos los cuatro tipos de componentes de una aplicación:

Actividades

Una actividad representa una pantalla con interfaz de usuario. Por ejemplo, una
aplicación de correo electrónico tiene una actividad que muestra una lista de los
correos electrónicos nuevos, otra actividad para redactar el correo electrónico y
otra actividad para leer correos electrónicos. Si bien las actividades trabajan juntas
para proporcionar una experiencia de usuario consistente en la aplicación de
correo electrónico, cada una es independiente de las demás. De esta manera, una
aplicación diferente puede inicial cualquiera de estas actividades (si la aplicación
de correo electrónico lo permite). Por ejemplo, una aplicación de cámara puede
iniciar la actividad en la aplicación de correo electrónico que redacta el nuevo
mensaje para que el usuario comparta una imagen.

Una actividad se implementa como una subclase de Activity y puedes


obtener más información acerca de este tema en la guía para
desarrolladores Actividades .
Servicios

Un servicio es un componente que se ejecuta en segundo plano para realizar


operaciones prolongadas o tareas para procesos remotos. Un servicio no
proporciona una interfaz de usuario. Por ejemplo, un servicio podría reproducir
música en segundo plano mientras el usuario se encuentra en otra aplicación, o
podría capturar datos en la red sin bloquear la interacción del usuario con una
actividad. Otro componente, como una actividad, puede iniciar el servicio y permitir
que se ejecute o enlazarse a él para interactuar.

Un servicio se implementa como una subclase de Service y puedes


obtener más información acerca de este tema en la guía para
desarrolladores Servicios.

Proveedores de contenido

Un proveedor de contenido administra un conjunto compartido de datos de la app.


Puedes almacenar los datos en el sistema de archivos, en una base de datos
SQLite, en la Web o en cualquier otra ubicación de almacenamiento persistente a
la que tu aplicación pueda acceder. A través del proveedor de contenido, otras
aplicaciones pueden consultar o incluso modificar los datos (si el proveedor de
contenido lo permite). Por ejemplo, el sistema Android proporciona un proveedor
de contenido que administra la información de contacto del usuario. De esta
manera, cualquier app con los permisos correspondientes puede consultar parte
del proveedor de contenido (como ContactsContract.Data) para la lectura y
escritura de información sobre una persona específica.

Los proveedores de contenido también son útiles para leer y escribir datos
privados de tu aplicación y que no se comparten. Por ejemplo, la aplicación
de ejemplo Bloc de notas usa un proveedor de contenido para guardar
notas.

Un proveedor de contenido se implementa como una subclase


de ContentProvider y debe implementar un conjunto estándar de API que
permitan a otras aplicaciones realizar transacciones. Para obtener más
información, lee la guía para desarrolladores Proveedores de contenido .

Receptores de mensajes

Un receptor de mensajes es un componente que responde a los anuncios de


mensajes en todo el sistema. Muchos mensajes son originados por el sistema; por
ejemplo, un mensaje que anuncie que se apagó la pantalla, que la batería tiene
poca carga o que se tomó una foto. Las aplicaciones también pueden iniciar
mensajes; por ejemplo, para permitir que otras aplicaciones sepan que se
descargaron datos al dispositivo y están disponibles para usarlos. Si bien los
receptores de mensajes no exhiben una interfaz de usuario, pueden crear una
notificación de la barra de estado para alertar al usuario cuando se produzca un
evento de mensaje. Aunque, comúnmente, un receptor de mensajes es
simplemente una "puerta de enlace" a otros componentes y está destinado a
realizar una cantidad mínima de trabajo. Por ejemplo, podría iniciar un servicio
para que realice algunas tareas en función del evento.

Un receptor de mensajes se implementa como una subclase


de BroadcastReceiver y cada receptor de mensajes se proporciona como
un objeto Intent. Para obtener más información, consulta la
clase BroadcastReceiver.

Un aspecto exclusivo del diseño del sistema Android es que cualquier aplicación
puede iniciar un componente de otra aplicación. Por ejemplo, si quieres que el
usuario tome una foto con la cámara del dispositivo, probablemente haya otra
aplicación para eso y tu aplicación pueda usarla, en lugar de desarrollar una
actividad para tomar una foto. No necesitas incorporar ni establecer un enlace con
el código de la aplicación de cámara. En su lugar, puedes simplemente iniciar la
actividad en la aplicación de cámara que toma la foto. Cuando termines, la foto
aparecerá en tu aplicación para que puedas usarla. Al usuario le parecerá que la
cámara en realidad forma parte de tu aplicación.

Cuando el sistema inicia un componente, inicia el proceso para esa aplicación (si
es que no se está ejecutando) y crea una instancia de las clases necesarias para
el componente. Por ejemplo, si tu app inicia la actividad en la app de cámara que
toma una foto, esa actividad se ejecuta en el proceso que pertenece a la app de
cámara, no en el proceso de tu app. Por lo tanto, a diferencia de lo que sucede
con las apps en la mayoría de los demás sistemas, las apps de Android no tienen
un solo punto de entrada (por ejemplo, no existe la función main()).

Como el sistema ejecuta cada aplicación en un proceso independiente con


permisos de archivo que limitan el acceso a otras aplicaciones, tu aplicación no
puede activar directamente un componente de otra aplicación. Sin embargo, el
sistema Android sí puede hacerlo. Por lo tanto, para activar un componente en
otra aplicación, debes enviar un mensaje al sistema que especifique tu intent de
iniciar un componente específico. Luego, el sistema activa ese componente por ti.

Activación de componentes
Tres de los cuatro tipos de componentes (actividades, servicios y receptores de
mensajes) se activan mediante un mensaje asincrónico llamado intent. Las intents
enlazan componentes individuales en tiempo de ejecución (son como mensajeros
que solicitan una acción de otros componentes), ya sea que el componente le
pertenezca a tu aplicación o a otra.

Una intent se crea con un objeto Intent, que define un mensaje para activar un
componente específico o un tipoespecífico de componente; una intent puede ser
explícita o implícita, respectivamente.
Para actividades y servicios, una intent define la acción a realizar (por ejemplo,
"ver" o "enviar" algo) y puede especificar el URI de los datos en los que debe
actuar (entre otras cosas que el componente que se está iniciando podría
necesitar saber). Por ejemplo, una intent podría transmitir una solicitud para que
una actividad muestre una imagen o abra una página web. En algunos casos,
puedes iniciar una actividad para recibir un resultado; en cuyo caso, la actividad
también devuelve el resultado en una Intent (por ejemplo, puedes emitir una
intent para que el usuario elija un contacto personal y te lo devuelva; la intent de
devolución incluye un URI que apunta al contacto seleccionado).

Para los receptores de mensajes, la intent simplemente define el anuncio que se


está transmitiendo (por ejemplo, un mensaje para indicar que la batería del
dispositivo tiene poca carga incluye solo una string de acción conocida que indica
“batería baja”).

El otro tipo de componente, proveedor de contenido, no se activa mediante intents,


sino a través de solicitudes de un ContentResolver. El solucionador de contenido
aborda todas las transacciones directas con el proveedor de contenido, de modo
que el componente que realiza las transacciones con el proveedor no deba
hacerlo y, en su lugar, llame a los métodos del objeto ContentResolver. Esto
deja una capa de abstracción entre el proveedor de contenido y el componente
que solicita información (por motivos de seguridad).

Existen métodos independientes para activar cada tipo de componente:

 Puedes iniciar una actividad (o asignarle algo nuevo para hacer) al pasar
una Intent a startActivity()o startActivityForResult() (cuando quieras
que la actividad devuelva un resultado).
 Puedes iniciar un servicio (o darle instrucciones nuevas a un servicio en curso) al pasar
una Intent a startService(). O puedes establecer un enlace con el servicio al pasar
una Intent a bindService().
 Puedes iniciar la transmisión de un mensaje pasando una Intent a métodos
como sendBroadcast(), sendOrderedBroadcast(), o sendStickyBroadcast().
 Puedes realizar una consulta a un proveedor de contenido llamando a query() en
un ContentResolver.

Para obtener más información acerca de cómo usar intents, lee el


documento Intents y filtros de intents. Puedes obtener más información acerca de
cómo activar componentes específicos en los siguientes
documentos: Actividades, Servicios, BroadcastReceiver y Proveedores de
contenido.
El archivo de manifiesto

Para que el sistema Android pueda iniciar un componente de la app, el sistema


debe reconocer la existencia de ese componente leyendo el
archivo AndroidManifest.xml de la app (el archivo de “manifiesto”). Tu
aplicación debe declarar todos sus componentes en este archivo, que debe
encontrarse en la raíz del directorio de proyectos de la aplicación.

El manifiesto puede hacer ciertas cosas además de declarar los componentes de


la aplicación, como por ejemplo:

 Identificar los permisos de usuario que requiere la aplicación, como acceso a Internet o
acceso de lectura para los contactos del usuario.
 Declarar el nivel de API mínimo requerido por la aplicación en función de las API que usa
la aplicación.
 Declarar características de hardware y software que la aplicación usa o exige, como una
cámara, servicios de bluetooth o una pantalla multitáctil.
 Bibliotecas de la API a las que la aplicación necesita estar vinculada (además de las
Android framework API), como la biblioteca Google Maps .
 Y más.

Declaración de componentes
La tarea principal del manifiesto es informarle al sistema acerca de los
componentes de la aplicación. Por ejemplo, un archivo de manifiesto puede
declarar una actividad de la siguiente manera:

<?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 señala los recursos


para un ícono que identifica la app.

En el elemento <activity>, el atributo android:name especifica el nombre de


clase plenamente calificado de la subclase Activity y el
atributo android:label especifican una string para usar como etiqueta de la
actividad visible para el usuario.

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

 Elementos <activity> para las actividades


 Elementos<service> para los servicios
 Elementos <receiver> para los receptores de mensajes
 Elementos <provider> para los proveedores de contenido

Las actividades, los servicios y los proveedores de contenido que incluyas en tu


archivo de origen pero que no declares en el manifiesto no estarán visibles para el
sistema y, por consiguiente, no se podrán ejecutar. No obstante, los receptores de
mensajes pueden declararse en el manifiesto o crearse dinámicamente en forma
de código (como objetos BroadcastReceiver) y registrarse en el sistema
llamando a registerReceiver().

Para obtener más información acerca de cómo estructurar el archivo de manifiesto


para tu aplicación lee la documentación Archivo AndroidManifest.xml .

Declaración de capacidades de los componentes


Como se discutió anteriormente, en Activación de componentes, puedes usar
una Intent para iniciar actividades, servicios y receptores de mensajes. Puedes
hacerlo al denominar explícitamente el componente objetivo (usando el nombre de
clase del componente) en la intent. Sin embargo, el poder real de las intents se
encuentra en el concepto de intents implícitas. Una intent simplemente describe el
tipo de acción a realizar (y, opcionalmente, los datos en función de los cuales
quieres realizar la acción) y le permite al sistema buscar un componente en el
dispositivo que pueda realizar la acción e iniciarla. Si hay múltiples componentes
que pueden realizar la acción que describe la intent, el usuario selecciona la que
quiere usar.

El sistema identifica los componentes que pueden responder a una intent


comparando la intent recibida con los filtros de intents que se proporcionan en el
archivo de manifiesto de otras apps en el dispositivo.

Cuando declaras una actividad en el manifiesto de tu aplicación, tienes la


posibilidad de incluir filtros de intents que declaran las capacidades de la actividad
de modo que pueda responder a intents desde otras aplicaciones. Puedes
declarar un filtro de intents para tu componente agregando un elemento <intent-
filter> como campo secundario del elemento de declaración del componente.

Por ejemplo, si compilaste una aplicación de correo electrónico con una actividad
para redactar un nuevo mensaje de correo electrónico, puedes declarar un filtro de
intents para responder a las intents "enviar" (a fin de enviar un nuevo correo
electrónico) de esta manera:

<manifest ... >


...
<application ... >
<activity
android:name="com.example.project.ComposeEmailActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<data android:type="*/*" />
<category
android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>

Luego, si app crea una intent con la acción ACTION_SEND y la pasa


a startActivity(), el sistema puede iniciar tu actividad para que el usuario
pueda redactar y enviar un correo electrónico.

Para obtener más información acerca de cómo crear filtros de intents, lee el
documento Intents y filtros de intents.

Declaración de requisitos de la aplicación


Existen muchos dispositivos con tecnología Android, pero no todos ofrecen las
mismas funciones y capacidades. Para evitar que se instale tu aplicación en
dispositivos que no tienen las funciones que tu aplicación necesita, es importante
que definas claramente un perfil para los tipos de dispositivos que admite la
aplicación al declarar los requisitos de dispositivos y software en tu archivo de
manifiesto. La mayoría de esas declaraciones son solo informativas y el sistema
no las lee, pero servicios externos como Google Play sí lo hacen para ofrecerles a
los usuarios opciones de filtrado cuando buscan aplicaciones desde sus
dispositivos.

Por ejemplo, si tu aplicación requiere una cámara y usa API introducidas en


Android 2.1 (nivel de API 7), debes declarar esto como requisitos en tu archivo de
manifiesto de la siguiente manera:

<manifest ... >


<uses-feature android:name="android.hardware.camera.any"
android:required="true" />
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19"
/>
...
</manifest>

Ahora, los dispositivos que no tengan cámara y tengan una versión de


Android anterior a 2.1 no podrán instalar tu aplicación desde Google Play.

No obstante, también puedes declarar que tu aplicación usa la cámara, pero no


la exige. En ese caso, tu app debe fijar el atributo required en "false" y
comprobar durante el tiempo de ejecución si el dispositivo tiene cámara e
inhabilitar las funciones de cámara según corresponda.

Encontrarás más información acerca de cómo administrar la compatibilidad de tu


aplicación con diferentes dispositivos en el documento Compatibilidad con
dispositivos .

Recursos de la aplicación

En Android, una aplicación está compuesta por más que simplemente código;
requiere recursos independientes del código fuente, como imágenes, archivos de
audio y otros elementos relacionados con la presentación de la aplicación. Por
ejemplo, debes definir animaciones, menús, estilos, colores y el diseño de las
interfaces de usuario de la actividad con archivos XML. El uso de recursos de la
aplicación facilita la actualización de varias características de tu aplicación sin
necesidad de modificar el código y, al proporcionar conjuntos de recursos
alternativos, puedes optimizar tu aplicación para una variedad de configuraciones
de dispositivos (como diferentes idiomas y tamaños de pantalla).

Por cada recurso que incluyes en tu proyecto para Android, las herramientas de
compilación del SDK definen un ID con número entero que puedes usar para
hacer referencia al recurso desde el código de tu aplicación o desde otros
recursos definidos en XML. Por ejemplo, si tu app contiene un archivo de imagen
denominado logo.png(guardado en el directorio res/drawable/), las
herramientas del SDK generan un ID de recurso llamado R.drawable.logo que
puedes usar para hacer referencia a la imagen e insertarla en tu interfaz de
usuario.

Uno de los aspectos más importantes de proporcionar recursos independientes de


tu código fuente es la capacidad de ofrecer recursos alternativos para diferentes
configuraciones de dispositivos. Por ejemplo, al definir strings de IU en XML,
puedes traducir las strings a otros idiomas y guardarlas en archivos
independientes. Luego, en función de un calificador de idioma que anexes al
nombre del directorio de recursos (como res/values-fr/para los valores de la
string Francés) y a la configuración de idioma del usuario, el sistema Android
aplica las strings de idioma correspondientes a tu IU.

Android admite muchos calificadores diferentes para tus recursos alternativos. El


calificador es una string corta que incluyes en el nombre de tus directorios de
recursos para definir la configuración de dispositivo en la que se deben usar esos
recursos. Para darte otro ejemplo, debes crear con frecuencia diferentes diseños
para tus actividades, según la orientación y el tamaño de pantalla del dispositivo.
Por ejemplo, cuando la orientación de la pantalla del dispositivo es vertical (a lo
alto), podrías usar un diseño en el que los botones estén alineados de forma
vertical, pero cuando es horizontal (a lo ancho), los botones deben alinearse
horizontalmente. Para cambiar el diseño según la orientación, puedes definir dos
diseños diferentes y aplicar el calificador adecuado al nombre de directorio de
cada diseño. El sistema luego aplicará automáticamente el diseño adecuado
según la orientación actual del dispositivo.

Para obtener más información acerca de los diferentes tipos de recursos que
puedes incluir en tu aplicación y cómo crear recursos alternativos para diferentes
configuraciones de dispositivos, lee Provisión de recursos.

Continúa leyendo:

Intents y filtros de intents

Información acerca de cómo usar las Intent API para activar componentes de la
aplicación, como actividades y servicios, y cómo hacer para que los componentes
de tu aplicación estén disponibles para que los usen otras apps.

Actividades

Información acerca de cómo crear una instancia de la clase Activity, que


proporciona una pantalla independiente en tu aplicación con una interfaz de
usuario.

Provisión de recursos

Información acerca de cómo se estructuran las aplicaciones de Android para


recursos independientes de la aplicación desde el código de la aplicación, incluido
cómo puedes proporcionar recursos alternativos parea configuraciones de
dispositivo específicas.
También te puede interesar:

Compatibilidad con dispositivos

Información acerca de cómo funciona Android en diferentes tipos de dispositivos y


una introducción a cómo puedes optimizar tu aplicación para cada dispositivo o
restringir la disponibilidad de tu aplicación para diferentes dispositivos.

Permisos del sistema

Información acerca de cómo Android restringe el acceso de la aplicación a


determinadas API mediante un sistema de permisos que requiere el
consentimiento del usuario para que tu aplicación pueda usar esas API.
Intents y filtros de intents
Una Intent es un objeto de acción que puedes usar para solicitar una acción de
otro componente de la aplicación. Aunque las intents facilitan la comunicación
entre los componentes de muchas maneras, existen tres casos de uso
fundamentales:

 Para comenzar una actividad:


Una Activity representa una única pantalla en una aplicación. Puedes iniciar una
nueva instancia de una Activity pasando una Intent a startActivity().
La Intent describe la actividad que se debe iniciar y contiene los datos
necesarios para ello.
Si deseas recibir un resultado de la actividad cuando finalice, llama
a startActivityForResult(). La actividad recibe el resultado como un
objeto Intent separado en el callback de onActivityResult() de la actividad.
Para obtener más información, consulta la guía Actividades.
 Para iniciar un servicio:
Un Service es un componente que realiza operaciones en segundo plano sin una
interfaz de usuario. Puede iniciar un servicio para realizar una operación única
(como descargar un archivo) pasando una Intent a startService().
La Intent describe el servicio que se debe iniciar y contiene los datos necesarios
para ello.
Si el servicio está diseñado con una interfaz cliente-servidor, puedes establecer un
enlace con el servicio de otro componente pasando
una Intent a bindService(). Para obtener más información, consulte la
guía Servicios.
 Para entregar un mensaje:
Un mensaje es un aviso que cualquier aplicación puede recibir. El sistema entrega
varios mensajes de eventos del sistema, como cuando el sistema arranca o el
dispositivo comienza a cargarse. Puedes enviar un mensaje a otras apps pasando
una Intent a sendBroadcast(), sendOrderedBroadcast() o sendStickyBroad
cast().

Tipos de intents

Existen dos tipos de intents:

 Intents explícitas: especifican qué componente se debe iniciar mediante su nombre (el
nombre de clase completamente calificado). Usualmente, el usuario usa una intent
explícita para iniciar un componente en su propia aplicación porque conoce el nombre de
clase de la actividad o el servicio que desea iniciar. Por ejemplo, puede utilizarla para
iniciar una actividad nueva en respuesta a una acción del usuario o iniciar un servicio para
descargar un archivo en segundo plano.
 Intents implícitas: no se nombra el componente específicamente; pero, en cambio, se
declara una acción general para realizar, lo que permite que un componente de otra
aplicación la maneje. Por ejemplo, si desea mostrar al usuario una ubicación en un mapa,
puede usar una intent implícita para solicitar que otra aplicación capaz muestre una
ubicación específica en un mapa.

Cuando crea una intent explícita para iniciar una actividad o un servicio, la
aplicación inicia inmediatamente el componente de la aplicación especificado en el
objeto Intent.

Figura 1: Ilustración de la forma en que se entrega una intent implícita mediante el sistema
para iniciar otra actividad. [1]La actividad A crea una Intent con una descripción de acción y
la pasa a startActivity(). [2] El sistema Android busca en todas las apps un filtro de
intents que coincida con la intent. Cuando se encuentra una coincidencia, [3] el sistema inicia
la actividad coincidente (actividad B) invocando su método onCreate() y pasándolo a
la Intent.

Cuando crea una intent implícita, el sistema Android busca el componente


apropiado para iniciar comparando el contenido de la intent con los filtros de
intents declarados en el archivo de manifiesto de otras aplicaciones en el
dispositivo. Si la intent coincide con un filtro de intents, el sistema inicia ese
componente y le entrega el objeto Intent. Si varios filtros de intents son
compatibles, el sistema muestra un cuadro de diálogo para que el usuario pueda
elegir la aplicación que se debe usar.

Un filtro de intents es una expresión en el archivo de manifiesto de una aplicación


que especifica el tipo de intents que el componente podría recibir. Por ejemplo,
declarando un filtro de intents para una actividad, permite que otras aplicaciones
inicien directamente la actividad con cierto tipo de intent. Así mismo, si nodeclara
ningún filtro de intent para una actividad, solo se la puede iniciar con una intent
explícita.

Advertencia: Para garantizar que su aplicación sea segura, siempre use una intent explícita
cuando inicie un Service y no declare filtros de intents para los servicios. El uso de una intent
implícita para iniciar un servicio es un riesgo de seguridad porque no puede estar seguro de
qué servicio responderá a la intent, y el usuario no puede ver qué servicio se inicia. A partir de
Android 5.0 (nivel de API 21), el sistema arroja una excepción si llama a bindService() con
una intent implícita.

Creación de una intent

Un objeto Intent tiene información que el sistema Android usa para determinar
qué componente debe iniciar (como el nombre exacto del componente o la
categoría del componente que debe recibir la intent), además de información que
el componente receptor usa para realizar la acción correctamente (por ejemplo, la
acción que debe efectuar y los datos en los que debe actuar).

La información principal que contiene una Intent es la siguiente:

Nombre del componente

El nombre del componente que se debe iniciar.

Esto es opcional, pero es la información clave que hace que una intent
sea explícita, lo que significa que la intent debe enviarse solamente al
componente de la aplicación definido en el nombre del componente. Sin un
nombre de componente, la intent es implícita y el sistema decide qué
componente debe recibir la intent conforme la información restante que esta
contiene (como la acción, los datos y la categoría, que se describen a
continuación). Por lo que si necesita iniciar un componente específico en su
aplicación, debe espceificar el nombre del componente.

Nota: Cuando inicies un Service, debes especificar siempre el nombre del


componente. De lo contrario, no puedes estar seguro de qué servicio responderá a la
intent, y el usuario no puede ver qué servicio se inicia.
Este campo del Intent es un objeto ComponentName, que puedes
especificar con un nombre de clase completamente calificado del
componente de destino, incluido el nombre del paquete de la aplicación.
Por ejemplo, com.example.ExampleActivity. Puedes establecer el
nombre del componente
con setComponent(), setClass(), setClassName() o el
constructor Intent.

Acción

Una string que especifica la acción genérica que se debe realizar


(como ver o elegir).

En el caso de una intent de mensaje, esta es la acción que se realizó y se


informa. La acción determina en gran parte cómo se estructura el resto de
la intent, especialmente qué contienen los datos y los extras.

Puedes especificar tus propias acciones para que las usen las intents en tu
aplicación (o para que las usen otras aplicaciones a fin de invocar
componentes en tu aplicación); pero, usualmente, debes usar acciones
constantes definidas por la clase Intent u otras clases del framework.
Estas son algunas acciones comunes para iniciar una actividad:

ACTION_VIEW

Usa esta acción en una intent con startActivity() cuando tengas información
que la actividad puede mostrar al usuario, como una foto para ver en una app de
galería o una dirección para ver en una app de mapa.

ACTION_SEND

También se conoce como la intent de “compartir” y debes usarla en una intent


con startActivity()cuando tengas información que el usuario puede
compartir mediante otra app, como una app de correo electrónico o intercambio
social.

Consulta la referencia de la clase Intent para conocer más constantes que


definen las acciones genéricas. Otras acciones se definen en otras partes
del framework de Android, como en Settings para las acciones que abren
pantallas específicas en la aplicación de configuración del sistema.

Puedes especificar la acción de una intent con setAction() o un


constructor Intent.

Si defines sus propias acciones, asegúrate de incluir el nombre del paquete


de la aplicación como prefijo. Por ejemplo:
static final String ACTION_TIMETRAVEL =
"com.example.action.TIMETRAVEL";

Datos

El URI (un objeto Uri) que hace referencia a los datos en los que se debe realizar
la acción o el tipo de MIME de esos datos. El tipo de datos suministrado está
generalmente determinado por la acción de la intent. Por ejemplo, si la acción
es ACTION_EDIT, los datos deben contener el URI del documento que se debe
editar.

Cuando se crea una intent, suele ser importante especificar el tipo de datos
(su tipo de MIME), además del URI. Por ejemplo, una actividad que puede
mostrar imágenes, probablemente no podrá reproducir un archivo de video,
aunque los formatos del URI podrían ser similares. Por lo tanto, especificar
el tipo de MIME de tus datos ayuda al sistema Android a encontrar el mejor
componente para recibir la intent. No obstante, el tipo de MIME puede, a
veces, inferirse del URI, en especial cuando los datos representan un
URIcontent:. Esto indica que los datos están en el dispositivo y los
controla un ContentProvider; esto hace que el tipo de MIME sea visible
para el sistema.

Para establecer únicamente el URI de los datos, llama asetData(). Para


establecer solamente el tipo de MIME, llama a setType(). Si es necesario,
puedes establecer ambos explícitamente con setDataAndType().

Advertencia: Si deseas establecer tanto el URI como el tipo de MIME, no llames


a setData()ni a setType()porque cada uno nulifica el valor del otro. Siempre
usa setDataAndType() para establecer el URI y el tipo de MIME.

Categoría

Una string que contiene información adicional sobre el tipo de componente que la
intent debe manejar. En una intent, se puede incluir la cantidad deseada de
descripciones de categorías, pero la mayoría de las intents no requieren una
categoría. Estas son algunas categorías comunes:

CATEGORY_BROWSABLE

La actividad de destino permite que la inicie un navegador web para mostrar datos
a los que hace referencia un vínculo, como una imagen o un mensaje de correo
electrónico.

CATEGORY_LAUNCHER

La actividad es la actividad inicial de una tarea y está enumerada en el lanzador de


la aplicación del sistema.
Para conocer la lista completa de categorías, consulte la descripción de la
clase Intent.

También puedes especificar una categoría con addCategory().

Las propiedades previamente indicadas (nombre de componente, acción, datos y


categoría) representan las características definitorias de una intent. Mediante la
lectura de estas propiedades, el sistema Android puede resolver qué componente
de la aplicación debe iniciar.

Sin embargo, una intent puede tener información adicional que no afecta cómo se
resuelve en un componente de la aplicación. Una intent también puede incluir lo
siguiente:

Extras

Pares de valores clave que tienen información adicional necesaria para lograr la
acción solicitada. Al igual que algunas acciones usan tipos particulares de URI de
los datos, algunas acciones también usan extras particulares.

Puedes agregar datos de campos extra con varios métodos putExtra(),


cada uno de los cuales acepta dos parámetros: el nombre clave y el valor.
También puedes crear un objeto Bundle con todos los datos de campos
extra y luego insertar el Bundle en el Intent con putExtras().

Por ejemplo, al crear una intent para enviar un correo electrónico


con ACTION_SEND, puedes especificar el destinatario "para" con la
clave EXTRA_EMAIL y especificar el "asunto" con la clave EXTRA_SUBJECT.

La clase Intent especifica muchas constantes EXTRA_* para tipos de


datos estandarizados. Si tienes que declarar sus propias claves extra (para
intents que recibe su aplicación), asegúrate de incluir el nombre del paquete
de la aplicación como prefijo. Por ejemplo:

static final String EXTRA_GIGAWATTS =


"com.example.EXTRA_GIGAWATTS";

Indicadores

Indicadores definidos en la clase Intent que funcionan como metadatos para la


intent. Los indicadores pueden indicar al sistema Android cómo iniciar una
actividad (por ejemplo, a qué tarea debe pertenecer la actividad) y cómo tratarla
después del inicio (por ejemplo, si pertenece a la lista de actividades recientes).

Para obtener más información, consulte el método setFlags().


Ejemplo de una intent explícita
Una intent explícita es una intent que se usa para iniciar un componente específico
de la aplicación, como una actividad o un servicio particular en la aplicación. Para
crear una intent explícita, define el nombre de componente para el objeto Intent,
todas las otras propiedades de la intent son opcionales.

Por ejemplo, si creaste un servicio en tu app denominado DownloadService,


diseñado para descargar un archivo de la Web, puedes iniciarlo con el siguiente
código:

// Executed in an Activity, so 'this' is the Context


// The fileUrl is a string URL, such as
"http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

El constructor Intent(Context, Class) proporciona Context a la aplicación ; y


el componente, un objeto Class. De esta manera, la intent inicia explícitamente la
clase DownloadService en la app.

Para obtener más información sobre la creación y el inicio de un servicio, consulte


la guía Servicios.

Ejemplo de una intent implícita


Una intent implícita especifica una acción que puede invocar cualquier aplicación
en el dispositivo que pueda realizar la acción. El uso de una intent implícita es útil
cuando la aplicación no puede realizar la acción pero otras aplicaciones
probablemente sí, y tu desearas que el usuario eligiera qué aplicación usar.

Por ejemplo, si tiene contenido que deseas que el usuario comparta con otras
personas, crea una intent con la acción ACTION_SEND y agrega extras que
especifiquen el contenido para compartir. Cuando llama astartActivity() con
esa intent, el usuario puede elegir una aplicación mediante la cual compartir el
contenido.

Advertencia: Es posible que un usuario no tenga ninguna aplicación para manejar la intent
implícita que tu envías a startActivity(). Si esto sucede, la llamada fallará y la aplicación
colapsará. Para verificar que una actividad recibirá la intent, llama a resolveActivity() en el
objeto Intent. Si el resultado no es nulo, hay, al menos, una aplicación que puede manejar la
intent y es seguro llamar astartActivity(). Si el resultado es nulo, no debes usar la intent y,
si es posible, debes inhabilitar la característica que emite la intent.
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");

// Verify that the intent will resolve to an activity


if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}

Nota: En este caso, el URI no se usa, pero el tipo de los datos de la intent se declara para
especificar el contenido que tienen los extras.

Cuando se llama a startActivity(), el sistema examina todas las aplicaciones


instaladas para determinar cuáles pueden manejar este tipo de intent (una intent
con la acción ACTION_SEND y que tiene datos de texto/sin formato). Si solo hay
una aplicación que puede manejarla, la aplicación se abre inmediatamente y se le
entrega la intent. Si varias actividades aceptan la intent, el sistema muestra un
cuadro de diálogo para que el usuario pueda elegir la aplicación que se debe usar.

Figura 2: Diálogo de selección.

Forzar un selector de apps


Cuando más de una aplicación responde a la intent implícita, el usuario puede
seleccionar qué aplicación se debe usar y establecerla como la opción
predeterminada para la acción. Esto es útil cuando se realiza una acción para la
cual el usuario probablemente desea utilizar la misma aplicación de ahora en
adelante, por ejemplo, al abrir una página web (los usuarios suelen preferir un solo
navegador web).

No obstante, si responden varias aplicaciones a la intent y el usuario podría


desear usar una aplicación diferente cada vez, debe mostrar explícitamente un
cuadro de diálogo de selección. El cuadro de diálogo de selección obliga al
usuario a seleccionar qué aplicación desea utilizar para la acción en cada ocasión
(el usuario no puede seleccionar una aplicación predeterminada para la acción).
Por ejemplo, cuando tu app realiza la acción de “compartir” con la
acción ACTION_SEND, es posible que los usuarios deseen concretar la
compartición usando una app diferente según la situación en la que estén. Por
ello, debes usar siempre el cuadro de diálogo de selección, como se muestra en la
figura 2.
Para mostrar el diálogo de selección, crea
una Intent usando createChooser() y pásala a startActivity(). Por
ejemplo:

Intent sendIntent = new Intent(Intent.ACTION_SEND);


...

// Always use string resources for UI text.


// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);

// Verify the original intent will resolve to at least one activity


if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}

Aquí se muestra un diálogo con una lista de apps que responden a la intent
pasada al método createChooser(), con el texto proporcionado como título del
diálogo.

Recepción de una intent implícita

Para informar las intents implícitas que puede recibir tu app, declara uno o más
filtros para cada componente de la esta con un elemento <intent-filter> en
el archivo de manifiesto. Cada filtro de intents especifica el tipo de intents que
acepta según la acción, los datos y la categoría de la intent. El sistema entregará
la intent implícita al componente de la aplicación solo si la intent puede pasar por
uno de los filtros de intents.

Nota: Una intent explícita siempre se entrega al destino, independientemente de los filtros de
intents que declare el componente.

Un componente de la aplicación debe declarar filtros independientes para cada


tarea única que puede hacer. Por ejemplo, una actividad en una aplicación de
galería de imágenes puede tener dos filtros: uno para ver una imagen y otro para
editarla. Cuando la actividad comienza, inspecciona la Intent y decide cómo
comportarse conforme la información en la Intent (como mostrar los controles del
editor o no).

Cada filtro de intents está definido por un elemento <intent-filter> en el


archivo de manifiesto de la app, anidado en el componente de la app
correspondiente (como un elemento <activity>). En el <intent-filter>,
puedes especificar el tipo de intents que se aceptará con uno o más de estos tres
elementos:

<action>

Declara la acción de la intent aceptada, en el atributo name. El valor debe ser el


valor de la string literal de una acción, no la constante de clase.

<data>

Declara el tipo de datos que se acepta, mediante el uso de uno o más atributos
que especifican varios aspectos del URI de los datos (scheme, host, port, path,
etc.) y el tipo de MIME.

<category>

Declara la categoría de la intent aceptada, en el atributo name. El valor debe ser el


valor de la string literal de una acción, no la constante de clase.

Nota: Para recibir intents implícitas, debe incluir la categoría CATEGORY_DEFAULT en


el filtro de intents. Los
métodos startActivity() y startActivityForResult() tratan todas las intents
como si pertenecieran a la categoría CATEGORY_DEFAULT. Si no declara esta categoría
en el filtro de intents, no se aplicará ninguna intent implícita a la actividad.

Por ejemplo, a continuación se muestra una declaración de actividad con un filtro


de intents para recibir una intent ACTION_SEND cuando el tipo de datos es un texto:

<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>

Estará bien crear un filtro que incluya más de una instancia


de <action>, <data> o <category>. Si no lo haces, simplemente debes estar
seguro de que el componente pueda manejar todos los tipos de combinaciones de
esos elementos de filtro.

Cuando desees manejar múltiples tipos de intents, pero solo en combinaciones


específicas de tipos de acciones, datos y categorías, debes crear varios filtros de
intents.
Restricción del acceso a los componentes

El uso de un filtro de intents no es una manera segura de prevenir que otras apps
inicien tus componentes. Si bien los filtros de intents restringen un componente
para que responda solamente a ciertos tipos de intents implícitas, otra app puede
iniciar potencialmente el componente de tu app usando una intent explícita si el
desarrollador determina los nombres de los componentes. Si es importante
que solo tu apppueda iniciar uno de los componentes, establece el
atributo exported en "false" para ese componente.

Una intent implícita se prueba con un filtro comparando la intent con cada uno de
los tres elementos. Para que se la entregue al componente, la intent debe pasar
las tres pruebas. Si no pasa tan solo una de ellas, el sistema Android no la
entregará al componente. Sin embargo, como un componente puede tener varios
filtros de intents, una intent que no pase por el filtro de un componente podría
pasar por otro filtro. Se proporciona más información sobre la manera en que el
sistema resuelve las intents en la siguiente sección sobre resolución de intents.

Advertencia: Para evitar ejecutar accidentalmente el Service de otra aplicación, siempre usa
una intent explícita cuando inicies tu propio servicio y no declares filtros de intents para el
servicio.
Nota: Para todas las actividades, debes declarar los filtros de intents en el archivo de
manifiesto. No obstante, los filtros para los receptores de mensajes se pueden registrar
dinámicamente llamando a registerReceiver(). Puede anular el registro del receptor
con unregisterReceiver(). Hacerlo permite que la aplicación espere mensajes específicos
solo durante un plazo especificado mientras la aplicación está ejecutándose.

Ejemplos de filtros
Para comprender mejor algunos de los comportamientos de los filtros de intents,
observa el siguiente fragmento de código del archivo de manifiesto de una
aplicación de intercambio social.

<activity android:name="MainActivity">
<!-- This activity is the main entry, should appear in app
launcher -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity android:name="ShareActivity">
<!-- This activity handles "SEND" actions with text data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<!-- This activity also handles "SEND" and "SEND_MULTIPLE" with
media data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:mimeType="application/vnd.google.panorama360+jpg"/>
<data android:mimeType="image/*"/>
<data android:mimeType="video/*"/>
</intent-filter>
</activity>

La primera actividad, MainActivity, es el punto de entrada principal de la app (la


actividad que se abre cuando el usuario lanza inicialmente la app con el ícono
lanzador):

 La acción ACTION_MAIN indica que este es el punto de entrada principal y que no se


esperan datos de intents.
 La categoría CATEGORY_LAUNCHER indica que el ícono de esta actividad debe colocarse
en el lanzador de la aplicación del sistema. Si el elemento <activity> no especifica un
ícono con icon, el sistema usa el ícono del elemento <application>.

Estos dos se deben emparejar para que la actividad aparezca en el lanzador de la


aplicación.

La segunda actividad, ShareActivity, tiene como objetivo facilitar el intercambio


de texto y contenido de medios. Aunque los usuarios pueden ingresar a esta
actividad navegando hasta ella desde la MainActivity, también pueden ingresar
a la ShareActivity directamente desde otra app que emita una intent implícita
que coincida con uno de los dos filtros de intents.

Nota: El tipo de MIME, application/vnd.google.panorama360+jpg, es un tipo de datos


especial que especifica fotos panorámicas que puedes manejar con las Google
Panorama API.
Uso de una intent pendiente

Un objeto PendingIntent es un contenedor de un objeto Intent. El objetivo


principal de un objeto PendingIntent es otorgar permiso a una aplicación externa
para usar la Intent contenida como si se ejecutara desde un proceso de su
propia aplicación.

Estos son algunos de los casos de uso principales de una intent pendiente:

 Declarar una intent que se ejecutará cuando el usuario realice una acción con
su notificación (el NotificationManager del sistema Android ejecuta la Intent).
 Declarar una intent que se ejecutará cuando el usuario realice una acción con el widget de
su aplicación (la app de la pantalla principal ejecuta la Intent).
 Declarar una intent que se ejecutará en un momento especificado en el futuro
(el AlarmManager del sistema Android ejecuta la Intent).

Como cada objeto Intent está diseñado para ser manejado por un tipo específico
de componente de la aplicación (Activity, Service o BroadcastReceiver), se
debe tener la misma consideración al crear unaPendingIntent. Cuando use una
intent pendiente, la aplicación no ejecutará la intent con una llamada
como startActivity(). En cambio, debe declarar el tipo de componente
deseado cuando cree la PendingIntentllamando al método creador respectivo:

 PendingIntent.getActivity() para una Intent que inicia una Activity.


 PendingIntent.getService() para una Intent que inicia un Service.
 PendingIntent.getBroadcast() para una Intent que inicia
un BroadcastReceiver.

A menos que la aplicación esté recibiendo intents pendientes de otras


aplicaciones, los métodos indicados arriba para crear
una PendingIntent probablemente sean los únicos métodos PendingIntent que
necesitarás.

Cada método toma el Context actual de la aplicación, la Intent que desea


encapsular y uno o más indicadores que especifican cómo se debe usar la intent
(por ejemplo, si se la puede usar más de una vez).

Se proporciona más información sobre el uso de intents pendientes con la


documentación para cada caso de uso, como en las guías de Notifications y App
Widgets API.
Resolución de intents

Cuando el sistema recibe una intent implícita para iniciar una actividad, busca la
mejor actividad para la intent mediante la comparación de la intent con los filtros
de intents basándose en tres aspectos:

 La acción de la intent
 Los datos de la intent (tanto URI como tipo de datos)
 La categoría de la intent

En las siguientes secciones se describe la manera de hacer coincidir las intents


con los componentes apropiados en cuanto a la forma de declarar el filtro de
intents en un archivo de manifiesto de una app.

Prueba de acción
Para especificar las acciones de intents aceptadas, un filtro de intents puede
declarar un número de elementos <action> de cero en adelante. Por ejemplo:

<intent-filter>
<action android:name="android.intent.action.EDIT" />
<action android:name="android.intent.action.VIEW" />
...
</intent-filter>

Para pasar el filtro, la acción especificada en la Intent debe coincidir con una de
las acciones indicadas en el filtro.

Si el filtro no enumera ninguna acción, no hay nada con qué establecer la


coincidencia, por lo que ninguna de las intents pasa la prueba. Sin embargo, si
una Intent no especifica una acción, pasará la prueba (si el filtro contiene, al
menos, una acción).

Prueba de categoría
Para especificar las categorías de intents aceptadas, un filtro de intents puede
declarar un número de elementos <category> de cero en adelante. Por ejemplo:

<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
...
</intent-filter>

Para que una intent pase una prueba de categoría, cada categoría en
la Intent debe coincidir con la categoría que figura en el filtro. No es necesario
que suceda la situación inversa (el filtro de intents puede declarar más categorías
que las que se especifican en la Intent y la Intent pasará la prueba). Por lo
tanto, una intent sin categorías siempre debería pasar esta prueba,
independientemente de qué categorías estén declaradas en el filtro.

Nota: Android aplica automáticamente la categoría CATEGORY_DEFAULT a todas las intents


implícitas pasadas a startActivity() y startActivityForResult(). Por ello, si deseas
que tu actividad reciba intents implícitas, debes incluir una categoría
para "android.intent.category.DEFAULT" en los filtros de intents (como se muestra en el
ejemplo de <intent-filter> anterior).

Prueba de datos
Para especificar datos de intents aceptadas, un filtro de intents puede declarar un
número de elementos <data>de cero en adelante. Por ejemplo:

<intent-filter>
<data android:mimeType="video/mpeg" android:scheme="http" ... />
<data android:mimeType="audio/mpeg" android:scheme="http" ... />
...
</intent-filter>

Cada elemento <data> puede especificar una estructura de URI y tipo de datos
(tipo de medios de MIME). Hay atributos separados (scheme, host, port y path)
para cada parte del URI:

<scheme>://<host>:<port>/<path>

Por ejemplo:

content://com.example.project:200/folder/subfolder/etc

En este URI, el esquema es content, el host com.example.project, el


puerto 200 y la ruta folder/subfolder/etc.

Cada uno de los atributos es opcional en un elemento <data>, pero existen


dependencias lineales:

 Si el esquema no se especifica, se ignora el host.


 Si el host no se especifica, se ignora el puerto.
 Si el esquema y el host no se especifican, se ignora la ruta de acceso.
Cuando el URI de una intent se compara con una especificación de URI en un
filtro, solo se lo compara con las partes del URI que se incluyen en el filtro. Por
ejemplo:

 Si un filtro especifica únicamente un esquema, todos los URI con ese esquema coinciden
con el filtro.
 Si un filtro especifica un esquema y una autoridad pero no una ruta de acceso, todos los
URI con el mismo esquema y autoridad pasan el filtro, independientemente de la ruta que
tengan.
 Si un filtro especifica un esquema, una autoridad y una ruta de acceso, solo los URI con el
mismo esquema, autoridad y ruta pasan el filtro.
Nota: La especificación de una ruta de acceso puede contener un asterisco (*) comodín para
requerir solamente una coincidencia parcial del nombre de la ruta.

La prueba de datos compara tanto el URI como el tipo de MIME en la intent con el
URI y el tipo de MIME especificados en el filtro. Las reglas son las siguientes:

1. Una intent que no contiene ni un URI ni un tipo de MIME pasa la prueba solo si el filtro no
especifica ningún URI ni tipo de MIME.
2. Una intent que contiene un URI pero no un tipo de MIME (ni explícitamente ni que se
pueda inferir del URI) pasa la prueba solo si el URI coincide con el formato de URI del
filtro y si el filtro tampoco especifica un tipo de MIME.
3. Una intent que contiene un tipo de MIME pero no un URI pasa la prueba solo si el filtro
enumera el mismo tipo de MIME y no especifica un formato de URI.
4. Una intent que contiene tanto un URI como un tipo de MIME (explícitamente o que se
pueda inferir del URI) pasa la parte de tipo de MIME de la prueba solo si ese tipo coincide
con el tipo enumerado en el filtro. Pasa la parte del URI de la prueba si este coincide con
un URI del filtro o si tiene un URI content: o file: y el filtro no especifica uno. Es decir,
se supone que un componente admite datos content: y file: si el filtro solo indica un
tipo de MIME.

Esta última regla, la regla (d), refleja la expectativa de que los componentes estén
disponibles para obtener datos locales de un archivo o proveedor de contenido.
Por lo tanto, los filtros pueden enumerar solo un tipo de datos y no deben explicitar
el nombre de los esquemas content: y file:. Este es un caso típico. Un
elemento <data> como el siguiente, por ejemplo, indica a Android que el
componente puede obtener datos de imagen de un proveedor de contenido y
mostrarlos:

<intent-filter>
<data android:mimeType="image/*" />
...
</intent-filter>
Como la mayoría del los datos son proporcionados por proveedores de contenido,
los filtros que especifican un tipo de datos pero no un URI son, tal vez, los más
comunes.

Otra configuración común es aquella en la que los filtros tienen un esquema y un


tipo de datos. Por ejemplo, un elemento <data> como el siguiente indica a Android
que el componente puede recuperar datos de video de la red para realizar la
acción:

<intent-filter>
<data android:scheme="http" android:type="video/*" />
...
</intent-filter>

Coincidencias de intents
Se establecen coincidencias de las intents con filtros de intents no solo para
detectar un componente de destino que se debe activar, sino también para
detectar algo sobre el conjunto de componentes del dispositivo. Por ejemplo, la
app de página principal completa el lanzador de la aplicación encontrando todas
las actividades con filtros de intents que especifiquen la acción ACTION_MAIN y la
categoría CATEGORY_LAUNCHER.

Tu app puede usar la coincidencia de intents de una manera similar.


El PackageManager tiene un conjunto de métodos query...() que muestran
todos los componentes que pueden aceptar una intent específica, al igual que una
serie similar de métodos resolve...() para determinar el mejor componente a
fin de responder a la intent. Por ejemplo, queryIntentActivities() muestra una
lista de todas las actividades que pueden realizar la intent pasada como
argumento y queryIntentServices() muestra una lista similar de servicios.
Ninguno de los métodos activa los componentes; solo enumeran los que pueden
responder. Existe un método similar,queryBroadcastReceivers(), para
receptores de mensajes.
Actividades
Una Activity es un componente de la aplicación que contiene una pantalla con
la que los usuarios pueden interactuar para realizar una acción, como marcar un
número telefónico, tomar una foto, enviar un correo electrónico o ver un mapa. A
cada actividad se le asigna una ventana en la que se puede dibujar su interfaz de
usuario. La ventana generalmente abarca toda la pantalla, pero en ocasiones
puede ser más pequeña que esta y quedar "flotando" encima de otras ventanas.

Una aplicación generalmente consiste en múltiples actividades vinculadas de


forma flexible entre sí. Normalmente, una actividad en una aplicación se especifica
como la actividad "principal" que se presenta al usuario cuando este inicia la
aplicación por primera vez. Cada actividad puede a su vez iniciar otra actividad
para poder realizar diferentes acciones. Cada vez que se inicia una actividad
nueva, se detiene la actividad anterior, pero el sistema conserva la actividad en
una pila (la "pila de actividades"). Cuando se inicia una actividad nueva, se la
incluye en la pila de actividades y capta el foco del usuario. La pila de actividades
cumple con el mecanismo de pila "el último en entrar es el primero en salir", por lo
que, cuando el usuario termina de interactuar con la actividad actual y presiona el
botón Atrás, se quita de la pila (y se destruye) y se reanuda la actividad anterior.
(La pila de actividades se explica más detalladamente en el documento Tareas y
pila de actividades).

Cuando se detiene una actividad porque se inicia otra, se notifica el cambio de


estado a través de los métodos callback del ciclo de vida de la actividad. Existen
diferentes métodos callback que podría recibir una actividad como consecuencia
de un cambio de estado (ya sea que el sistema la esté creando, deteniendo,
reanudando o destruyendo) y cada callback te da la oportunidad de realizar una
tarea específica que resulta adecuada para ese cambio de estado. Por ejemplo,
cuando se detiene una actividad, esta debería liberar los objetos grandes, como
una conexión de red o a la base de datos. Cuando se reanuda la actividad, puedes
volver a adquirir los recursos necesarios y reanudar las acciones que se
interrumpieron. Todas estas transiciones de estado forman parte del ciclo de vida
de la actividad.

El resto de este documento aborda los conceptos básicos con respecto a cómo
crear y utilizar una actividad, incluido un artículo completo sobre cómo funciona el
ciclo de vida de la actividad, de modo que puedas administrar correctamente la
transición entre diferentes estados de la misma.

Crear una actividad


Para crear una actividad, debes crear una subclase de Activity (o una subclase
existente de ella). En tu subclase debes implementar métodos callback a los que
el sistema invoca cuando la actividad alterna entre diferentes estados de su ciclo
de vida, como cuando se crea, se detiene, se reanuda o se destruye. Los dos
métodos callback más importantes son los siguientes:

onCreate()

Debes implementar este método. El sistema realiza esta llamada cuando


crea tu actividad. En tu implementación, debes inicializar los componentes
fundamentales de tu actividad. No te olvides de que este es el momento en
el que debes llamar a setContentView() para definir el diseño de la
interfaz de usuario de la actividad.

onPause()

El sistema llama a este método como el primer indicador de que el usuario


está abandonando tu actividad (aunque no siempre significa que la
actividad se esté destruyendo). Generalmente este es el momento en el
que debes confirmar los cambios que deban conservarse más allá de la
sesión de usuario actual (porque es posible que el usuario no vuelva).

Existen muchos otros métodos callback del ciclo de vida que deberías usar para
proporcionar una experiencia de usuario fluida entre actividades y abordar
interrupciones inesperadas que provocan la detención e incluso la destrucción de
tu actividad. Todos los métodos callback del ciclo de vida se discuten más
adelante, en la sección acerca de Cómo administrar el ciclo de vida de la
actividad.

Implementar una interfaz de usuario


La interfaz de usuario para una actividad se proporciona mediante una jerarquía
de vistas; objetos derivados de la clase View. Cada vista controla un espacio
rectangular específico dentro de la ventana de la actividad y pueden responder a
la interacción del usuario. Por ejemplo, una vista podría ser un botón que inicie
una acción cuando el usuario lo toca.

Android ofrece varias vistas listas que puedes usar para diseñar y organizar tu
presentación. Los “widgets” son vistas que proporcionan elementos visuales (e
interactivos) para la pantalla, como un botón, un campo de texto, una casilla de
verificación o una imagen. Los “diseños” son vistas derivadas de ViewGroup que
proporcionan un modelo de diseño único para sus vistas secundarias, como un
diseño lineal, un diseño de cuadrículas o un diseño relativo. También puedes
convertir en subclases las clases View y ViewGroup (o subclases ya existentes)
para crear tus propios widgets y diseños y aplicarlos en el diseño de tu actividad.
La forma más común de definir un diseño mediante el uso de vistas es con un
archivo de diseño XML guardado en los recursos de tu aplicación. De esta
manera, puedes mantener el diseño de tu interfaz de usuario separado del código
fuente que define el comportamiento de la actividad. Puedes configurar el diseño
como la IU para tu actividad con setContentView(), pasando la ID de recurso
para el diseño. También puedes crear nuevas Viewen el código de tu actividad y
una jerarquía de vistas insertando nuevas View en un ViewGroup, y luego usar
ese diseño pasando la raíz ViewGroup a setContentView().

Para obtener información acerca de cómo crear una interfaz de usuario, consulta
la documentación Interfaz de usuario.

Declarar la actividad en el manifiesto


Debes declarar tu actividad en el archivo de manifiesto para que pueda estar
accesible para el sistema. Para declarar tu actividad, abre el archivo de manifiesto
y agrega un elemento <activity> como campo secundario del
elemento <application>. Por ejemplo:

<manifest ... >


<application ... >
<activity android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >

Existen muchos otros atributos que puedes incluir en este elemento para definir
propiedades, como la etiqueta para la actividad, un ícono para la actividad o un
tema para diseñar la IU de la actividad. El atributo android:name es el único
obligatorio; especifica el nombre de clase de actividad. Una vez que publicas tu
aplicación, no debes cambiar este nombre porque si lo haces podrías anular
funcionalidades, como accesos directos de la aplicación (lee la publicación del
blog, Cosas que no pueden cambiar).

Consulta la referencia del elemento <activity> para obtener más información


acerca de cómo declarar tu actividad en el manifiesto.

Usar filtros de intents

Un elemento <activity> también puede especificar varios filtros de intents a


través del elemento <intent-filter> para declarar la forma en que otros
componentes de la aplicación pueden activarlo.
Cuando creas una aplicación nueva con las herramientas del Android SDK, la
actividad auxiliar que se crea automáticamente incluye un filtro de intents que
declara que la actividad responde a la acción “principal” y se debe colocar en la
categoría “lanzador”. El filtro de intents se ve de esta manera:

<activity android:name=".ExampleActivity"
android:icon="@drawable/app_icon">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

El elemento <action> especifica que este es el punto de entrada “principal” a la


aplicación. El elemento <category> especifica que esta actividad debe aparecer
en el lanzador de aplicaciones del sistema (para que los usuarios puedan iniciar
esta actividad).

Si quieres que tu aplicación sea independiente y no permitir que otras aplicaciones


activen sus actividades, entonces no necesitas ningún otro filtro de intents. Una
sola actividad debe tener la acción "principal" y la categoría "lanzador", como en el
ejemplo anterior. Las actividades que no quieres que estén disponibles para otras
aplicaciones no deben tener filtros de intents, y puedes iniciarlas tú mismo usando
intents explícitas (como las que se discuten en la siguiente sección).

Pero si quieres que tu actividad responda a intents implícitas que provienen de


otras aplicaciones (y de la tuya), debes definir filtros de intents adicionales para tu
actividad. Para cada tipo de intent a la que desees responder debes agregar
un <intent-filter> que incluya un elemento <action> y, opcionalmente, un
elemento <category> o <data>. Estos elementos especifican el tipo de intent a la
que tu actividad puede responder.

Para obtener más información acerca de cómo tus actividades pueden responder
a intents, lee el documento Intents y filtros de intents .

Cómo iniciar una actividad


Puedes iniciar otra actividad al llamar a startActivity(), y pasarle
una Intent que describa la actividad que quieres iniciar. La intent especifica la
actividad exacta que quieres iniciar o describe el tipo de acción que quieres
realizar (y el sistema selecciona la actividad adecuada para ti, que incluso puede
ser de otra aplicación). Una intent también puede contener pequeñas cantidades
de datos que utilizará la actividad que se inicie.
Cuando trabajes en tu propia aplicación, con frecuencia necesitarás iniciar una
actividad conocida. Puedes hacerlo al crear una intent que defina de forma
explícita la actividad que quieres iniciar, y para eso deberás usar el nombre de
clase. Por ejemplo, aquí se muestra la forma en que una actividad inicia otra
llamada SignInActivity:

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


startActivity(intent);

Sin embargo, tu aplicación también podría querer realizar alguna acción, como
enviar un correo electrónico, un mensaje de texto o actualizar el estado con datos
de tu actividad. En este caso, tu aplicación podría no tener sus propias actividades
para realizar esas acciones, por lo que, en su lugar, puedes aprovechar las
actividades que proporcionan otras aplicaciones en el dispositivo y que pueden
realizar las acciones por ti. Aquí es cuando las intents pasan a ser muy valiosas,
ya que puedes crear una intent que describa una acción que quieres realizar y el
sistema iniciará la actividad adecuada desde otra aplicación. Si hubieran varias
actividades que pudiesen ejecutar la intent, el usuario podrá seleccionar la que
quiera usar. Por ejemplo, si quieres permitirle al usuario enviar un mensaje de
correo electrónico, puedes crear la siguiente intent:

Intent intent = new Intent(Intent.ACTION_SEND);


intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

El EXTRA_EMAIL extra agregado a la intent es un conjunto de strings de


direcciones de correo electrónico a las que se debe enviar el correo electrónico.
Cuando una aplicación de correo electrónico responde a esta intent, lee el
conjunto de strings proporcionado en el extra y las coloca en el campo “Para” del
formulario de composición de correo electrónico. En esta situación, se inicia la
actividad de la aplicación de correo electrónico y cuando el usuario termina, se
reanuda tu actividad.

Iniciar una actividad para obtener un resultado


Algunas veces, querrás recibir un resultado a partir de la actividad que inicias. En
ese caso, inicia la actividad llamando a startActivityForResult() (en lugar
de startActivity()). Para luego recibir el resultado de la siguiente actividad,
implementa el método callback onActivityResult(). Cuando finaliza la siguiente
actividad, muestra un resultado en una Intent a tu
método onActivityResult().

Por ejemplo, quizá quieras que el usuario seleccione uno de sus contactos para
que tu actividad pueda hacer algo con la información de ese contacto. Aquí te
mostramos cómo puedes crear esa intent y manipular el resultado:
private void pickContact() {
// Create an intent to "pick" a contact, as defined by the content
provider URI
Intent intent = new Intent(Intent.ACTION_PICK,
Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT_REQUEST);
}

@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
// If the request went well (OK) and the request was
PICK_CONTACT_REQUEST
if (resultCode == Activity.RESULT_OK && requestCode ==
PICK_CONTACT_REQUEST) {
// Perform a query to the contact's content provider for the
contact's name
Cursor cursor = getContentResolver().query(data.getData(),
new String[] {Contacts.DISPLAY_NAME}, null, null, null);
if (cursor.moveToFirst()) { // True if the cursor is not empty
int columnIndex =
cursor.getColumnIndex(Contacts.DISPLAY_NAME);
String name = cursor.getString(columnIndex);
// Do something with the selected contact's name...
}
}
}

En este ejemplo se muestra la lógica básica que debes usar en tu


método onActivityResult() para manipular el resultado de una actividad. La
primera condición verifica si la solicitud tuvo éxito (si lo tuvo,
el resultCodeserá RESULT_OK) y si se conoce la solicitud a la cual responde ese
resultado (en este caso, el requestCodecoincide con el segundo parámetro
enviado con startActivityForResult(). A partir de este punto, el código
manipula el resultado de la actividad consultando los datos mostrados en
una Intent (el parámetro data).

Lo que sucede es que un ContentResolver realiza una consulta a un proveedor


de contenido, el que devuelve un Cursor que permite leer los datos consultados.
Para obtener más información, lee el documento Proveedores de contenido.

Para obtener más información acerca de cómo usar intents, lee el


documento Intents y filtros de intents.
Cerrar una actividad
Puedes cerrar una actividad llamando a su método finish(). También puedes
cerrar una actividad que hayas iniciado anteriormente llamando
a finishActivity().

Nota: En la mayoría de los casos, no debes finalizar explícitamente una actividad con estos
métodos. Tal como se discute en la siguiente sección acerca del ciclo de vida de la actividad,
el sistema Android se encarga de administrar el ciclo de vida de una actividad por ti, por lo que
no necesitas finalizar tus propias actividades. Llamar a estos métodos podría afectar de forma
negativa la experiencia de usuario esperada y solo deben usarse cuando no quieres que el
usuario vuelva a esta instancia de la actividad de forma terminante.

Administración del ciclo de vida de la actividad


Administrar el ciclo de vida de tus actividades mediante la implementación de
métodos callbacks es fundamental para desarrollar una aplicación potente y
flexible. El ciclo de vida de una actividad se ve directamente afectado por su
asociación con otras actividades, con sus tareas y con la pila de actividades.

Una actividad puede existir básicamente en tres estados:

Reanudada

La actividad se encuentra en el primer plano de la pantalla y tiene la


atención del usuario. (A veces, este estado también se denomina "en
ejecución").

Pausada

Otra actividad se encuentra en el primer plano y tiene la atención del


usuario, pero esta todavía está visible. Es decir, otra actividad está visible
por encima de esta y esa actividad es parcialmente transparente o no cubre
toda la pantalla. Una actividad pausada está completamente "viva" (el
objeto Activity se conserva en la memoria, mantiene toda la información
de estado y miembro y continúa anexado al administrador de ventanas),
pero el sistema puede eliminarla en situaciones en que la memoria sea
extremadamente baja.

Detenida

La actividad está completamente opacada por otra actividad (ahora la


actividad se encuentra en "segundo plano"). Una actividad detenida
también permanece "viva" (el objeto Activity se conserva en memoria,
mantiene toda la información de estado y miembro, pero no está anexado al
administrador de ventanas). Sin embargo, ya no está visible para el usuario
y el sistema puede eliminarla cuando necesite memoria en alguna otra
parte.

Si se pausa o se detiene una actividad, el sistema puede excluirla de la memoria


al solicitarle que se cierre (llamando a su método finish()), o simplemente
eliminando su proceso. Cuando se vuelve a abrir la actividad (después de haber
sido eliminada o destruida), es necesario crearla nuevamente.

Implementación de callbacks del ciclo de vida


Cuando una actividad entra y sale de los diferentes estados que se describieron
más arriba, esto se notifica a través de diferentes métodos callback. Todos los
métodos callback son enlaces que puedes invalidar para realizar las tareas
correspondientes cuando cambia el estado de la actividad. La siguiente actividad
estructural incluye todos los métodos fundamentales del ciclo de vida:

public class ExampleActivity extends Activity {


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// The activity is being created.
}
@Override
protected void onStart() {
super.onStart();
// The activity is about to become visible.
}
@Override
protected void onResume() {
super.onResume();
// The activity has become visible (it is now "resumed").
}
@Override
protected void onPause() {
super.onPause();
// Another activity is taking focus (this activity is about to
be "paused").
}
@Override
protected void onStop() {
super.onStop();
// The activity is no longer visible (it is now "stopped")
}
@Override
protected void onDestroy() {
super.onDestroy();
// The activity is about to be destroyed.
}
}

Nota: La implementación que realices de estos métodos del ciclo de vida siempre deben
llamar la implementación de la superclase antes de realizar cualquier otra tarea, como se
muestra en los ejemplos anteriores.

En conjunto, estos métodos definen el ciclo de vida completo de una actividad. Al


implementar estos métodos, puedes monitorear tres bucles anidados en el ciclo de
vida de la actividad:

 El ciclo de vida completo de una actividad transcurre entre la llamada


a onCreate() y la llamada a onDestroy(). Tu actividad debe configurar el estado
"global" (como la definición del diseño) en onCreate(), y liberar todos los
recursos restantes en onDestroy(). Por ejemplo, si hay un subproceso de
descarga de datos de la red en ejecución en segundo plano en tu actividad, esta
podría crear ese subproceso en onCreate() y luego detenerlo en onDestroy().
 El ciclo de vida visible de una actividad transcurre entre la llamada
a onStart() y la llamada a onStop(). Durante ese tiempo, el usuario puede ver
la actividad en pantalla e interactuar con ella. Por ejemplo, se llama
a onStop() cuando se inicia una nueva actividad y esta ya no está visible. Entre
estos dos métodos, puedes conservar los recursos necesarios para mostrarle la
actividad al usuario. Por ejemplo, puedes registrar
un BroadcastReceiver en onStart() para controlar los cambios que afecten tu
IU y anular su registro en onStop() cuando el usuario ya no pueda ver lo que
muestras. El sistema podría llamar a onStart() y onStop() muchas veces
durante el ciclo de vida completo de la actividad, ya que la actividad pasa de ser
visible y a estar oculta para el usuario.
 El ciclo de vida en primer plano de una actividad transcurre entre la llamada
a onResume() y la llamada a onPause(). Durante ese tiempo, la actividad se
encuentra al frente de todas las demás actividades en la pantalla y tiene el foco en
la interacción del usuario. Con frecuencia, una actividad puede entrar y salir de
primer plano, por ejemplo, se llama a onPause() cuando el dispositivo entre en
suspensión o cuando aparece un diálogo. Dado que este estado puede cambiar
con frecuencia, el código en estos métodos debe ser bastante liviano para evitar
las transiciones lentas que hacen que el usuario deba esperar.

La figura 1 ilustra esos bucles y el camino que debe tomar una actividad entre
estados. Los rectángulos representan los métodos callback que puedes
implementar para realizar operaciones cuando la actividad cambie de estado.
Figura 1: Ciclo de vida de la actividad.

Los mismos métodos callback del ciclo de vida se indican en la tabla 1, que
describe cada uno de los métodos callback en más detalle y ubica a cada uno
dentro del ciclo de vida total de la actividad, incluido si el sistema puede eliminar la
actividad después de que se completa el método callback.

Tabla 1: Resumen de los métodos de callback del ciclo de vida de una actividad.

¿Se puede
A
Método Descripción eliminar después
continuación
?

onCreate() Recibe una llamada No onStart()


cuando se crea la
actividad por primera vez.
Aquí es donde debes
realizar todas las
configuraciones estáticas
normales: crear vistas,
enlazar datos con listas,
etc. A este método se le
pasa un objeto agrupado
que contiene el estado
anterior de la actividad, si
se hubiera capturado ese
estado (lee Guardar el
estado de una
actividad más adelante).

Siempre seguido
por onStart().

onRestart() Recibe una llamada No onStart()


después de que se
detiene la actividad, junto
antes de que vuelva a
iniciarse.
Siempre seguido
por onStart().
¿Se puede
A
Método Descripción eliminar después
continuación
?

onStart() Recibe una llamada justo No onResume()


antes de que la actividad o
se vuelva visible para el onStop()
usuario.
Seguido
por onResume() si la
actividad pasa a primer
plano, o por onStop() si
se oculta.

onResume( Recibe una llamada justo No onPause()


) antes de que la actividad
comience a interactuar
con el usuario. En este
momento la actividad se
encuentra en la parte
superior de la pila de
actividades, y recibe las
entradas del usuario.
Siempre seguido
por onPause().

onPause() Recibe una llamada Sí onResume()


cuando el sistema está a o
punto de reanudar otra onStop()
actividad. Este método
generalmente se usa
para confirmar los
cambios sin guardar
como datos persistentes,
para detener
animaciones y otras
tareas que podrían estar
consumiendo CPU, etc.
Lo que sea que haga,
debe hacerlo muy rápido
porque la siguiente
actividad no se
¿Se puede
A
Método Descripción eliminar después
continuación
?

reanudará hasta que el


método regrese.
Seguido
por onResume() si la
actividad vuelve al primer
plano, o por onStop() si
se vuelve invisible para el
usuario.

onStop() Recibe una llamada Sí onRestart(


cuando la actividad ya no )
es visible para el usuario. o
Esto puede ocurrir onDestroy(
porque se la destruyó o )
porque se reanudó otra
actividad (ya sea una
actividad existente o una
nueva) y la está
cubriendo.
Seguido
por onRestart() si la
actividad vuelve a
interactuar con el
usuario, o
por onDestroy() si la
actividad desaparece.

onDestroy() Recibe una llamada Sí nada


antes de que se destruya
la actividad. Esta es la
última llamada que
recibirá la actividad. Se lo
puede llamar porque la
actividad está finalizando
(alguien llamó
a finish() para esa
actividad), o porque el
sistema destruye
¿Se puede
A
Método Descripción eliminar después
continuación
?

temporalmente esa
instancia de la actividad
para ahorrar espacio.
Puedes diferenciar estos
dos escenarios con el
método isFinishing()
.

La columna llamada "¿Se puede eliminar después?" indica si el sistema puede


eliminar el proceso que aloja a la actividad en cualquier momento después de que
el método regresa, sin ejecutar otra línea del código de la actividad. En tres
métodos se indica “sí”: (onPause(), onStop() y onDestroy()). Debido a
que onPause() es el primero de los tres, una vez que se crea la
actividad, onPause() es el último método al que se llamará para que
se pueda finalizar el proceso; si el sistema debe recuperar memoria en una
emergencia, es posible que no se llame a onStop() ni a onDestroy(). Por lo
tanto, debes usar onPause() para escribir datos persistentes fundamentales
(como ediciones realizadas por el usuario) para almacenar. Sin embargo, debes
seleccionar bien la información que quieres conservar durante onPause(), ya que
cualquier procedimiento de bloqueo en este método bloqueará la transición a la
siguiente actividad y hará que la experiencia del usuario sea más lenta.

Los métodos en los que se indica "No" en la columna ¿Se puede eliminar
después? protegen el proceso que aloja la actividad para que no pueda ser
eliminada desde el momento en que se los llama. De esta manera, la actividad es
"eliminable" desde el momento en que onPause() regresa hasta el momento en
que se llama a onResume(). No volverá a ser "eliminable" hasta que se llame
nuevamente a onPause() y regrese.

Nota: Una actividad que técnicamente no sea "eliminable" de acuerdo con su definición en la
tabla 1, aún podrá ser eliminada por el sistema, pero esto solo ocurriría en situaciones
extremas en las que no haya otros recursos. Cuándo se podría eliminar una actividad se
discute en más detalle en el documento Procesos y subprocesos.

Cómo guardar el estado de una actividad


La introducción a Administrar el ciclo de vida de una actividad menciona
brevemente que cuando se pausa o se detiene una actividad, se conserva el
estado de la actividad. Esto ocurre porque el objeto Activity aún se encuentra
en la memoria cuando la actividad se pausa o se detiene; toda la información de
sus miembros y el estado actual aún está con vida. Por lo tanto, los cambios que
realice el usuario en la actividad se conservan de modo que cuando la actividad
regrese a primer plano (cuando se "reanude"), esos cambios todavía estén ahí.

Sin embargo, cuando el sistema destruye una actividad para recuperar memoria,
el objeto Activity también se destruye, por lo cual el sistema no puede
simplemente reanudarla con su estado intacto. En su lugar, si el usuario retrocede
en su navegación hasta esa actividad, el sistema debe volver a crear el
objeto Activity. Aún así, el usuario no sabe que el sistema destruyó la actividad
y la volvió a crear y, por lo tanto, probablemente espere que la actividad se
encuentre tal como estaba. En esa situación, puedes garantizar que se conserve
la información importante acerca del estado de la actividad mediante la
implementación de un método de callback adicional que te permita guardar
información acerca del estado de tu actividad: onSaveInstanceState().

Antes de que la actividad sea vulnerable a la destrucción, el sistema llama


a onSaveInstanceState(). El sistema pasa a este método un Bundle en el que
puedes guardar información del estado de la actividad como pares nombre-valor
mediante métodos como putString() y putInt(). Luego, si el sistema finaliza el
proceso de tu aplicación y el usuario regresa a la actividad, el sistema vuelve a
crear la actividad y pasa el Bundle a onCreate() y
a onRestoreInstanceState(). Al usar cualquiera de estos métodos, puedes
extraer el estado guardado de Bundle y restaurar el estado de la actividad. Si no
hay información de estado para restaurar, el Bundle que recibes es null (como
sucede cuando se crea la actividad por primera vez).

Figura 2: Dos maneras en las cuales una actividad recupera el foco para el usuario con su
estado intacto: la actividad se destruye, luego vuelve a crearse y debe restaurar el estado
guardado anteriormente, o se detiene y luego se reanuda, y su estado permanece intacto.

Nota: No se garantizan llamadas a onSaveInstanceState() antes de destruir tu actividad, ya


que hay casos en los cuales no será necesario guardar el estado (como cuando el usuario
sale de tu actividad con el botón Atrás, porque cierra la actividad explícitamente). Si el sistema
llama a onSaveInstanceState(), lo hace antes de llamar a onStop() y posiblemente antes
de llamar a onPause().

No obstante, incluso si no haces nada y no


implementas onSaveInstanceState(), parte del estado de la actividad se
restaura mediante la implementación predeterminada
de onSaveInstanceState() por parte de la clase Activity. Específicamente, la
implementación predeterminada llama al
método onSaveInstanceState() correspondiente para cada View del diseño, el
cual permite que cada vista proporcione información acerca de sí misma que debe
guardarse. Prácticamente todos los widgets del framework de Android
implementan este método según les convenga, de modo que los cambios visibles
en la IU se guardan automáticamente y se restauran cuando se vuelve a crear la
actividad. Por ejemplo, el widget EditText guarda el texto ingresado por el
usuario y el widget CheckBox guarda si se comprobó o no. Lo único que debes
hacer es proporcionar un ID único (con el atributo android:id ) para cada widget
cuyo estado desees guardar. Si un widget no tiene una ID, el sistema no puede
guardar su estado.

También puedes evitar explícitamente que una vista de tu diseño guarde su


estado fijando el atributoandroid:saveEnabled en "false" o al llamando al
método setSaveEnabled(). Generalmente, no deberías inhabilitar esto, pero
podrías hacerlo si quieres restaurar el estado de la IU de la actividad de una
manera distinta.

Si bien la implementación predeterminada de onSaveInstanceState() guarda


información útil acerca de la IU de tu actividad, probablemente necesites
sobrescribirla para guardar información adicional. Por ejemplo, podría ser
necesario que guardes valores de miembro que cambiaron durante la vida útil de
la actividad (que podrían correlacionarse con valores restaurados en la IU, pero
los miembros que poseen esos valores de la IU no se restauran, de forma
predeterminada).

Debido a que la implementación predeterminada


de onSaveInstanceState() ayuda a guardar el estado de la IU, si sobrescribes
el método para guardar información de estado adicional siempre debes llamar la
implementación de onSaveInstanceState() por parte de la superclase antes de
realizar cualquier tarea. De la misma manera, también debes llamar a la
implementación de onRestoreInstanceState() por parte de la superclase si la
sobrescribes, de modo que la implementación predeterminada pueda restaurar
estados de las vistas.

Nota: Dado que no se garantiza la llamada a onSaveInstanceState(), debes usarlo solo


para registrar el estado transitorio de la actividad (el estado de la IU); nunca debes usarlo para
almacenar datos persistentes. En su lugar, debes usar onPause() para guardar datos
persistentes (como datos que deben guardarse en una base de datos) cuando el usuario
abandona la actividad.

Una buena manera de probar la capacidad de tu aplicación de restaurar su estado


es simplemente girar el dispositivo para que cambie la orientación de la pantalla.
Cuando cambia la orientación de la pantalla, el sistema destruye y vuelve a crear
la actividad para poder aplicar recursos alternativos que podrían estar disponibles
para la nueva configuración de pantalla. Solo por este motivo, es muy importante
que tu actividad restaure por completo su estado cuando se vuelva a crear, ya que
los usuarios generalmente giran la pantalla cuando usan aplicaciones.

Manejar cambios de configuración


Algunas configuraciones de dispositivos pueden cambiar durante el tiempo de
ejecución (como la orientación de la pantalla, la disponibilidad del teclado y el
idioma). Cuando se produce un cambio como este, Android vuelve a crear la
actividad en ejecución (el sistema llama a onDestroy() y, de inmediato, llama
a onCreate()). Este comportamiento fue diseñado para ayudar a tu aplicación a
adaptarse a las nuevas configuraciones al recargar automáticamente la aplicación
con recursos alternativos que tú proporcionaste (como diferentes diseños para las
diferentes orientaciones y tamaños de pantalla).

Si diseñas tu actividad correctamente para que sea capaz de afrontar un reinicio


como consecuencia de un cambio en la orientación de la pantalla y restaure el
estado de la actividad como se describió antes, tu aplicación será más resistente a
otros eventos inesperados en el ciclo de vida de la actividad.

La mejor manera de manejar un reinicio como ese es guardar y restaurar el estado


de tu actividad
usando onSaveInstanceState() y onRestoreInstanceState() (o onCreate())
, como en la sección anterior.

Para obtener más información acerca de los cambios de configuración que


ocurren durante el tiempo de ejecución y cómo puedes manejarlos, lee la
guía Manejo de cambios en tiempo de ejecución.

Coordinar actividades
Cuando una actividad inicia otra, ambas experimentan transiciones en el ciclo de
vida. La primera actividad se pausa y se detiene (aunque no se detendrá si aún
está visible en segundo plano) mientras se crea la otra actividad. Si esas
actividades comparten datos guardados en el disco o en alguna otra parte, es
importante que entiendas que la primera actividad no se detiene completamente
antes de que se cree la segunda, sino que el proceso de inicio de una segunda
actividad se superpone con el proceso de detención de la primera.

El orden de los callbacks del ciclo de vida está bien definido, especialmente
cuando las dos actividades están en el mismo proceso y una inicia la otra. Aquí te
mostramos el orden de las operaciones que ocurren cuando la actividad A inicia la
actividad B:

1. Se ejecuta el método onPause() de la actividad A.


2. Los métodos onCreate(), onStart() y onResume() de la actividad B se ejecutan
en secuencia. (Ahora la actividad B tiene la atención del usuario).
3. Por lo tanto, si la actividad A deja de verse en pantalla, se ejecuta su
método onStop().
Esta secuencia predecible de callbacks del ciclo de vida te permite administrar la
transición de información de una actividad a otra. Por ejemplo, si debes realizar
operaciones de escritura en una base de datos cuando la primera actividad se
detiene para que la siguiente pueda leerla, debes realizar operaciones de escribir
en la base de datos durante onPause() en lugar de hacerlo durante onStop().
Resumen de compatibilidad de
dispositivos
Android está diseñado para funcionar en muchos tipos diferentes de dispositivos,
desde teléfonos hasta tabletas y televisores. Como desarrollador, la gama de
dispositivos ofrece una gran audiencia potencial para su aplicación. Para que su
aplicación tenga éxito en todos estos dispositivos, debe tolerar cierta variabilidad
de funciones y proporcionar una interfaz de usuario flexible que se adapte a
diferentes configuraciones de pantalla.

Para facilitar su esfuerzo hacia ese objetivo, Android proporciona un marco de


aplicación dinámico en el que puede proporcionar recursos de
aplicación específicos de configuración en archivos estáticos (como diferentes
diseños XML para diferentes tamaños de pantalla). Luego, Android carga los
recursos adecuados según la configuración actual del dispositivo. Así que con un
poco de previsión en el diseño de su aplicación y algunos recursos de aplicación
adicionales, puede publicar un paquete de aplicación (APK) que proporcione una
experiencia de usuario optimizada en una variedad de dispositivos.

Sin embargo, si es necesario, puede especificar los requisitos de funciones de su


aplicación y controlar qué tipos de dispositivos pueden instalar su aplicación desde
Google Play Store. Esta página explica cómo puede controlar qué dispositivos
tienen acceso a sus aplicaciones y cómo prepararlas para asegurarse de que
lleguen al público adecuado. Para obtener más información sobre cómo puede
hacer que su aplicación se adapte a diferentes dispositivos, lea Cómo admitir
diferentes dispositivos .

¿Qué significa "compatibilidad"?

A medida que lea más sobre el desarrollo de Android, probablemente encontrará


el término "compatibilidad" en diversas situaciones. Hay dos tipos de
compatibilidad: compatibilidad de dispositivos y compatibilidad de aplicaciones .

Debido a que Android es un proyecto de código abierto, cualquier fabricante de


hardware puede construir un dispositivo que ejecute el sistema operativo
Android. Sin embargo, un dispositivo es "compatible con Android"solo si
puede ejecutar correctamente las aplicaciones escritas para el entorno de
ejecución de Android . Los detalles exactos del entorno de ejecución de Android
están definidos por el programa de compatibilidad de Android y cada dispositivo
debe pasar el conjunto de pruebas de compatibilidad (CTS) para que se considere
compatible.
Como desarrollador de aplicaciones, no debe preocuparse por si un dispositivo es
compatible con Android, ya que solo los dispositivos que son compatibles con
Android incluyen Google Play Store. Por lo tanto, puede estar seguro de que los
usuarios que instalan su aplicación desde Google Play Store están usando un
dispositivo compatible con Android.

Sin embargo, debe considerar si su aplicación es compatible con cada


configuración de dispositivo potencial. Debido a que Android se ejecuta en una
amplia gama de configuraciones de dispositivos, algunas funciones no están
disponibles en todos los dispositivos. Por ejemplo, algunos dispositivos pueden no
incluir un sensor de brújula. Si la funcionalidad principal de su aplicación requiere
el uso de un sensor de brújula, entonces su aplicación es compatible solo con
dispositivos que incluyen un sensor de brújula.

Controlando la disponibilidad de su aplicación para dispositivos

Android es compatible con una variedad de características que su aplicación


puede aprovechar a través de las API de la plataforma. Algunas características
están basadas en hardware (como un sensor de brújula), otras están basadas en
software (como widgets de aplicaciones) y otras dependen de la versión de la
plataforma. No todos los dispositivos son compatibles con todas las funciones, por
lo que es posible que deba controlar la disponibilidad de su aplicación para los
dispositivos en función de las funciones requeridas de su aplicación.

Para lograr la mayor base de usuarios posible para su aplicación, debe esforzarse
por admitir tantas configuraciones de dispositivo como sea posible con un solo
APK. En la mayoría de las situaciones, puede hacerlo desactivando las funciones
opcionales en tiempo de ejecución y proporcionando recursos de aplicaciones con
alternativas para diferentes configuraciones (como diferentes diseños para
diferentes tamaños de pantalla). Sin embargo, si es necesario, puede restringir la
disponibilidad de su aplicación a los dispositivos a través de Google Play Store
según las siguientes características del dispositivo:

 Características del dispositivo


 Versión de plataforma
 Configuracion de pantalla

Características del dispositivo


Para poder administrar la disponibilidad de su aplicación en función de las
funciones del dispositivo, Android define las ID de las funciones para
cualquier característica de hardware o software que pueda no estar disponible en
todos los dispositivos. Por ejemplo, el ID de función para el sensor de la brújula
es FEATURE_SENSOR_COMPASSy el ID de función para los widgets de la aplicación
es FEATURE_APP_WIDGETS.

Si es necesario, puede evitar que los usuarios instalen su aplicación cuando sus
dispositivos no proporcionan una característica determinada declarándola con
un <uses-feature> elemento en el archivo de manifiesto desu aplicación .

Por ejemplo, si su aplicación no tiene sentido en un dispositivo que carece de un


sensor de brújula, puede declarar el sensor de brújula según sea necesario con la
siguiente etiqueta de manifiesto:

<manifest ... > <uses-feature android: name =


"android.hardware.sensor.compass" android: required = "true"
/> ... </manifest>

Google Play Store compara las funciones que su aplicación requiere con las
funciones disponibles en el dispositivo de cada usuario para determinar si su
aplicación es compatible con cada dispositivo. Si el dispositivo no proporciona
todas las funciones que su aplicación requiere, el usuario no puede instalarla.

Sin embargo, si la funcionalidad principal de su aplicación no requiere una función


del dispositivo, debe establecer el required atributo "false"y verificar la función
del dispositivo en tiempo de ejecución. Si la función de la aplicación no está
disponible en el dispositivo actual, degradar con gracia la función de la aplicación
correspondiente. Por ejemplo, puede consultar si una característica está
disponible llamando dehasSystemFeature()esta manera:

KOTLIN

JAVA
si (! packageManager . hasSystemFeature ( PackageManager . FEATURE _
SENSOR _ COMPASS )) { // Este dispositivo no tiene una brújula,
desactive la función brújula disableCompassFeature () }

Para obtener información sobre todos los filtros que puede usar para controlar la
disponibilidad de su aplicación para los usuarios a través de Google Play Store,
consulte el documento Filtros en Google Play .
Nota: algunos permisos del sistema requieren implícitamente la disponibilidad de una función
del dispositivo. Por ejemplo, si su aplicación solicita permiso para acceder BLUETOOTH, esto
requiere implícitamente la FEATURE_BLUETOOTHfunción del dispositivo. Puede deshabilitar el
filtrado basado en esta función y hacer que su aplicación esté disponible para dispositivos sin
Bluetooth configurando el requiredatributo "false"en la <uses-feature>etiqueta. Para
obtener más información sobre las funciones del dispositivo requeridas implícitamente, lea
los Permisos que implican los requisitos de las funciones .

Versión de plataforma
Diferentes dispositivos pueden ejecutar diferentes versiones de la plataforma
Android, como Android 4.0 o Android 4.4. Cada versión de plataforma sucesiva a
menudo agrega nuevas API no disponibles en la versión anterior. Para indicar qué
conjunto de API están disponibles, cada versión de plataforma especifica un nivel
de API . Por ejemplo, Android 1.0 es el nivel API 1 y Android 4.4 es el nivel API 19.

El nivel de API le permite declarar la versión mínima con la que su aplicación es


compatible, utilizando la <uses-sdk>etiqueta de manifiesto y
su minSdkVersion atributo. Por ejemplo, las API de proveedor de calendario se
agregaron en Android 4.0 (nivel de API 14). Si su aplicación no puede funcionar
sin estas API, debe declarar el nivel 14 de API como la versión mínima admitida
de su aplicación.

El minSdkVersionatributo declara la versión mínima con la que su aplicación es


compatible y el targetSdkVersionatributo declara la versión más alta en la que
ha optimizado su aplicación.

Sin embargo, tenga en cuenta que los atributos en el <uses-sdk>elemento son


anulados por las propiedades correspondientes en
el build.gradlearchivo. Entonces, si está utilizando Android Studio, debe
especificar los valores minSdkVersiony los targetSdkVersionvalores allí:

android {
defaultConfig {
applicationId 'com.example.myapp' // Define el nivel de API mínimo
requerido para ejecutar la aplicación. minSdkVersion 15 // Especifica
el nivel de API utilizado para probar la aplicación. targetSdkVersion
28 ... } }
Para obtener más información sobre el build.gradlearchivo, lea acerca de cómo
configurar su compilación .

Cada versión sucesiva de Android proporciona compatibilidad para las


aplicaciones que se crearon utilizando las API de versiones anteriores de la
plataforma, por lo que su aplicación siempre debe ser compatible con las
versiones futuras de Android al usar las API documentadas de Android.

Nota: el targetSdkVersionatributo no impide que su aplicación se instale en versiones de


plataforma superiores al valor especificado, pero es importante porque le indica al sistema si
su aplicación debe heredar los cambios de comportamiento en las versiones más nuevas. Si
no actualiza la targetSdkVersionversión más reciente, el sistema asume que su aplicación
requiere algunos comportamientos de compatibilidad con versiones anteriores cuando se
ejecuta en la versión más reciente. Por ejemplo, entre los cambios de comportamiento en
Android 4.4 , las alarmas creadas con las AlarmManagerAPI ahora son inexactas de manera
predeterminada, por lo que el sistema puede agrupar las alarmas de las aplicaciones y
conservar la potencia del sistema, pero el sistema conservará el comportamiento anterior de la
API para su aplicación si su nivel de API objetivo es más bajo que "19".

Sin embargo, si su aplicación utiliza API agregadas en una versión más reciente
de la plataforma, pero no las requiere para su funcionalidad principal, debe
verificar el nivel de API en tiempo de ejecución y degradar las características
correspondientes cuando el nivel de API sea demasiado bajo. En este caso,
establezca el minSdkVersionvalor más bajo posible para la funcionalidad principal
de su aplicación, luego compare la versión del sistema actual SDK_INT, con una de
las constantes de nombre de código Build.VERSION_CODESque corresponda al
nivel de API que desea verificar. Por ejemplo:

KOTLIN

JAVA
if ( Build . VERSION . SDK _ INT < Build . VERSION _ CODES . HONEYCOMB
) { // Se ejecuta en algo más antiguo que el nivel API 11, así que
deshabilita // las funciones de arrastrar y soltar que usan <code> <a
href = "/ reference / android / content / ClipboardManager.html ">
ClipboardManager </a> </code> APIs disableDragAndDrop () }
Configuracion de pantalla
Android se ejecuta en dispositivos de varios tamaños, desde teléfonos hasta
tabletas y televisores. Para clasificar los dispositivos por su tipo de pantalla,
Android define dos características para cada dispositivo: el tamaño de la pantalla
(el tamaño físico de la pantalla) y la densidad de la pantalla (la densidad física de
los píxeles en la pantalla, conocida como DPI ). Para simplificar las diferentes
configuraciones, Android generaliza estas variantes en grupos que facilitan su
orientación:

 Cuatro tamaños generalizados: pequeño, normal, grande y grande.


 Y varias densidades generalizadas: mdpi (media), hdpi (alta), xhdpi (extra alta), xxhdpi
(extra extra alta) y otras.

De forma predeterminada, su aplicación es compatible con todos los tamaños y


densidades de pantalla, ya que el sistema realiza los ajustes adecuados a su
diseño de UI y los recursos de imagen según sea necesario para cada
pantalla. Sin embargo, debe optimizar la experiencia del usuario para cada
configuración de pantalla agregando diseños especializados para diferentes
tamaños de pantalla e imágenes de mapa de bits optimizadas para densidades de
pantalla comunes.

Para obtener información sobre cómo crear recursos alternativos para diferentes
pantallas y cómo restringir su aplicación a ciertos tamaños de pantalla cuando sea
necesario, lea Cómo admitir diferentes pantallas .

Controlando la disponibilidad de su aplicación por razones de negocios.

Además de restringir la disponibilidad de su aplicación según las características


del dispositivo, es posible que deba restringir la disponibilidad de su aplicación por
razones comerciales o legales. Por ejemplo, es poco probable que una aplicación
que muestra los horarios de los trenes del metro de Londres sea útil para los
usuarios fuera del Reino Unido. Para este tipo de situación, Google Play Store
ofrece opciones de filtrado en la Play Console que le permiten controlar la
disponibilidad de su aplicación por razones no técnicas, como la configuración
regional del usuario o el proveedor de servicios inalámbricos.

El filtrado para la compatibilidad técnica (como los componentes de hardware


necesarios) siempre se basa en la información contenida en su archivo APK. Pero
el filtrado por razones no técnicas (como la configuración geográfica) siempre se
maneja en la consola de Google Play .
Información general de recursos
Siempre debes externalizar los recursos como imágenes y strings del código de tu
aplicación para que puedas mantenerlos de forma independiente. Externalizar los
recursos también te permite proporcionar recursos alternativos que admiten
configuraciones específicas de los dispositivos, como idiomas o tamaños de
pantalla distintos, lo que cada vez es más importante, ya que más dispositivos con
tecnología Android están disponibles con configuraciones diferentes. A fin de
brindar compatibilidad con configuraciones diferentes, debes organizar los
recursos del directorio res/ del proyecto, para lo cual debes usar varios
subdirectorios que agrupen recursos por tipo y configuración.

Figura 1: Dos dispositivos diferentes, cada uno con el diseño predeterminado (la app no
proporciona diseños alternativos).

Figure 2: Dos dispositivos diferentes, cada uno con un diseño diferente para distintos tamaños
de pantalla.

En cualquier tipo de recurso, puedes especificar recursos predeterminados y


varios recursos alternativos para la aplicación:

 Los recursos predeterminados son los que debes usar sin importar la
configuración del dispositivo o cuando no hay recursos alternativos que coincidan
con la configuración actual.
 Los recursos alternativos son los que diseñaste para usar con una configuración
específica. A fin de especificar que un grupo de recursos es para una
configuración específica, agrega un calificador de configuración apropiado al
nombre del directorio.
Por ejemplo, si bien el diseño predeterminado de la IU se guarda en el
directorio res/layout/, puedes especificar que se debe usar un diseño diferente
cuando la pantalla tiene orientación horizontal guardándolo en el
directorio res/layout-land/. Android aplica automáticamente los recursos
correspondientes estableciendo una coincidencia de la configuración actual del
dispositivo con los nombres del directorio de recursos.

En la figura 1, se ejemplifica cómo aplica el sistema el mismo diseño en dos


dispositivos diferentes cuando no hay recursos alternativos disponibles. En la
figura 2, se muestra la misma aplicación cuando se agrega un recurso alternativo
de diseño para pantallas más grandes.

Los siguientes documentos proporcionan una guía completa sobre cómo puedes
organizar los recursos de la aplicación, especificar recursos alternativos, acceder a
ellos en la aplicación y más:

Provisión de recursos

Información sobre los tipos de recursos que puedes incluir en tu app, dónde
guardarlos y cómo crear recursos alternativos para configuraciones
específicas de dispositivos.

Acceso a recursos

Información sobre cómo usar los recursos que proporcionaste, haciendo


referencia a ellos desde el código de la aplicación u otros recursos XML.

Manejo de cambios en tiempo de ejecución

Información sobre cómo administrar cambios de configuración que tienen


lugar mientras la actividad se está ejecutando.

Localización

Una guía con un enfoque ascendente para localizar la aplicación con


recursos alternativos. Si bien este es tan solo un uso específico de recursos
alternativos, es muy importante para llegar a más usuarios.

Recursos XML complejos

Un formato XML para compilar recursos complejos, como elementos de


diseño de vector animado en un único archivo XML.

Tipos de recursos

Una referencia a varios tipos de recursos que puedes proporcionar, en la


que se describen los elementos XML, los atributos y la sintaxis. Por
ejemplo, en esta referencia, se muestra cómo crear un recurso para menús
de la aplicación, elementos de diseño, animaciones y más.

Información general de la IU
Todos los elementos de la interfaz de usuario de una app para Android están
desarrollados con objetos View yViewGroup. Una View es un objeto que dibuja
algo en la pantalla con lo que el usuario puede interactuar. Un ViewGroup es un
objeto que tiene otros objetos View (y ViewGroup) para definir el diseño de la
interfaz.

Android proporciona una colección de subclases View y ViewGroup que te ofrecen


controles de entrada comunes (como los botones y los campos de texto) y varios
modelos de diseño (como un diseño lineal o relativo).

Diseño de la interfaz de usuario

La interfaz de usuario de cada componente de tu app se define con una jerarquía


de objetos View y ViewGroup, como se muestra en la figura 1. Cada grupo de
vista es un contenedor invisible que organiza vistas secundarias, mientras que las
vistas secundarias pueden ser controles de entrada u otros widgets que dibujan
alguna parte de la IU. Este árbol de jerarquía puede ser tan simple o complejo
como lo necesites (pero la simplicidad es lo mejor para el rendimiento).

Figura 1: Ilustración de una jerarquía de vistas, que define un diseño de IU.

Para declarar el diseño, puedes crear una instancia de objetos View en el código y
desarrollar un árbol, pero la manera más sencilla y efectiva para definir el diseño
consiste en utilizar un archivo XML. XML ofrece una estructura en lenguaje natural
para el diseño, similar a HTML.

El nombre de un elemento XML para una vista se relaciona con la clase de


Android que representa. Por lo tanto, un elemento <TextView> crea un
widget TextView en la IU, y un elemento <LinearLayout> crea un grupo de
vistaLinearLayout.

Por ejemplo, un diseño vertical simple con una vista de texto y un botón tiene esta
apariencia:

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


<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a TextView" />
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="I am a Button" />
</LinearLayout>

Cuando cargas un recurso de diseño en la app, Android inicia cada nodo del
diseño en un objeto de tiempo de ejecución que puedes usar para definir
comportamientos adicionales, consultar el estado del objeto o modificar el diseño.

Para consultar una guía completa sobre la creación de un diseño de IU,


consulta Diseños XML.

Componentes de la interfaz de usuario

No es necesario que compiles toda la IU con objetos View y ViewGroup. Android


proporciona varios componentes de app que ofrecen un diseño de IU estándar, en
el cual solo tienes que definir el contenido. Cada uno de estos componentes de IU
tienen un conjunto único de API, que se describen en los documentos
correspondientes, como Adición de la barra de app, Cuadros de
diálogo y Notificaciones de estado.

Das könnte Ihnen auch gefallen