Así como una app puede enviar datos a otras apps, también puede recibirlos de ellas. Piensa en la manera en que los usuarios interactúan con tu aplicación y qué tipos de datos quieres recibir de otras. Por ejemplo, una aplicación de red social podría estar interesada en recibir de otra app contenido de texto, como una URL web interesante.
Los usuarios suelen enviar datos a tu app mediante Android Sharesheet o el agente de resolución de intent. La app que proporciona los datos recibidos establece su tipo de MIME. Tu app puede recibir datos enviados por otra app de las siguientes tres maneras:
- Un elemento
Activity
con una etiquetaintent-filter
correspondiente en el manifiesto - Uno o más objetos
ChooserTarget
mostrados por tuChooserTargetService
- Accesos directos de uso compartido publicados por tu app, que reemplazan a los objetos
ChooserTarget
(los accesos directos de uso compartido solo están disponibles si tu app ejecuta Android 10, API nivel 29)
Los accesos directos de uso compartido y los objetos ChooserTarget
son vínculos directos de Direct Share en un elemento Activity
específico dentro de tu aplicación. Suelen representar a una persona, y Android Sharesheet los muestra.
Por ejemplo, una aplicación de mensajería puede proporcionar a una persona un acceso directo de uso compartido que contenga un vínculo directo a una conversación con esa persona.
Compatibilidad con tipos de MIME
Tu app debería poder recibir la mayor variedad de tipos de MIME posible. Por ejemplo, una app de mensajería que se usa para enviar texto, imágenes y video debería poder recibir text/*
, image/*
y video/*
. A continuación, puedes ver algunos tipos de MIME comunes que se usan al enviar datos simples en Android.
text/*
: los remitentes suelen enviartext/plain
,text/rtf
,text/html
ytext/json
image/*
: los remitentes suelen enviarimage/jpg
,image/png
yimage/gif
video/*
: los remitentes suelen enviarvideo/mp4
yvideo/3gp
- Los receptores deberían registrarse para extensiones de archivos compatibles; los remitentes suelen enviar
application/pdf
Consulta el registro oficial de la IANA de los tipos de medios MIME. Puedes recibir un tipo de MIME de */*
. Sin embargo, no es recomendable, a menos que puedas manejar correctamente cualquier tipo de contenido entrante.
Cómo crear grandes objetivos de uso compartido
Cuando un usuario presiona un objetivo de uso compartido asociado con una actividad específica, debería poder confirmar y editar el contenido compartido antes de usarlo. Esto resulta particularmente importante para datos de texto.
Si presiona en cualquier objetivo de Direct Share, el usuario debería ir directamente a una interfaz en la que se pueda realizar una acción directamente en el asunto del objetivo. Evita mostrar a los usuarios una desambiguación o colocarlos en una interfaz que no está relacionada con el objetivo presionado. En particular, no lleves al usuario a una interfaz de desambiguación de contactos en la que deba confirmar o volver a seleccionar el contacto con quien quiere compartir contenido, ya que ya lo hizo cuando presionó el objetivo en Android Sharesheet. Por ejemplo, en una app de mensajería, presionar un objetivo de Direct Share llevaría al usuario a una vista de conversación con la persona seleccionada. El teclado debería ser visible y el mensaje debería autocompletarse con los datos compartidos.
Cómo recibir datos con una actividad
Actualiza tu manifiesto
Los filtros de intents informan al sistema qué intents está dispuesto a aceptar un componente de la aplicación.
Así como construiste un intent con una acción ACTION_SEND
en la lección Cómo enviar datos simples a otras apps, puedes crear filtros de intents para poder recibir intents con esta acción. Se define el filtro de intents en tu manifiesto con el elemento <intent-filter>
. Por ejemplo, si tu aplicación puede recibir contenido de texto, una sola imagen de cualquier tipo o varias imágenes de cualquier tipo, tu manifiesto se vería de la siguiente manera:
<activity android:name=".ui.MyActivity" > <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 aplicación intente compartir cualquiera de estos elementos construyendo un intent y pasándolo a startActivity()
, tu aplicación aparecerá como opción en Android Sharesheet o el agente de resolución de intents. Si el usuario selecciona tu aplicación, se iniciará la actividad correspondiente (.ui.MyActivity
en el ejemplo anterior). Luego, deberás manejar correctamente el contenido dentro de tu IU y tu código.
Nota: Para obtener más información sobre los filtros y la resolución de intents, lee Intents y filtros de intents.
Cómo administrar el contenido entrante
A fin de controlar el contenido publicado por un Intent
, llama a getIntent()
para obtener el objeto Intent
. Cuando lo tengas, podrás examinar su contenido a fin de determinar qué hacer luego. Ten en cuenta que, si esta actividad puede iniciarse desde otras partes del sistema, como el selector, tendrás que tenerlo presente cuando examines el intent.
Presta especial atención a revisar los datos entrantes, ya que nunca se sabe qué podría enviarte otra aplicación. Por ejemplo, podría estar configurado el tipo de MIME incorrecto o la imagen enviada podría ser extremadamente grande. También recuerda procesar los datos binarios en un subproceso independiente en lugar de en el subproceso principal ("IU").
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... when { intent?.action == Intent.ACTION_SEND -> { if ("text/plain" == intent.type) { handleSendText(intent) // Handle text being sent } else if (intent.type?.startsWith("image/") == true) { handleSendImage(intent) // Handle single image being sent } } intent?.action == Intent.ACTION_SEND_MULTIPLE && 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 to reflect text being shared } } private fun handleSendImage(intent: Intent) { (intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let { // Update UI to reflect image being shared } } private fun handleSendMultipleImages(intent: Intent) { intent.getParcelableArrayListExtra<Parcelable>(Intent.EXTRA_STREAM)?.let { // Update UI to reflect multiple images being shared } }
Java
void onCreate (Bundle savedInstanceState) { ... // Get intent, action and MIME type Intent intent = getIntent(); String action = intent.getAction(); String type = intent.getType(); if (Intent.ACTION_SEND.equals(action) && type != null) { if ("text/plain".equals(type)) { handleSendText(intent); // Handle text being sent } else if (type.startsWith("image/")) { handleSendImage(intent); // Handle single image being sent } } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) { if (type.startsWith("image/")) { handleSendMultipleImages(intent); // Handle multiple images being sent } } else { // Handle other intents, such as being started from the home screen } ... } void handleSendText(Intent intent) { String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); if (sharedText != null) { // Update UI to reflect text being shared } } void handleSendImage(Intent intent) { Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); if (imageUri != null) { // Update UI to reflect image being shared } } void handleSendMultipleImages(Intent intent) { ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); if (imageUris != null) { // Update UI to reflect multiple images being shared } }
La actualización de la IU después de recibir los datos puede ser tan simple como completar un elemento EditText
o puede resultar más complicada, como cuando se aplica un filtro de foto interesante a una imagen. Tú decides qué sucede luego.
Cómo asegurarte de que los usuarios reconozcan tu app
Tu app aparece representada con el ícono y la etiqueta en Android Sharesheet y en el agente de resolución de intents. Ambos se definen en el manifiesto. Puedes establecer etiquetas de filtros de intent o actividad para brindar más contexto.
A partir de Android 10 (API nivel 29), Android Sharesheet solo usará íconos configurados en el manifiesto en tu etiqueta application
y se ignorarán los configurados en las etiquetas intent-filter
y activity
.
Nota: Los mejores objetivos de uso compartido no necesitan una etiqueta y un ícono en la actividad o el filtro de intents asociados. El nombre de la app receptora y el ícono bastan para que los usuarios entiendan lo que sucederá después de iniciar el uso compartido.
Cómo proporcionar objetivos de Direct Share
Direct Share se incorporó a Android 6.0 (API nivel 23) y permitía a las apps proporcionar objetos ChooserTarget
mediante un objeto ChooserTargetService
. Los resultados se recuperaban de manera reactiva a pedido, lo que hacía que los objetivos se cargaran lentamente.
En Android 10 (API nivel 29), las API ChooserTargetService
de Direct Share se reemplazaron por la nueva API de accesos directos de uso compartido. En lugar de obtener resultados de manera reactiva a pedido, esta API permite que las apps publiquen con anticipación objetivos directos de uso compartido.
El mecanismo ChooserTargetService
de Direct Share seguirá funcionando, pero los objetivos proporcionados de esta manera podrían tener una prioridad inferior a los que usen la API de accesos directos de uso compartido.
ShortcutManagerCompat es una API de AndroidX que proporciona accesos directos de uso compartido que son retrocompatibles con la antigua API ChooserTargetService
de Direct Share. Esta es la manera preferida de publicar accesos directos de uso compartido y ChooserTargets
. Consulta las instrucciones que se muestran a continuación.
Cómo publicar objetivos de Direct Share
Solo puedes usar accesos directos dinámicos para publicar objetivos de Direct Share. Sigue estos pasos para publicar objetivos de Direct Share con la nueva API:
- Declara los elementos de los objetivos de uso compartido en el archivo XML de recursos de la app. Para obtener más información, consulta la sección Cómo declarar un objetivo de uso compartido a continuación.
- Publica accesos directos dinámicos cuyas categorías coincidan con los objetivos de uso compartido declarados. Con ShortcutManager o ShortcutManagerCompat en AndroidX, es posible agregar accesos directos, actualizarlos, quitarlos y acceder a ellos. El método preferido consiste en usar una biblioteca de compatibilidad en AndroidX, ya que proporciona retrocompatibilidad con versiones anteriores de Android.
API de accesos directos de uso compartido
ShortcutInfo.Builder
incluye métodos nuevos y mejorados que proporcionan información adicional sobre el objetivo de uso compartido:
setCategories()
- Este no es un método nuevo; sin embargo, ahora también se usan las categorías para filtrar los accesos directos que pueden administrar intents o acciones de uso compartido. Para obtener más información, consulta Cómo declarar un objetivo de uso compartido a continuación. Este campo es obligatorio para los accesos directos que se deben usar como objetivos de uso compartido.
setLongLived()
-
Especifica si un acceso directo es válido o no cuando la app anula su publicación o lo oculta (ya sea un acceso directo dinámico o fijo). Si un acceso directo es permanente, se puede almacenar en la caché de diversos servicios del sistema, incluso en el caso de que se anule su publicación como acceso directo dinámico.
Hacer que un acceso directo sea permanente puede mejorar su clasificación. Para obtener más información, consulta Cómo obtener la mejor clasificación.
setPerson()
,setPersons()
-
Asocia uno o más objetos
Person
con el acceso directo. Se puede usar para comprender mejor el comportamiento del usuario en diferentes apps y ayudar a los servicios de predicción potenciales del marco de trabajo a brindar mejores sugerencias en ShareSheet. Agregar información de Person a un acceso directo es algo opcional, pero lo recomendamos si el objetivo de uso compartido puede asociarse a un usuario. Ten en cuenta que algunos objetivos de uso compartido, como la nube, no se pueden asociar a una persona.Incluir un objeto
Person
específico con una clave única en un objetivo de uso compartido y en notificaciones relacionadas puede mejorar su clasificación. Para obtener más información, consulta Cómo obtener la mejor clasificación.En el caso de una app de mensajería típica, se debería publicar un acceso directo de uso compartido separado para cada contacto, y el campo
Person
debería contener la información del contacto. Si el objetivo se puede asociar con varias personas (como un chat en grupo), agrega varios objetosPerson
a un único objetivo de uso compartido.Cuando publiques un acceso directo para una persona en particular, incluye su nombre completo en
setLongLabel()
y cualquier nombre corto, como un sobrenombre o un nombre de pila ensetShortLabel()
.
En código de muestra de accesos directos de uso compartido puedes ver un ejemplo de cómo publicarlos.
Cómo obtener la mejor clasificación
Android Sharesheet muestra una cantidad fija de objetivos de Direct Share. Estas sugerencias están ordenadas según su clasificación. Puedes hacer lo siguiente para mejorar potencialmente la clasificación de tus accesos directos:
- Asegúrate de que todos los shortcutIds sean únicos y que nunca se reutilicen para diferentes objetivos.
- Asegúrate de que el acceso directo sea permanente. Para ello, llama a
setLongLived(true)
. - Proporciona una clasificación que pueda usarse para comparar accesos directos de tu app en caso de que no haya datos de preparación. Consulta
setRank()
. Una clasificación más baja significa que el acceso directo es más importante.
Para mejorar aún más la clasificación, recomendamos que las aplicaciones sociales lleven a cabo todo lo mencionado anteriormente y lo siguiente:
- Proporciona objetos
Person
relevantes con una clave configurada en el acceso directo; consultasetPerson()
,setPersons()
ysetKey()
. - Vincula tu acceso directo con notificaciones relevantes de la misma persona o el mismo grupo de personas; consulta
setShortcutId().
. El shortcutId puede ser de cualquier acceso directo publicado anteriormente consetLongLived(true)
.
Para obtener la clasificación máxima, las aplicaciones sociales pueden hacer todo lo mencionado arriba y lo siguiente:
- En los objetos
Person
proporcionados, brinda un URI válido a un contacto asociado en el dispositivo; consultasetUri()
.
A continuación, puedes ver un acceso directo de ejemplo con potenciales mejoras de clasificación.
Kotlin
val person = Person.Builder() ... .setName(fullName) .setKey(staticPersonIdentifier) .setUri("tel:$phoneNumber") // alternatively "mailto:$email" or CONTENT_LOOKUP_URI .build() val shortcutInfo = ShortcutInfoCompat.Builder(myContext, staticPersonIdentifier) ... .setShortLabel(firstName) .setLongLabel(fullName) .setPerson(person) .setLongLived(true) .setRank(personRank) .build()
Java
Person person = Person.Builder() ... .setName(fullName) .setKey(staticPersonIdentifier) .setUri("tel:"+phoneNumber) // alternatively "mailto:"+email or CONTENT_LOOKUP_URI .build(); ShortcutInfoCompat shortcutInfo = ShortcutInfoCompat.Builder(myContext, staticPersonIdentifier) ... .setShortLabel(firstName) .setLongLabel(fullName) .setPerson(person) .setLongLived(true) .setRank(personRank) .build();
Kotlin
val notif = NotificationCompat.Builder(myContext, channelId) ... .setShortcutId(staticPersonIdentifier) .build()
Java
Notification notif = NotificationCompat.Builder(myContext, channelId) ... .setShortcutId(staticPersonIdentifier) .build();
Cómo proporcionar imágenes para accesos directos
Para crear un acceso directo de uso compartido, tendrás que agregar una imagen mediante setIcon()
.
El acceso directo de uso compartido puede aparecer en varias superficies del sistema y se puede modificar. Para asegurarte de que tu acceso directo se vea como corresponde, proporciona un mapa de bits adaptable mediante IconCompat.createWithAdaptiveBitmap()
.
Los mapas de bits adaptables deberían seguir las mismas pautas y dimensiones configuradas para íconos adaptables. La forma más común de lograrlo es ajustar el mapa de bits cuadrado pretendido a 72 x 72 dp y centrarlo dentro de un recuadro transparente de 108 x 108 dp.
No proporciones imágenes enmascaradas en una forma específica. Por ejemplo, en Android 10 (API nivel 29), era común proporcionar avatares de usuarios para objetos ChooserTarget
de Direct Share que estaban enmascarados en un círculo. Android Sharesheet y otras superficies del sistema de Android 10 ahora ofrecen formas y temas para las imágenes de accesos directos. El método preferido para proporcionar accesos directos de uso compartido, mediante ShortcutManagerCompat, dará forma automáticamente a fin de brindar retrocompatibilidad con objetos ChooserTarget
de Direct Share para círculos.
Cómo declarar un objetivo de uso compartido
Los objetivos de uso compartido deben declararse en el archivo de recursos de la app, de manera similar a las definiciones de accesos directos estáticos.
Agrega definiciones de objetivos de uso compartido dentro del elemento raíz <shortcuts>
en el archivo de recursos, junto con otras definiciones de accesos directos estáticos. Cada elemento <share-targets>
contiene información sobre el tipo de datos compartidos, las categorías que coinciden y la clase de objetivo que manejará el intent compartido.
El código XML se verá así:
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android"> <share-target android:targetClass="com.example.android.sharingshortcuts.SendMessageActivity"> <data android:mimeType="text/plain" /> <category android:name="com.example.android.sharingshortcuts.category.TEXT_SHARE_TARGET" /> </share-target> </shortcuts>
El elemento de datos en un objetivo de uso compartido es similar al de la especificación de datos en un filtro de intents. Cada objetivo de uso compartido puede tener varias categorías, que solo se usan para hacer coincidir los accesos directos publicados de una app con sus definiciones de objetivo de uso compartido. Las categorías pueden tener valores aleatorios definidos por las apps.
Si el usuario selecciona un acceso directo de uso compartido en Android Sharesheet que coincide con el objetivo del ejemplo anterior, la app obtendrá el siguiente intent de uso compartido:
Action: Intent.ACTION_SEND ComponentName: {com.example.android.sharingshortcuts / com.example.android.sharingshortcuts.SendMessageActivity} Data: Uri to the shared content EXTRA_SHORTCUT_ID: <ID of the selected shortcut>
Si el usuario abre el objetivo de uso compartido desde los accesos directos del selector, la app obtendrá el intent que se haya creado al agregar el acceso directo de uso compartido a ShortcutManagerCompat.
Como es un intent diferente, Intent.EXTRA_SHORTCUT_ID
no estará disponible, por lo que tendrás que pasar el ID manualmente si lo necesitas.
Cómo usar AndroidX para proporcionar accesos directos de uso compartido y ChooserTargets
Para poder trabajar con la biblioteca de compatibilidad de AndroidX, el manifiesto de la app debe contener el conjunto meta-data + chooser-target-service + intent-filters.
Obtén información sobre la API ChooserTargetService
de Direct Share.
Este servicio ya está declarado en la biblioteca de compatibilidad, por lo que no es necesario que el usuario lo declare en el manifiesto de la app. Sin embargo, se debe tomar el vínculo de actividad de uso compartido con el servicio como proveedor para el selector de objetivos.
En el siguiente ejemplo, la implementación de ChooserTargetService
es androidx.core.content.pm.ChooserTargetServiceCompat
y ya está definida en AndroidX:
<activity android:name=".SendMessageActivity" android:label="@string/app_name" android:theme="@style/SharingShortcutsDialogTheme"> <!-- This activity can respond to Intents of type SEND --> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> <!-- Only needed if you import the sharetarget AndroidX library that provides backwards compatibility with the old DirectShare API. The activity that receives the Sharing Shortcut intent needs to be taken into account with this chooser target provider. --> <meta-data android:name="android.service.chooser.chooser_target_service" android:value="androidx.sharetarget.ChooserTargetServiceCompat" /> </activity>
Preguntas frecuentes sobre accesos directos de uso compartido
¿Cuáles son las principales diferencias entre la API de accesos directos de uso compartido actual y la antigua API de ChooserTargetService
de Direct Share?
La API de accesos directos de uso compartido utiliza un modelo push, en comparación con el modelo pull que se usaba en la antigua API de Direct Share. De esta manera, el proceso de recuperar objetivos de Direct Share es mucho más rápido cuando se prepara Sharesheet. Desde el punto de vista del desarrollador de la app, al usar la nueva API, la app debe proporcionar la lista de objetivos de uso compartido directo con anticipación y, potencialmente, actualizar la lista de accesos directos cada vez que cambie su estado interno (por ejemplo, si se agrega un nuevo contacto en una app de mensajería).
¿Qué sucede si no realizo la migración para usar las API de accesos directos de uso compartido?
En Android 10 (API nivel 29) y versiones posteriores, Android Sharesheet proporcionará mayor prioridad a los objetivos de uso compartido que se proporcionan mediante ShortcutManager con la API de accesos directos de uso compartido. Por lo tanto, los objetivos de uso compartido publicados podrían quedar ocultos por los de otras apps y quizás nunca aparezcan durante el uso compartido.
¿Puedo usar las API de ChooserTargetService
y de accesos directos de uso compartido en mi app para brindar retrocompatibilidad?
No lo hagas. En su lugar, usa las API que se proporcionan en la biblioteca de asistencia ShortcutManagerCompat
.
Si combinas ambos conjuntos de API, es posible que notes comportamientos inesperados o no deseados durante la obtención de objetivos de uso compartido.
¿En qué se diferencian los accesos directos publicados para objetivos de uso compartido de los accesos directos de selector (el típico uso de accesos directos por el cual se mantienen presionados los íconos de las apps en el selector)?
Los accesos directos que se publiquen para un "objetivo de uso compartido" también serán accesos directos del selector y se mostrarán en el menú cuando se mantenga presionado el ícono de tu app. El límite máximo de accesos directos por actividad también se aplica a la cantidad total de accesos directos que publica una app (incluye objetivos de uso compartido y accesos directos de selector heredados).