Android ofrece dos formas para que los usuarios compartan datos entre apps:
- La Android Sharesheet está diseñada 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 intents 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 el 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 la hoja de uso compartido.
La Android Sharesheet permite que los usuarios compartan información con la persona adecuada, con sugerencias de apps pertinentes, todo con un solo toque. La Sharesheet puede sugerir objetivos que no están disponibles para las soluciones personalizadas y usa un ranking coherente. Esto se debe a que la hoja de compartir puede tener en cuenta 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
- Agrega segmentaciones personalizadas y de apps
- Proporciona vistas previas de contenido de texto enriquecido, a partir de Android 10 (nivel de API 29)
- Excluye los destinos que coincidan con nombres de componentes específicos
Usa la hoja de contenido compartido de Android
Para todos los tipos de uso compartido, crea un intent y establece su acción en Intent.ACTION_SEND.
Para mostrar el Android Sharesheet, llama a Intent.createChooser() y pásale tu objeto Intent.
Devuelve una versión de tu intent que siempre muestra el Android Sharesheet.
Envía contenido de texto
El uso más directo y común de Android Sharesheet es enviar contenido de texto de una Activity 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 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 los destinatarios del 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.
Envía contenido binario
Comparte los datos binarios con la acción ACTION_SEND.
Establece el tipo de MIME adecuado y coloca un URI para los datos en el elemento adicional 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 el 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 un objetoContentProvidercomo este, usa la clase auxiliarFileProvider. - Usa la clase
MediaStoredel sistema. ElMediaStorees principalmente para tipos de MIME de video, audio y de imagen. Sin embargo, a partir de Android 3.0 (nivel de API 11), también puede almacenar tipos que no sean de contenido 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 al sistemaMediaStore, cualquier app del dispositivo puede acceder al contenido.
Usa 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. A continuación, se indican algunos tipos de MIME comunes para enviar 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 entorno de ejecución en lugar de codificarlo de forma fija, usa los siguientes métodos:
- Para los URI de
content://(como los que proporcionanFileProvideroMediaStore), llama aContentResolver.getType(). - Para las extensiones de archivo, llama a
MimeTypeMap.getSingleton().getMimeTypeFromExtension(). - Si usas el framework de acceso al almacenamiento, 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 la IANA de los tipos de medios MIME.
La 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, usa 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 queda claro para el receptor qué se pretende enviar. Si es necesario enviar varios tipos, usa "*/*". La aplicación receptora debe 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.
Agrega 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 darles a los usuarios la seguridad de 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 del contenido de la imagen se proporciona desde un
FileProvider, por lo general, desde un <cache-path> configurado.
Para obtener más información, consulta Cómo compartir archivos. Asegúrate de otorgarle a Sharesheet los permisos adecuados 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 verá de la siguiente manera:
Agrega acciones personalizadas a la hoja de contenido compartido
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 pequeños íconos de acción en la parte superior del 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 objeto 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 de uso 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) }
Agrega objetivos personalizados
El Android Sharesheet te permite especificar hasta dos intents de actividad personalizados que se enumeran antes de las sugerencias de apps con Intent.EXTRA_INITIAL_INTENTS.
Para los destinos de Direct Share (como conversaciones o contactos), publica accesos directos dinámicos con ShortcutManagerCompat (consulta Cómo proporcionar destinos de Direct Share):
Agrega Intent.EXTRA_INITIAL_INTENTS a tu intent de uso 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 reducirá la cantidad que sugiere el sistema. En general, evita
agregar destinos personalizados. Un ejemplo común y apropiado 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.
Excluye objetivos específicos por componente
Puedes excluir destinos específicos proporcionando Intent.EXTRA_EXCLUDE_COMPONENTS.
Solo haz esto para quitar los destinos 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 ella, ya que es probable que su intención sea compartirlo fuera de la 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) }
Obtén información sobre el uso compartido
Puede ser útil saber cuándo tus usuarios comparten contenido y qué destino seleccionan. La hoja de contenido compartido de Android te permite obtener esta información proporcionando el ComponentName de los destinos 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 el ejemplo de uso compartido de la plataforma.
Usa el agente de resolución de intents de Android
ACTION_SEND.El 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 intents de Android, crea un intent y agrega elementos adicionales 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 resolución de intents que permite al usuario elegir un destino para compartir. Si coincide una sola aplicación, se ejecuta.
Este es un ejemplo de cómo usar el agente de resolución de intents 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.