Así como una app puede enviar datos a otras apps, también puede recibirlos de otras apps. Piensa en cómo interactúan los usuarios con tu aplicación y qué tipos de datos quieres recibir de otras aplicaciones. Por ejemplo, una aplicación de redes sociales podría estar interesada en recibir contenido de texto, como una URL web interesante, de otra app.
En una app que usa Compose Navigation, recibir datos enviados por otra app es un proceso de tres pasos:
Declara un
<intent-filter>en el manifiesto: Debes agregar un filtro de intents a tu actividad en el archivoAndroidManifest.xml. Esto le indica al SO Android que tu aplicación puede recibir acciones específicas (comoACTION_SEND) y tipos de MIME (comotext/plain).Define un
navDeepLinken tu gráfico de Compose Navigation: Adjunta unnavDeepLinkque coincida con la acción y el tipo de MIME directamente al destino componible que debería mostrar el contenido. ElNavControllerintercepta automáticamente el intent entrante y dirige al usuario directamente a esa pantalla.Extrae la carga útil de datos entrantes: En la pantalla de destino, accede a los extras del intent (como
EXTRA_TEXToEXTRA_STREAM) para recuperar el contenido compartido y actualizar el estado de la IU.
Los destinos de Direct Share son vínculos directos a una actividad específica dentro de tu app. Suelen representar a una persona o un grupo, y la hoja de Android Sharesheet los muestra. Por ejemplo, una app de mensajería puede proporcionar un destino de Uso compartido directo para una persona que incluya un vínculo directo a una conversación con esa persona. Consulta Cómo proporcionar objetivos de Direct Share para obtener instrucciones detalladas.
Tipos de MIME admitidos
Idealmente, una app debe poder recibir la mayor variedad posible de tipos de MIME.
Por ejemplo, una app de mensajería diseñada para enviar texto, imágenes y video debería admitir la recepción de text/*, image/* y video/*. Estos son algunos tipos de MIME comunes para enviar y recibir datos en Android.
| Los receptores se registran para | Los remitentes envían |
|---|---|
text/* |
|
image/* |
|
video/* |
|
| Extensiones de archivo compatibles | application/pdf |
Consulta el registro oficial de la IANA de los tipos de medios MIME.
Crea objetivos de uso compartido excelentes
Cuando los usuarios presionen un destino de uso compartido asociado a una actividad específica, permíteles confirmar y editar el contenido compartido antes de que tu app lo use. Esto es especialmente importante para los datos de texto.
Recibe datos en tu app
Para recibir datos compartidos en una app que usa Compose, debes declarar filtros de intents en tu manifiesto, enrutar los intents entrantes a la pantalla adecuada con vínculos directos y extraer la carga útil del intent para actualizar tu IU.
Actualiza tu manifiesto
Los filtros de intents informan al sistema qué intents acepta un componente de la app. De manera similar a como construiste un intent con una acción ACTION_SEND en la lección Cómo enviar datos a otras apps, creas filtros de intents para recibir intents con esta acción. Para definir un filtro de intents en tu manifiesto, usa el elemento <intent-filter>. Por ejemplo, si tu app controla la recepción de contenido de texto, un manifiesto que incluya una o más imágenes de cualquier tipo se vería como el siguiente fragmento:
<activity android:name=".ui.MyActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
Cuando otra app intenta compartir cualquiera de estos elementos creando un intent y pasándolo a startActivity(), tu aplicación aparece como una opción en el Android Sharesheet o en el agente de resolución de intents. Si el usuario selecciona tu app, se inicia la actividad correspondiente (.ui.MyActivity en el ejemplo anterior). Luego, depende de ti controlar el contenido de forma adecuada en tu código y tu IU.
Define un vínculo directo en tu gráfico de navegación
En Compose Navigation, adjunta un navDeepLink directamente al destino componible que debería mostrar el contenido. Cuando otra app comparte datos que coinciden con tu filtro de intents, Compose Navigation dirige al usuario directamente a este destino:
composable( route = "incoming_share", deepLinks = listOf( navDeepLink { action = Intent.ACTION_SEND mimeType = "text/plain" }, navDeepLink { action = Intent.ACTION_SEND mimeType = "image/*" }, navDeepLink { action = Intent.ACTION_SEND_MULTIPLE mimeType = "image/*" } ) ) { SharesheetHandler() }
El navDeepLink coincide con la acción y el tipo de MIME del intent entrante para navegar a la pantalla de destino correcta. Una vez en ese destino, tu controlador inspecciona el intent para determinar qué carga útil se recibió (como una sola imagen en comparación con varias imágenes) y extrae los extras correspondientes.
Cómo administrar el contenido entrante
Para recuperar el contenido que entrega un Intent, lee la actividad actual de LocalActivity.current dentro de tu elemento componible y, luego, examina el intent para determinar qué hacer a continuación. Si esta actividad se puede iniciar desde otras partes del sistema (como el selector), tenlo en cuenta cuando examines el intent.
Ten mucho cuidado cuando verifiques los datos entrantes: es posible que se haya establecido un tipo de MIME incorrecto o que se esté enviando una imagen demasiado grande. Procesa datos binarios o realiza operaciones de E/S pesadas (como decodificar imágenes grandes o escribir archivos) de forma asíncrona con corrutinas (como Dispatchers.IO) en lugar de hacerlo en el subproceso de IU principal.
@Composable fun SharesheetHandler() { val activity = LocalActivity.current val intent = activity?.intent when (intent?.action) { Intent.ACTION_SEND -> { if (intent.type == "text/plain") { handleSendText(intent) // Handle text being sent } else if (intent.type?.startsWith("image/") == true) { handleSendImage(intent) // Handle single image being sent } } Intent.ACTION_SEND_MULTIPLE -> { if (intent.type?.startsWith("image/") == true) { handleSendMultipleImages(intent) // Handle multiple images being sent } } else -> { // Handle other intents, such as being started from the home screen } } } private fun handleSendText(intent: Intent) { intent.getStringExtra(Intent.EXTRA_TEXT)?.let { // Update UI state with the shared text } } private fun handleSendImage(intent: Intent) { val imageUri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java) imageUri?.let { // Update UI state with the shared image } } private fun handleSendMultipleImages(intent: Intent) { val imageUris = IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java) imageUris?.let { // Update UI state with the shared images } }
Cuando extraigas datos binarios o URIs de intents adicionales (como EXTRA_STREAM), usa IntentCompat.getParcelableExtra() o IntentCompat.getParcelableArrayListExtra() de la biblioteca principal de AndroidX, como se muestra en las funciones handleSendImage y handleSendMultipleImages anteriores. En Android 13 (nivel de API 33), el método Intent.getParcelableExtra(String) sin parámetros se reemplaza por métodos con seguridad de tipos que toman el tipo de clase esperado.
Actualizar la IU después de recibir los datos puede ser tan sencillo como actualizar el estado para propagar un TextField o tan complejo como aplicar un filtro a una imagen. Lo que suceda después dependerá de tu app.
Uso compartido de URLs de capturas de pantalla
Cuando tomas una captura de pantalla, puedes compartirla junto con cualquier URL asociada.
Esto proporciona una experiencia del usuario más enriquecedora. Cuando recibas una URL, asegúrate de obtener el campo EXTRA_TEXT del intent, como se muestra en el siguiente ejemplo:
IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let { // Handle the EXTRA_TEXT as well val extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT) // Update UI state with the shared image and the EXTRA_TEXT if available }
Cómo asegurarte de que los usuarios reconozcan tu app
Tu app se representa con su ícono y su etiqueta en Android Sharesheet y el agente de resolución de intents. Ambos se definen en el manifiesto. Puedes establecer etiquetas de filtro de intents o de actividades para proporcionar más contexto.
A partir de Android 10 (nivel de API 29), Android Sharesheet solo usa los íconos establecidos en el manifiesto en la etiqueta application. Android ignora los íconos establecidos en las etiquetas intent-filter y activity.
Cómo recibir contenido enriquecido
Si bien los intents ACTION_SEND permiten recibir datos del Android Sharesheet y el agente de resolución de intents a nivel de la actividad o la navegación, las apps también pueden recibir contenido enriquecido (como imágenes, videos, archivos de audio y texto con diseño) a través de interacciones directas con la IU. Estos mecanismos incluyen los siguientes:
- Pegar contenido desde el portapapeles (menú de mantener presionado)
- Insertar contenido multimedia directamente desde el teclado en pantalla (IME), como calcomanías o GIFs
- Arrastrar y soltar contenido de otra app en el modo multiventana o de pantalla dividida
En las IU basadas en objetos View, Android 12 (nivel de API 31) y AndroidX Core 1.7 presentan la API unificada de OnReceiveContentListener. Este objeto de escucha consolida el control de contenido del portapapeles, el teclado y la función de arrastrar y soltar en una sola devolución de llamada. Para obtener instrucciones detalladas sobre cómo implementar esto en las vistas, consulta Cómo recibir contenido enriquecido.
En Jetpack Compose, puedes controlar la recepción de contenido enriquecido insertado en componentes de la IU (como campos de texto) con el modificador Modifier.contentReceiver o los modificadores de arrastrar y soltar.