Un Intent
es un objeto de mensajería que puedes usar para solicitar una acción
desde otro componente de la aplicación.
Aunque los intents facilitan la comunicación entre los componentes de varias maneras, existen tres
casos de uso fundamentales:
- Cómo iniciar una actividad
Un
Activity
representa una sola pantalla en una app. Puedes iniciar una instancia nueva de unActivity
pasando unIntent
astartActivity()
. ElIntent
describe la actividad que se debe iniciar y contiene los datos necesarios.Si deseas recibir un resultado de la actividad cuando finalice, llama a
startActivityForResult()
. Tu actividad recibe el resultado como un objetoIntent
separado en la devolución de llamada deonActivityResult()
de tu actividad. Para obtener más información, consulta la guía Actividades. - Cómo iniciar un servicio
Un
Service
es un componente que realiza operaciones en segundo plano. sin una interfaz de usuario. Con Android 5.0 (nivel de API 21) y versiones posteriores, puedes iniciar un servicio conJobScheduler
. Más información acerca deJobScheduler
, consulta suAPI-reference documentation
En las versiones anteriores a Android 5.0 (nivel de API 21), puedes iniciar un servicio usando de la clase
Service
. Puedes iniciar un servicio para realizar una operación única (como descargar un archivo). Para ello, pasa unIntent
. astartService()
.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 un
Intent
abindService()
. Para obtener más información, consulta la guía de Servicios. - Publicación de una transmisión
Una emisión es un aviso que cualquier aplicación puede recibir. El sistema ofrece varias para eventos del sistema, como cuando se inicia el sistema o cuando el dispositivo comienza a cargarse. Puedes transmitir una emisión a otras apps pasando un
Intent
asendBroadcast()
osendOrderedBroadcast()
.
El resto de esta página explica cómo funcionan las intents y cómo debes usarlas. Para obtener información relacionada, consulta Cómo interactuar con otras apps y Uso Compartido del Contenido.
Tipos de intents
Existen dos tipos de intents:
- Los intents explícitos especifican qué componente de qué aplicación satisfará el intent, ya que especifican un
ComponentName
completo. Deberás normalmente usan un intent explícito para iniciar un componente en tu propia app, porque conoces el nombre de clase de la actividad o el servicio que quieres iniciar. Para ejemplo, puedes iniciar una nueva actividad dentro de la aplicación en respuesta a una acción del usuario, o iniciar un servicio que descargue un archivo en segundo plano. - Los intents implícitos no nombran un componente específico, sino que declaran una acción general. lo que permite que un componente de otra app lo controle. Por ejemplo, si quieres mostrar al usuario una ubicación en un mapa, puedes usar un intent implícito para solicitar que se cree una app muestra una ubicación específica en un mapa.
La figura 1 muestra cómo se usa una intent para iniciar una actividad. Cuando
El objeto Intent
nombra un componente de actividad específico de forma explícita, el sistema
inicia de inmediato ese componente.
Cuando usas un intent implícito, el sistema Android busca el componente apropiado para iniciar
comparando el contenido del intent con los filtros de intents declarados en el archivo de manifiesto de otras apps en la
dispositivo. Si el intent coincide con un filtro de intents, el sistema inicia ese componente y lo entrega.
el objeto Intent
. Si varios filtros de intents son compatibles, el sistema
Muestra un diálogo para que el usuario pueda elegir qué app usar.
Un filtro de intents es una expresión en el archivo de manifiesto de una app que especifica el tipo de intents que el componente podría recibir. Por ejemplo, al declarar un filtro de intents para una actividad, permites que otras apps inicien tu actividad directamente con un tipo determinado de intent. Del mismo modo, si no declaras ningún filtro de intents para una actividad, esta solo se puede iniciar con un intent explícito.
Precaución: Para garantizar que tu app sea segura,
usa un lenguaje de marcado explícito
cuando inicies un Service
y no
declarar filtros de intents para tus servicios. El uso de un intent explícito para iniciar un servicio es un riesgo de seguridad porque no puedes estar seguro de qué servicio responderá al 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 llamas a bindService()
con un intent implícito.
Cómo crear una intent
Un objeto Intent
contiene información que usa el sistema Android
para determinar qué componente debe comenzar (como el nombre exacto del componente o el componente)
que debe recibir el intent), además de información que el componente receptor utiliza en
para realizar la acción correctamente (como la acción que se debe realizar y los datos sobre los que debe actuar).
La información principal que se incluye en un Intent
es la siguiente:
- Nombre del componente
- Es 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 app definido en el nombre del componente. Sin un nombre de componente, el intent es implícito y el el sistema decide qué componente debe recibir el intent según la otra información de la intent (como la acción, los datos y la categoría, que se describen a continuación). Si necesitas iniciar una campaña de la aplicación, debes especificar el nombre del componente.
Nota: Cuando inicies un
Service
, especifica siempre el nombre del componente. De lo contrario, no puedes estar seguro de qué servicio responderá al intent, y el usuario no puede ver qué servicio se inicia.Este campo de
Intent
es un objetoComponentName
, que puedes especificar con un objeto Es el nombre de clase calificado del componente de destino, incluido el nombre del paquete de la app, por ejemplo,com.example.ExampleActivity
Puedes establecer el nombre del componente consetComponent()
,setClass()
,setClassName()
. o con elIntent
. - Acción
- Es una cadena que especifica la acción genérica que se debe realizar (como ver o elegir).
En el caso de la intent de una emisión, es la acción que se produjo y que se está registrando. La acción determina en gran medida cómo se estructura el resto de la intent, en particular la información que se incluye en los datos y extras.
Puedes especificar tus propias acciones para que las usen los intents dentro de tu app (o para que las usen otras apps para invocar componentes en tu app), pero, por lo general, se deben especificar constantes de acción definido por la clase
Intent
u otras clases del framework. Estos son algunos ejemplos Acciones comunes para iniciar una actividad:ACTION_VIEW
- Usa esta acción en un intent con
startActivity()
cuando tengas información que que una actividad puede mostrar al usuario, como una foto para ver en una app de galería o una dirección a en una app de mapas. ACTION_SEND
- También conocido como el intent share, debes usarlo en un intent con
startActivity()
cuando tengas algunos datos que el usuario pueda. Compartir a través de otra app, como una app de correo electrónico o de uso compartido en redes sociales
Consulta la referencia de la clase
Intent
para obtener más información constantes que definen acciones genéricas. Otras acciones se definen en otro lugar del framework de Android, como enSettings
para acciones que abren pantallas específicas en la app de Configuración del sistema.Puedes especificar la acción para un intent con
setAction()
o con un constructorIntent
.Si defines tus propias acciones, asegúrate de incluir el nombre del paquete de tu app. como un prefijo, como se muestra en el siguiente ejemplo:
Kotlin
const val ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL"
Java
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
- Datos
- El URI (un objeto
Uri
) que hace referencia a los datos de en los que se debe actuar o que Es el tipo de MIME de esos datos. Por lo general, la acción del intent determina el tipo de datos que se proporciona. Para Por ejemplo, si la acción esACTION_EDIT
, los datos deben contener la Es el URI del documento que se editará.Cuando se crea un intent, a menudo es importante especificar el tipo de datos (su tipo de MIME) además de su URI. Por ejemplo, una actividad que puede mostrar imágenes probablemente no sea capaz de reproducir un archivo de audio aunque los formatos de URI sean similares. Especificar el tipo de MIME de los datos ayuda a Android a encontrar el mejor componente para recibir tu intent. Sin embargo, el tipo de MIME a veces se puede deducir del URI, especialmente cuando los datos son un URI
content:
. Un URIcontent:
indica que los datos se encuentran en el dispositivo y controlado por unContentProvider
, que hace que el tipo de MIME de datos sea visible para el sistemaPara establecer solo el URI de datos, llama a
setData()
. Para establecer solo el tipo de MIME, llama asetType()
. Si es necesario, puedes establecer ambos de forma explícita consetDataAndType()
.Precaución: Si deseas establecer el URI y el tipo de MIME, no llames a
setData()
ysetType()
porque cada una anula el valor del otro. Usar siempresetDataAndType()
para establecer ambos URI y tipo de MIME. - Categoría
- Una cadena que contiene información adicional sobre el tipo de componente
que debe manejar el intent. Cualquier cantidad de descripciones de categorías se puede
se coloca en un intent, pero la mayoría de los 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 desde el selector de aplicaciones del sistema.
Consulta la descripción de la clase
Intent
para ver la lista completa de categorías.Puedes especificar una categoría con
addCategory()
.
Las propiedades nombradas anteriormente (nombre de componente, acción, datos y categoría) representan las características definitorias de un intent. Con la lectura de estas propiedades, el sistema Android puede resolver qué componente de la aplicación debe iniciar. Sin embargo, un intent puede llevar información adicional que no afecta cómo se resuelve en un componente de la aplicación. Una intent también puede incluir la siguiente información:
- Adicional
- Pares clave-valor que tienen información adicional necesaria para lograr el objetivo
la acción solicitada.
Al igual que algunas acciones usan tipos particulares de URI de datos, algunas acciones también usan extras específicos.
Puedes agregar datos adicionales con varios métodos
putExtra()
. cada uno acepta dos parámetros: el nombre de la clave y el valor. También puedes crear un objetoBundle
con todos los datos adicionales y, luego, insertarlos elBundle
en elIntent
conputExtras()
.Por ejemplo, cuando creas un intent para enviar un correo electrónico con
ACTION_SEND
, puedes especificar el destinatario para con elEXTRA_EMAIL
y especifica el asunto con el TeclaEXTRA_SUBJECT
.La clase
Intent
especifica muchas constantesEXTRA_*
para tipos de datos estandarizados. Si necesitas declarar tus propias claves adicionales (para intents que que recibe tu aplicación), asegúrate de incluir el nombre del paquete como un prefijo, como se muestra en el siguiente ejemplo:Kotlin
const val EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS"
Java
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
Precaución: No uses
Parcelable
ni Datos deSerializable
cuando envías un intent que esperas otra app para recibir. Si se muestra una app intenta acceder a los datos de un objetoBundle
, pero no tienen acceso a la clase parcelada o serializada, el sistema envíaRuntimeException
- Marcas
- Las marcas se definen en la clase
Intent
, que funcionan como metadatos para el . Las marcas pueden indicar al sistema Android cómo iniciar una actividad (por ejemplo, qué tarea la actividad debería pertenecer a) y cómo tratarlo tras su lanzamiento (por ejemplo, si pertenece a la lista de actividades).Para obtener más información, consulta el método
setFlags()
.
Ejemplo de una intent explícita
Un intent explícito es aquel que se usa para iniciar un componente específico de la aplicación, como
una actividad o un servicio particular en tu app. Para crear un intent explícito, define
el nombre del componente para el objeto Intent
,
otras propiedades del intent son opcionales.
Por ejemplo, si compilaste un servicio en tu app, llamado DownloadService
,
diseñado para descargar un archivo de la Web, puedes comenzarlo con el siguiente código:
Kotlin
// Executed in an Activity, so 'this' is theContext
// The fileUrl is a string URL, such as "http://www.example.com/image.png" val downloadIntent = Intent(this, DownloadService::class.java).apply { data =Uri.parse
(fileUrl) } startService(downloadIntent)
Java
// Executed in an Activity, so 'this' is theContext
// 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 Intent(Context, Class)
este constructor proporciona la app Context
y el
componente, un objeto Class
. Por lo tanto,
este intent inicia de manera explícita la clase DownloadService
en la app.
Para obtener más información sobre la creación y el inicio de un servicio, consulta el Servicios.
Ejemplo de una intent implícita
Un intent implícito especifica una acción que puede invocar cualquier aplicación en el dispositivo que pueda para realizar la acción. El uso de un intent implícito es útil cuando la app no puede realizar la acción, pero otras apps probablemente sí, y quieres que el usuario elija qué app usar.
Por ejemplo, si tienes contenido que quieres que el usuario comparta con otras personas,
crear un intent
con la acción ACTION_SEND
y agregar extras
que especifiquen el contenido que se compartirá. Cuando llames
startActivity()
con ese intent, el usuario puede
elige una app mediante la cual compartir el contenido.
Kotlin
// Create the text message with a string. val sendIntent = Intent().apply { action = Intent.ACTION_SEND putExtra(Intent.EXTRA_TEXT, textMessage) type = "text/plain" } // Try to invoke the intent. try { startActivity(sendIntent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
// 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"); // Try to invoke the intent. try { startActivity(sendIntent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
Cuando se llama a startActivity()
, el sistema examina todas las apps instaladas para determinar cuáles pueden manejar este tipo de intent (un intent con la acción ACTION_SEND
y que tiene datos de texto/sin formato). Si solo hay una app que puede manejarla, esta se abre de inmediato y se le otorga
. Si ninguna otra app puede controlarlo, tu app puede detectar la
ActivityNotFoundException
que ocurra. Si varias actividades aceptan el intent, el sistema
Muestra un diálogo como el que aparece en la Figura 2, para que el usuario pueda elegir qué app usar.
En la guía, también se proporciona más información sobre cómo iniciar otras apps. sobre enviar al usuario a otra app.
Cómo forzar un selector de apps
Cuando más de una app responde a tu intent implícito, el usuario puede seleccionar qué app se debe usar y establecerla como la opción predeterminada para la acción. La capacidad de seleccionar un valor predeterminado es útil cuando se realiza una acción para la que el usuario probablemente quiera usar siempre la misma aplicación, por ejemplo, al abrir una página web (los usuarios a menudo prefieren un solo navegador web).
Sin embargo, si varias apps pueden responder al intent y el usuario podría querer usar una diferente cada vez, debes mostrar explícitamente un cuadro de diálogo de selección. En el cuadro de diálogo de selección
usuario seleccione qué aplicación usar para la acción (el usuario no puede seleccionar una aplicación predeterminada para
la acción). Por ejemplo, cuando la app realiza acciones con la acción ACTION_SEND
, es posible que los usuarios quieran compartir contenido usando otra app, según
según su situación actual, por lo que siempre debes usar el diálogo de selección, como se muestra en la Figura 2.
Para mostrar el selector, crea un Intent
con createChooser()
y pásalo a startActivity()
, como se muestra en el siguiente ejemplo.
En este ejemplo, se muestra un diálogo con una lista de apps que responden al intent pasado al método createChooser()
, con el texto proporcionado como
título del diálogo.
Kotlin
val sendIntent = Intent(Intent.ACTION_SEND) ... // Always use string resources for UI text. // This says something like "Share this photo with" val title: String = resources.getString(R.string.chooser_title) // Create intent to show the chooser dialog val chooser: Intent = Intent.createChooser(sendIntent, title) // Verify the original intent will resolve to at least one activity if (sendIntent.resolveActivity(packageManager) != null) { startActivity(chooser) }
Java
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); }
Detecta lanzamientos de intents no seguros
Tu app podría iniciar intents para navegar entre componentes dentro de ella. o para realizar una acción en nombre de otra app. Para mejorar la seguridad de la plataforma, Android 12 (nivel de API 31) y las versiones posteriores proporcionan una función de depuración que te advierte si tu app realiza un inicio no seguro de un intent. Por ejemplo, tu app podría realizar un lanzamiento no seguro de un intent anidado, que es un intent que se pasa como un extra en otro intent.
Si tu app realiza las siguientes dos acciones, el sistema detecta un lanzamiento de intent inseguro y se produce un incumplimiento de StrictMode:
- La app descomprime un intent anidado desde los valores adicionales de un intent entregado.
- La app inicia inmediatamente un componente de la app con ese intent anidado, como cuando se pasa el intent a
startActivity()
,startService()
obindService()
.
Para obtener más detalles sobre cómo identificar esta situación y realizar cambios en tu app, lee la entrada de blog sobre Nesting de Android Intents en Medium.
Cómo verificar si hay lanzamientos de intents no seguros
Para verificar lanzamientos de intents no seguros en la app, llama a detectUnsafeIntentLaunch()
cuando configures VmPolicy
, como se muestra en el siguiente fragmento de código. Si la app detecta un incumplimiento de StrictMode, te recomendamos detener la ejecución de la app a fin de proteger la información potencialmente sensible.
Kotlin
fun onCreate() { StrictMode.setVmPolicy(VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()) }
Java
protected void onCreate() { StrictMode.setVmPolicy(new VmPolicy.Builder() // Other StrictMode checks that you've previously added. // ... .detectUnsafeIntentLaunch() .penaltyLog() // Consider also adding penaltyDeath() .build()); }
Usa los intents de manera más responsable
Para minimizar la posibilidad de un lanzamiento de intent no seguro y un incumplimiento de StrictMode, y sigue estas prácticas recomendadas.
Copia solamente los valores adicionales y fundamentales dentro de los intents, y realiza cualquier limpieza o validación necesaria. Es posible que la app copie los valores adicionales de un intent a otro que se use para lanzar un componente nuevo. Esto sucede cuando la app llama a putExtras(Intent)
o putExtras(Bundle)
.
Si la app realiza una de estas operaciones, copia solo los valores adicionales que espera el componente receptor. Si el otro intent (que recibe la copia) lanza un componente que no se exportó, limpia y valida los valores adicionales antes de copiarlos en el intent que lanza el componente.
No exportes los componentes de la app innecesariamente. Por ejemplo, si
desees iniciar un componente de la app con un intent anidado interno, establece ese
atributo android:exported
del componente a false
.
Usa un PendingIntent
en lugar de un intent anidado. De esta manera, cuando otra app separa el PendingIntent
de su Intent
que lo contiene, la otra app puede iniciar el PendingIntent
con la identidad de tu app. Esta configuración permite que la otra app inicie de forma segura cualquier componente, incluido un componente no exportado, en tu app.
El diagrama de la figura 2 muestra cómo el sistema pasa el control de tu (cliente). app a otra app (de servicio) y de vuelta a tu app:
- Tu app crea un intent que invoca una actividad en otra app. En un radio de
ese intent, agregas un objeto
PendingIntent
como objeto adicional. Esta intent pendiente Invoca un componente en tu app. este componente no se exporta. - Cuando recibe el intent de tu app, la otra app extrae los atributos anidados
PendingIntent
. - La otra app invoca el método
send()
en el objetoPendingIntent
. - Después de devolver el control a tu app, el sistema invoca intent usando el contexto de tu app.
Figura 2: Diagrama de la comunicación entre apps cuando se usa un elemento pendiente anidado .
Cómo recibir una intent implícita
Para anunciar qué intents implícitos puede recibir tu app, declara uno o más filtros de intents para
cada uno de los componentes de tu app con un objeto <intent-filter>
de tu archivo de manifiesto.
Cada filtro de intents especifica el tipo de intents que acepta según la acción del intent,
los datos y la categoría. El sistema entrega un intent implícito al componente de la aplicación solo si la
puede pasar por uno de tus filtros de intents.
Nota: Un intent explícito 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 app de galería de imágenes puede tener dos filtros: uno
para ver una imagen y otro filtro para editarla. Cuando comienza la actividad,
Inspecciona el Intent
y decide cómo comportarse según la información.
en Intent
(por ejemplo, para 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 correspondiente (como un elemento <activity>
).
En cada componente de la app que incluya un elemento <intent-filter>
,
establece explícitamente un valor para
android:exported
Este atributo indica si otras apps pueden acceder al componente de la app. En algunos
situaciones, como las actividades cuyos filtros de intents incluyen las
LAUNCHER
categoría, es útil establecer este atributo en true
. De lo contrario,
es más seguro establecer este atributo en false
.
Advertencia: Si una actividad, un servicio o una transmisión
en tu app usa filtros de intents y no establece explícitamente el valor
para android:exported
, no se puede instalar la app en un dispositivo que
ejecuta Android 12 o una versión posterior.
Dentro de <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 intent aceptada, en el atributo
name
. El valor Debe ser el valor de string literal de una acción, no la constante de clase. <data>
- Declara el tipo de datos que se acepta mediante uno o más atributos que especifican varios
aspectos del URI de datos (
scheme
,host
,port
,path
) y el tipo de MIME. <category>
- Declara la categoría del intent aceptada, en el atributo
name
. El valor debe ser el de la cadena literal de una acción, no la constante de clase.Nota: Para recibir intents implícitos, debes debes incluir Categoría
CATEGORY_DEFAULT
en el filtro de intents. Los métodosstartActivity()
ystartActivityForResult()
tratan todos los intents como si declararan la categoríaCATEGORY_DEFAULT
. Si no declaras esta categoría en el filtro de intents, no se resolverá ningún intent implícito en tu actividad.
Por ejemplo, a continuación, puedes ver una declaración de actividad con un filtro de intents para recibir un
ACTION_SEND
cuando el tipo de datos es texto:
<activity android:name="ShareActivity" android:exported="false"> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter> </activity>
Puedes crear un filtro que incluya más de una instancia de
<action>
:
<data>
o
<category>
Si es así, debes asegurarte de que el componente pueda manejar cualquier
combinaciones de esos elementos de filtro.
Cuando quieres manejar varios tipos de intents, pero solo en combinaciones específicas de acción, datos y tipo de categoría, debes crear varios filtros de intents.
Un intent implícito se prueba con un filtro comparando el intent con cada uno de los tres elementos. Para que se entregue al componente, la intent debe pasar las tres pruebas. Si no coincide ni siquiera con uno de ellos, el sistema Android no entregará el intent al este componente. Sin embargo, como un componente puede tener varios filtros de intents, una intent que no pase por el filtro de un componente quizá pase por otro filtro. En la siguiente sección, encontrarás más información sobre cómo el sistema resuelve los intents. sobre la resolución de intents.
Precaución: El uso de un filtro de intents no es una forma segura de evitar que se inicien otras apps.
tus componentes. Aunque los filtros de intents restringen un componente para que responda únicamente
ciertos tipos de intents implícitos, otra aplicación puede iniciar potencialmente el componente de tu aplicación
usando un intent explícito si el desarrollador determina los nombres de tus componentes.
Si es importante que solo tu app pueda iniciar uno de tus componentes, no declares filtros de intents en tu manifiesto. En cambio, establece la
Atributo exported
a "false"
para ese componente.
De manera similar, para evitar ejecutar accidentalmente el Service
de otra app, siempre usa una intent explícita cuando inicies tu propio servicio.
Nota:
Para todas las actividades, debes declarar tus filtros de intents en el archivo de manifiesto.
Sin embargo, los filtros de receptores de emisión pueden registrarse de forma dinámica llamando a registerReceiver()
. Luego, puedes cancelar el registro del receptor con unregisterReceiver()
. Si lo haces, tu app
esperará emisiones específicas solo durante un plazo especificado mientras está ejecutándose.
Ejemplos de filtros
Para demostrar algunos de los comportamientos del filtro de intents, aquí se muestra un ejemplo desde el archivo de manifiesto de una aplicación de uso compartido social:
<activity android:name="MainActivity" android:exported="true"> <!-- 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" android:exported="false"> <!-- 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 inicia la app con el ícono de selector por primera vez:
- 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 nombre de esta actividad El ícono debe colocarse en el selector de aplicaciones del sistema. Si el elemento<activity>
no especifica un ícono conicon
, el sistema usará el ícono de<application>
.
Estos dos deben sincronizarse para que la actividad aparezca en el selector de la aplicación.
La segunda actividad, ShareActivity
, tiene como objetivo facilitar el uso compartido de texto y contenido multimedia.
contenido. Si bien los usuarios pueden ingresar a esta actividad navegando hasta ella desde MainActivity
,
también pueden ingresar ShareActivity
directamente desde otra app que emita una respuesta
que coincida con uno de los dos filtros de intents.
Nota: El tipo MIME,
application/vnd.google.panorama360+jpg
es un tipo de datos especial que especifica
fotos panorámicas, que puedes controlar con la
panorámicas.
Cómo hacer coincidir los intents con los de otras apps filtros de intents
Si otra app se orienta a Android 13 (nivel de API 33) o versiones posteriores, puede controlar tu
el intent de una app solo si tu intent coincide con las acciones y categorías de una
<intent-filter>
en la otra app. Si el sistema no encuentra un
una coincidencia, arroja un
ActivityNotFoundException
La app emisora debe controlar
esta excepción.
Del mismo modo, si actualizas tu app para que se oriente a Android 13
o una superior, todos los intents que se originan en apps externas se entregan a un
componente exportado de tu app solo si ese intent coincide con las acciones y
categorías de un elemento <intent-filter>
que tu app declara. Este comportamiento se produce independientemente de la versión del SDK de destino de la app de envío.
En los siguientes casos, no se aplica de manera forzosa la coincidencia de intents:
- Intents enviados a componentes que no declaran ningún filtro de intents.
- Intents que se originan en la misma app.
- Intents que se originan en el sistema es decir, los intents que se envían desde el "UID del sistema" (uid=1000). Las apps del sistema incluyen
system_server
y apps que configuranandroid:sharedUserId
comoandroid.uid.system
. - Intents que se originan en la raíz.
Obtén más información sobre la coincidencia de intenciones.
Cómo usar una intent pendiente
Un objeto PendingIntent
es un wrapper alrededor de un objeto Intent
. El propósito principal de un PendingIntent
es otorgar permiso a una aplicación externa
usar el objeto Intent
contenido como si se ejecutara desde tu
propio proceso de la app.
Estos son algunos de los casos de uso principales de una intent pendiente:
- Declarar un intent que se ejecutará cuando el usuario realice una acción con tu Notification
(el archivo
NotificationManager
del sistema Android ejecuta elIntent
). - Declarar un intent que se ejecutará cuando el usuario realice una acción con tu
Widget de la app
(la app de la pantalla principal ejecuta
Intent
). - Declarar un intent que se ejecutará en un momento específico en el futuro (el Centro de
AlarmManager
del sistema ejecutaIntent
).
Así como cada objeto Intent
está diseñado para que lo controle un usuario
tipo de componente de app (ya sea un Activity
, un Service
o
un objeto BroadcastReceiver
), por lo tanto, también debe ser un elemento PendingIntent
crear con la misma consideración. Cuando usas un intent pendiente, la app no
y ejecutar el intent con una llamada como startActivity()
En cambio, debes declarar el tipo de componente deseado cuando crees el
PendingIntent
llamando al método de creador respectivo:
PendingIntent.getActivity()
para unIntent
que inicia unActivity
PendingIntent.getService()
para unIntent
que inicia unService
PendingIntent.getBroadcast()
para unIntent
que inicia unBroadcastReceiver
A menos que tu app reciba intents pendientes de otras apps,
Es probable que los métodos anteriores para crear PendingIntent
sean los únicos
PendingIntent
que necesitarás.
Cada método toma el objeto Context
actual de la app, el
Intent
que quieres unir y una o más marcas que especifiquen
la manera en que se debe usar el intent (por ejemplo, si el intent se puede usar más de una vez)
Para obtener más información sobre el uso de intents pendientes, consulta la documentación de cada uno de ellos. de los casos de uso respectivos, como en las Notificaciones. y las guías de la API de App Widgets.
Especifica la mutabilidad
Si la app se orienta a Android 12 o versiones posteriores, debes especificar la
de cada objeto PendingIntent
que crea tu app. Para declarar que un objeto PendingIntent
determinado es mutable o inmutable, usa la marca PendingIntent.FLAG_MUTABLE
o PendingIntent.FLAG_IMMUTABLE
, respectivamente.
Si tu app intenta crear un objeto PendingIntent
sin establecer una de esas marcas de mutabilidad, el sistema arroja una excepción IllegalArgumentException
, y aparece el siguiente mensaje en Logcat:
PACKAGE_NAME: Targeting S+ (version 31 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.
Crea intents pendientes inmutables cuando sea posible
En la mayoría de los casos, tu app debe crear objetos PendingIntent
inmutables, como se muestra en el siguiente fragmento de código. Si un objeto PendingIntent
es inmutable,
otras apps no podrán modificar el intent para ajustar el resultado de invocar
.
Kotlin
val pendingIntent = PendingIntent.getActivity(applicationContext, REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE)
Java
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), REQUEST_CODE, intent, /* flags */ PendingIntent.FLAG_IMMUTABLE);
Sin embargo, algunos casos de uso requieren objetos PendingIntent
mutables:
- Admitir acciones de respuesta directa en
notificaciones. El
la respuesta directa requiere un cambio en los datos de clips del objeto PendingIntent
asociado a la respuesta. Por lo general, este cambio se solicita
FILL_IN_CLIP_DATA
como una marca parafillIn()
. - Asociar las notificaciones con el framework de Android Auto mediante instancias de
CarAppExtender
- Colocar conversaciones en burbujas con instancias
de
PendingIntent
. Un objetoPendingIntent
mutable permite que el sistema aplique las marcas correctas, comoFLAG_ACTIVITY_MULTIPLE_TASK
yFLAG_ACTIVITY_NEW_DOCUMENT
- Cómo solicitar información sobre la ubicación del dispositivo mediante una llamada
requestLocationUpdates()
o APIs similares. El objeto mutablePendingIntent
permite que el sistema agregue extras de intent que representan eventos de ciclo de vida de la ubicación. Estos eventos incluyen un en la ubicación y cuando un proveedor esté disponible. - Programar alarmas con
AlarmManager
El objeto mutablePendingIntent
permite que el sistema agregue el elementoEXTRA_ALARM_COUNT
intent adicional. Este extra representa la cantidad de veces que una alarma repetitiva se activó. Al contener este extra, el intent puede notificar con precisión una aplicación para saber si una alarma repetitiva se activó varias veces, por ejemplo, cuando el dispositivo estaba suspendido.
Si tu app crea un objeto PendingIntent
mutable, te recomendamos que uses un intent explícito y completes el elemento ComponentName
. De esa manera, cada vez que otra app invoque el PendingIntent
y pase el control a tu app, siempre se iniciará el mismo componente.
Cómo usar intents explícitos en intents pendientes
Para definir mejor la manera en que otras apps pueden usar los intents pendientes de tu app, haz lo siguiente: unen un intent pendiente alrededor de un intent explícito. Para seguir esta práctica recomendada, haz lo siguiente:
- Cómo comprobar que los campos de acción, paquete y componente del intent de base de configuración.
-
Usa
FLAG_IMMUTABLE
, agregados en Android 6.0 (nivel de API 23) para crear intents pendientes. Esta marca evita que las apps que reciben unPendingIntent
completen propiedades que no se propagaron. Si laminSdkVersion
de tu app es22
o inferiores, pueden ofrecer seguridad y compatibilidad juntos con el siguiente código:if (Build.VERSION.SDK_INT >= 23) { // Create a PendingIntent using FLAG_IMMUTABLE. } else { // Existing code that creates a PendingIntent. }
Resolución de intents
Cuando el sistema recibe un intent implícito para iniciar una actividad, busca el mejor actividad para la intent al compararla con los filtros de intents según tres aspectos:
- Acción.
- Datos (tanto URI como tipo de datos)
- Categoría
En las siguientes secciones, se describe cómo se hacen coincidir los intents con los componentes adecuados según la declaración de filtro de intents del archivo de manifiesto de la app.
Prueba de acción
Para especificar las acciones de intents aceptadas, un filtro de intents puede declarar cero o más.
Elementos <action>
, como se muestra en el siguiente ejemplo:
<intent-filter> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.VIEW" /> ... </intent-filter>
Para pasar este filtro, la acción especificada en el archivo Intent
debe coincidir con una de las acciones enumeradas en el filtro.
Si el filtro no enumera ninguna acción, no hay nada para un
para que coincida, por lo que todos los intents no pasan la prueba. Sin embargo, si un objeto Intent
no especifica una acción, pasa la prueba siempre que 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 cero o más.
Elementos <category>
, como se muestra en el siguiente ejemplo:
<intent-filter> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> ... </intent-filter>
Para que un intent pase la prueba de categoría, cada categoría en el Intent
debe coincidir con una categoría del filtro. No es necesario hacer lo contrario: el filtro de intents puede
declarar más categorías de las que se especifican en Intent
y
Intent
todavía pasa. Por lo tanto, un intent sin categorías
siempre pasa esta prueba, independientemente de las categorías declaradas en el filtro.
Nota:
Android aplica automáticamente la categoría CATEGORY_DEFAULT
a todos los intents implícitos que se pasan a startActivity()
y startActivityForResult()
.
Si quieres que tu actividad reciba intents implícitos, debe
incluir una categoría para "android.intent.category.DEFAULT"
en sus filtros de intents, como
como se muestra en el ejemplo anterior de <intent-filter>
.
Prueba de datos
Para especificar los datos de intents aceptados, un filtro de intents puede declarar cero o más.
Elementos <data>
, como se muestra en el siguiente ejemplo:
<intent-filter> <data android:mimeType="video/mpeg" android:scheme="http" ... /> <data android:mimeType="audio/mpeg" android:scheme="http" ... /> ... </intent-filter>
Cada <data>
puede especificar una estructura de URI y un tipo de datos (tipo de medio de MIME).
Cada parte del URI es un
atributos: scheme
, host
, port
,
y path
:
<scheme>://<host>:<port>/<path>
El siguiente ejemplo muestra valores posibles para estos atributos:
content://com.example.project:200/folder/subfolder/etc
En este URI, el esquema es content
, el host es com.example.project
el puerto es 200
y la ruta es folder/subfolder/etc
.
Cada uno de estos atributos es opcional en un elemento <data>
.
pero hay dependencias lineales:
- Si no se especifica el esquema, se ignora el host.
- Si el host no se especifica, se ignora el puerto.
- Si no se especifican el esquema ni el host, se ignora la ruta de acceso.
Cuando se compara el URI de un intent con una especificación de URI en un filtro, solo se compara con las partes del URI incluidas 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 sus rutas de acceso.
- Si un filtro especifica un esquema, una autoridad y una ruta, solo los URI con el mismo esquema autoridad y la ruta pasan el filtro.
Nota: Una especificación de ruta puede contienen un asterisco (*) comodín para requerir solo una coincidencia parcial del nombre de la ruta.
La prueba de datos compara tanto el URI como el tipo de MIME en el intent con un URI y el tipo de MIME especificado en el filtro. Las reglas son las siguientes:
- Una intent que no contiene ni un URI ni un tipo de MIME pasa la probar solo si el filtro no especifica ningún URI ni tipo de MIME.
- Una intent que contiene un URI, pero ningún tipo de MIME (ni explícito ni que se pueda inferir de la URI) pasa la prueba solo si su URI coincide con el formato de URI del filtro y el filtro tampoco especifica un tipo de MIME.
- Si 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.
- Una intent que contiene tanto un URI como un tipo de MIME (explícito o que se pueda inferir de la
URI) pasa la parte del tipo de MIME de la prueba solo si ese
coincide con un tipo que aparece en el filtro. Pasa la parte del URI de la prueba
ya sea si su URI coincide con un URI en el filtro o si tiene un
content:
ofile:
y el filtro no especifica un URI. Es decir, se presume que un componente admite datoscontent:
yfile:
si su filtro enumera solo un tipo de MIME.
Nota: Si un intent especifica un tipo de URI o MIME, la prueba de datos
fallarán si no hay elementos <data>
en <intent-filter>
.
Esta última regla, la regla (d), refleja la expectativa
para que los componentes obtengan datos locales de un archivo o proveedor de contenido.
Por lo tanto, sus filtros pueden enumerar solo un tipo de datos y no necesitan nombrar explícitamente los esquemas content:
y file:
.
En el siguiente ejemplo, se muestra un caso típico en el que un elemento <data>
le indica a Android que el componente puede obtener datos de imagen de un elemento
proveedor y los mostrará:
<intent-filter> <data android:mimeType="image/*" /> ... </intent-filter>
Filtros que especificar un tipo de datos, pero no un URI son tal vez los más comunes porque la mayoría son los proveedores de contenido.
Otra configuración común es aquella en la que los filtros tienen un esquema y un tipo de datos. Para
Por ejemplo, un objeto <data>
como el siguiente le 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:mimeType="video/*" /> ... </intent-filter>
Coincidencias de intents
Los intents se comparan
con los filtros de intents
pero también para descubrir algo sobre el conjunto de
componentes del dispositivo. Por ejemplo, la app de Home propaga el selector de aplicaciones
buscando todas las actividades con filtros de intents que especifiquen
ACTION_MAIN
acción y
Categoría CATEGORY_LAUNCHER
.
Una coincidencia solo es exitosa si las acciones y las categorías en el intent coinciden
con el filtro, como se describe en la documentación de IntentFilter
clase.
Tu aplicación puede usar la coincidencia de intents de forma similar a como lo hace la app de pantalla principal.
PackageManager
tiene un conjunto de query...()
métodos que devuelvan todos los componentes que pueden aceptar un intent específico y
una serie similar de métodos resolve...()
que determinan la mejor
para responder a un intent. Por ejemplo:
queryIntentActivities()
devuelve una lista de todas las actividades que se pueden realizar.
el intent que se pasa como argumento, y queryIntentServices()
muestra una lista similar de servicios.
Ninguno de los métodos activa los componentes; solo enumeran las que
pueden responder. Existe un método similar,
queryBroadcastReceivers()
, para receptores de emisión