Android proporciona dos maneras para que los usuarios compartan datos entre apps:
- Android Sharesheet está diseñado principalmente para enviar contenido fuera de tu app o directamente a otro usuario (por ejemplo, para compartir una URL con un amigo).
- El agente de resolución de intent de Android es más adecuado para pasar datos a la siguiente etapa de una tarea bien definida (por ejemplo, abrir un PDF desde tu app y permitir que los usuarios elijan su lector preferido).
Por qué usar Android Sharesheet
Usa Android Sharesheet para crear coherencia para tus usuarios en todas las apps. No muestres la lista de objetivos de uso compartido de tu app ni crees tus propias variaciones de Sharesheet.
Android Sharesheet permite que los usuarios compartan información con la persona adecuada, con sugerencias de apps relevantes, todo con un solo toque. Sharesheet puede sugerir objetivos que no están disponibles para las soluciones personalizadas y usa una clasificación coherente. Esto se debe a que Sharesheet puede tener en cuenta la información sobre la actividad de la app y del usuario que solo está disponible para el sistema.
Android Sharesheet también tiene diversas funciones útiles para desarrolladores. Por ejemplo, puedes hacer lo siguiente:
- Conocer cuándo los usuarios implementan el uso compartido y dónde
- Agregar segmentación personalizada y objetivos de la app
- Proporcionar vistas previas de contenido de texto enriquecido, a partir de Android 10 (nivel de API 29)
- Excluir objetivos que coincidan con nombres de componentes específicos
Cómo usar Android Sharesheet
Para todos los tipos de uso compartido, crea un intent y establece su acción en Intent.ACTION_SEND.
Para mostrar Android Sharesheet, llama a
Intent.createChooser(),
y pásale el objeto Intent.
Devuelve una versión de tu intent que siempre muestra Android Sharesheet.
Cómo enviar contenido de texto
El uso más sencillo y común de Android Sharesheet es enviar contenido de texto de una actividad a otra. Por ejemplo, la mayoría de los navegadores pueden compartir la URL de la página que se muestra actualmente como texto con otra app. Esto es útil para compartir un artículo o un sitio web con amigos por correo electrónico o redes sociales. En Jetpack Compose, recupera el contexto actual con LocalContext.current y llama a context.startActivity().
Este es un ejemplo de cómo hacerlo:
fun shareText(context: Context) { val sendIntent: Intent = Intent().apply { action = ACTION_SEND putExtra(Intent.EXTRA_TEXT, "This is my text to send.") type = "text/plain" } val shareIntent = Intent.createChooser(sendIntent, null) context.startActivity(shareIntent) }
De manera opcional, puedes agregar extras para incluir más información, como destinatarios de correo electrónico (EXTRA_EMAIL, EXTRA_CC, EXTRA_BCC) o el asunto del correo electrónico (EXTRA_SUBJECT).
Nota: Algunas apps de correo electrónico, como Gmail, esperan un String[] para extras como EXTRA_EMAIL y EXTRA_CC. Usa putExtra(String, String[]) para agregarlos a tu intent.
Cómo enviar contenido binario
Comparte los datos binarios con la acción ACTION_SEND.
Establece el tipo de MIME adecuado y coloca un URI en los datos del extra EXTRA_STREAM, como se muestra en el siguiente ejemplo.
Esto es de uso frecuente para compartir una imagen, pero se puede usar para compartir cualquier tipo de contenido binario.
fun shareBinaryContent(context: Context) { val shareIntent: Intent = Intent().apply { action = ACTION_SEND // Example: content://com.google.android.apps.photos.contentprovider/... val imageUri: Uri = Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1") putExtra(Intent.EXTRA_STREAM, imageUri) type = "image/jpeg" } context.startActivity(Intent.createChooser(shareIntent, null)) }
La aplicación receptora necesita permiso para acceder a los datos a los que apunta Uri. Existen dos maneras recomendadas de hacerlo:
- Almacena los datos en tu propio
ContentProvidery asegúrate de que otras apps tengan el permiso correcto para acceder a tu proveedor. El mecanismo preferido para proporcionar acceso es usar permisos por URI, que son temporales y solo otorgan acceso a la aplicación receptora. Para crear unContentProvidercomo este, usa la clase auxiliarFileProvider. - Usa el
MediaStoredel sistema.MediaStorees principalmente para tipos de MIME de video, audio e imagen. Sin embargo, a partir de Android 3.0 (nivel de API 11), también puede almacenar tipos que no sean multimedia. Para obtener más información, consultaMediaStore.Files. Los archivos se pueden insertar enMediaStoreconscanFile(), después de lo cual se pasa unUride estilocontent://adecuado para compartir a la devolución de llamadaonScanCompleted()proporcionada. Ten en cuenta que, una vez que se agrega alMediaStoredel sistema, se puede acceder al contenido desde cualquier app del dispositivo.
Cómo usar el tipo de MIME correcto
Proporciona el tipo de MIME más específico disponible para los datos que envías. Por ejemplo, usa text/plain cuando compartas texto sin formato. Estos son algunos tipos de MIME comunes cuando se envían datos en Android:
| Los receptores se registran para | Los remitentes envían |
|---|---|
text/* |
|
image/* |
|
video/* |
|
| Extensiones de archivo compatibles | application/pdf |
Para determinar el tipo de MIME de forma dinámica en el tiempo de ejecución en lugar de codificarlo, usa los siguientes métodos:
- Para los
content://URIs (como los que proporcionanFileProvideroMediaStore), llama aContentResolver.getType(). - Para las extensiones de archivo, llama a
MimeTypeMap.getSingleton().getMimeTypeFromExtension(). - Si usas Storage Access Framework, también puedes consultar
DocumentFile.getType().
Si no puedes determinar un tipo de MIME específico, usa application/octet-stream para datos binarios genéricos o */* como último recurso.
Para obtener más información sobre los tipos de MIME, consulta el registro oficial de IANA de tipos de medios MIME.
Android Sharesheet puede mostrar una vista previa del contenido, según el tipo de MIME proporcionado. Algunas funciones de versión preliminar solo están disponibles para tipos específicos.
Cómo compartir varios elementos de contenido
Para compartir varios elementos de contenido, usa la acción ACTION_SEND_MULTIPLE junto con una lista de URIs que apunten al contenido. El tipo de MIME varía según la combinación de contenido que compartas. Por ejemplo, si compartes tres imágenes JPEG, usas el tipo "image/jpg". Para una combinación de tipos de imágenes, usa "image/*" para que coincida con una actividad que controle cualquier tipo de imagen. Si bien es posible compartir una combinación de tipos, evita hacerlo, ya que no está claro para el receptor lo que se pretende enviar. Si es necesario enviar varios tipos, usa "*/*". Depende de la aplicación receptora analizar y procesar tus datos. Por ejemplo:
fun shareMultiple(context: Context) { val imageUris: ArrayList<Uri> = arrayListOf( Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1"), Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/2") ) val shareIntent = Intent().apply { action = Intent.ACTION_SEND_MULTIPLE putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris) type = "image/*" } context.startActivity(Intent.createChooser(shareIntent, null)) }
Asegúrate de que los objetos Uri proporcionados apunten a datos a los que pueda acceder una aplicación receptora.
Cómo agregar contenido enriquecido a las vistas previas de texto
A partir de Android 10 (nivel de API 29), Android Sharesheet muestra una vista previa del texto que se comparte. En algunos casos, el texto que se comparte puede ser difícil de comprender. Considera compartir una URL complicada como https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4. Una vista previa más enriquecida puede asegurar a tus usuarios lo que se comparte.
Si obtienes una vista previa del texto, puedes establecer un título, una imagen en miniatura o ambos. Agrega una descripción a Intent.EXTRA_TITLE antes de llamar a Intent.createChooser() y agrega una miniatura relevante con ClipData.
Nota: El URI de contenido de la imagen se proporciona desde un
FileProvider, por lo general, desde un <cache-path>.
Para obtener más información, consulta Cómo compartir archivos. Asegúrate de otorgar a Sharesheet los permisos correctos para leer cualquier imagen que quieras usar como miniatura. Para obtener más información, consulta Intent.FLAG_GRANT_READ_URI_PERMISSION.
Por ejemplo:
fun richContentToTextPreviewShares(context: Context) { val share = Intent.createChooser( Intent().apply { action = ACTION_SEND putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/") // (Optional) Here you're setting the title of the content putExtra(Intent.EXTRA_TITLE, "Introducing content previews") // (Optional) Here you're passing a content URI to an image to be displayed data = Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/A123456789") flags = Intent.FLAG_GRANT_READ_URI_PERMISSION }, null ) context.startActivity(share) }
La vista previa se ve de la siguiente manera:
Cómo agregar acciones personalizadas a la hoja compartida
En Android 14 (nivel de API 34) y versiones posteriores, las apps pueden agregar acciones personalizadas a Android Sharesheet.
Las acciones personalizadas se muestran como íconos de acción pequeños en la parte superior de Android Sharesheet, y las apps pueden especificar cualquier Intent como la acción que se invoca cuando se hace clic en el ícono.
Para agregar acciones personalizadas en Android Sharesheet, primero crea un
ChooserAction con ChooserAction.Builder.
Puedes especificar un PendingIntent como la acción que se invoca cuando se hace clic en el ícono. Crea un array que contenga todas tus acciones personalizadas y especifícalo como EXTRA_CHOOSER_CUSTOM_ACTIONS del Intent compartido.
fun sharesheetCustomActions(context: Context, previewText: String) { val sendIntent = Intent(ACTION_SEND) .setType("text/plain") .putExtra(Intent.EXTRA_TEXT, previewText) val shareIntent = Intent.createChooser(sendIntent, null) val customActions = arrayOf( ChooserAction.Builder( Icon.createWithResource(context, R.drawable.ic_logo), "Custom", PendingIntent.getBroadcast( context, 1, Intent(Intent.ACTION_VIEW), PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT ) ).build() ) shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions) context.startActivity(shareIntent) }
Cómo agregar objetivos personalizados
Android Sharesheet te permite especificar hasta dos intents de actividad personalizados que se muestran antes de las sugerencias de la app con Intent.EXTRA_INITIAL_INTENTS.
Para los objetivos de Direct Share (como conversaciones o contactos), publica accesos directos dinámicos con
ShortcutManagerCompat en su lugar
(consulta Cómo proporcionar objetivos de Direct Share):
Agrega Intent.EXTRA_INITIAL_INTENTS a tu intent compartido después de llamar a Intent.createChooser():
val sendIntent = Intent(ACTION_SEND).apply { type = "text/plain" putExtra(Intent.EXTRA_TEXT, previewText) } val customIntent = Intent().apply { component = ComponentName(context.packageName, "${context.packageName}.CustomActivity") } val shareIntent = Intent.createChooser(sendIntent, null).apply { putExtra( Intent.EXTRA_INITIAL_INTENTS, arrayOf(customIntent) ) } context.startActivity(shareIntent)
Usa esta función con cuidado. Cada Intent personalizado que agregues reduce la cantidad que sugiere el sistema. En general, evita agregar objetivos personalizados. Un ejemplo común y adecuado de agregar Intent.EXTRA_INITIAL_INTENTS es proporcionar acciones adicionales que los usuarios pueden realizar en el contenido compartido. Por ejemplo, un usuario comparte imágenes y se usa Intent.EXTRA_INITIAL_INTENTS para permitirle enviar un vínculo en su lugar.
Cómo excluir objetivos específicos por componente
Puedes excluir objetivos específicos proporcionando Intent.EXTRA_EXCLUDE_COMPONENTS.
Solo haz esto para quitar los objetivos sobre los que tienes control. Un caso de uso común es ocultar los objetivos de uso compartido de tu app cuando los usuarios comparten contenido desde tu app, ya que es probable que su intención sea compartir fuera de tu app.
Agrega Intent.EXTRA_EXCLUDE_COMPONENTS a tu intent después de llamar a Intent.createChooser():
fun excludeSpecificTargets(context: Context) { val share = Intent.createChooser(Intent(ACTION_SEND), null).apply { // Only use for components you have control over val excludedComponentNames = arrayOf(ComponentName("com.example.android", "ExampleClass")) putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames) } context.startActivity(share) }
Cómo obtener información sobre el uso compartido
Puede ser útil saber cuándo comparten tus usuarios y qué objetivo seleccionan. Android Sharesheet te permite obtener esta información proporcionando el ComponentName de los objetivos que seleccionan tus usuarios con un IntentSender.
Primero, crea un PendingIntent para un BroadcastReceiver y proporciona su IntentSender en Intent.createChooser():
fun infoAboutSharing(context: Context, requestCode: Int) { var share = Intent(ACTION_SEND) // ... val pi = PendingIntent.getBroadcast( context, requestCode, Intent(context, ShareBroadcastReceiver::class.java), PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) share = Intent.createChooser(share, null, pi.intentSender) context.startActivity(share) }
Recibe la devolución de llamada en MyBroadcastReceiver y busca en Intent.EXTRA_CHOOSER_RESULT:
override fun onReceive(context: Context?, intent: Intent) { val TAG = ShareBroadcastReceiver::class.simpleName val chooserResult: ChooserResult? = IntentCompat.getParcelableExtra( intent, Intent.EXTRA_CHOOSER_RESULT, ChooserResult::class.java, ) chooserResult?.let { Log.i(TAG, "Share callback: isShortcut: ${it.isShortcut}, type: ${typeToString(it.type)}, componentName: ${it.selectedComponent}", ) } ?: Log.i(TAG, "chooserResult is null") }
Para obtener más información, consulta la muestra de uso compartido de la plataforma.
Cómo usar el agente de resolución de intent de Android
ACTION_SENDEl agente de resolución de intent de Android se usa mejor cuando se envían datos a otra app como parte de un flujo de tareas bien definido.
Para usar el agente de resolución de intent de Android, crea un intent y agrega extras como lo harías para llamar a Android Sharesheet. Sin embargo, no llames a
Intent.createChooser().
Si hay varias aplicaciones instaladas con filtros que coinciden con ACTION_SEND y el tipo de MIME, el sistema muestra un diálogo de desambiguación llamado agente de resolución de intent que permite al usuario elegir un objetivo para compartir. Si coincide una sola aplicación, se ejecuta.
Este es un ejemplo de cómo usar el agente de resolución de intent de Android para enviar texto:
fun intentResolver(context: Context) { val sendIntent: Intent = Intent().apply { action = ACTION_SEND putExtra(Intent.EXTRA_TEXT, "This is my text to send.") type = "text/plain" } context.startActivity(sendIntent) }
Más información
Para obtener más información sobre el envío de datos, consulta Intents y filtros de intents.