Enviando contenido a otras aplicaciones

Al crear una intención, tenemos que especificar la acción que queremos que "lance". Android define varias acciones, incluyendo ACTION_SEND la cual, como habrás adivinado, indica que la intención está enviando datos de una actividad a otra, cosa que puede hacerse incluso entre actividades en distintos procesos. Para enviar datos a otra actividad, todo lo que necesitas hacer es especificar el dato y su tipo, el sistema identificará las actividades que pueden recibirlo y se las mostrará al usuario (si existen múltiples opciones) o iniciará inmediatamente la actividad (si sólo hay una opción). De forma similar, puedes indicar los tipos de datos que otras aplicaciones pueden enviar a tu actividad especificándolos en tu manifiesto.

El uso más habitual del envío y recepción de datos entre aplicaciones usando intenciones es compartir contenido de forma social. Las intenciones permiten a los usuarios compartir información de forma rápida y sencilla, usando sus aplicaciones favoritas.

Nota: La mejor forma de añadir una acción para compartir a una ActionBar es usar ShareActionProvider, que está disponible desde el nivel API 14. Trataremos el uso de ShareActionProvider en profundidad en la lección Añadiendo una acción de compartir.

Enviar texto


Figura 1. Captura de pantalla de un selector de una intención ACTION_SEND en un dispositivo de mano.

La forma más sencilla y común de usar la acción ACTION_SEND es enviar texto de una actividad a otra. Por ejemplo, la aplicación de navegador incluida por defecto puede compartir la URL de la página que se está mostrando en ese momento con cualquier aplicación. Esto es útil si quieres compartir un artículo o una página web con un amigo usando el correo electrónico o las redes sociales. Aquí está el código necesario para implementar este tipo de funcionalidad:

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "Este es mi texto a enviar.");
sendIntent.setType("text/plain");
startActivity(sendIntent);

Si hay alguna aplicación instalada que tenga un filtro que coincida con la acción ACTION_SEND y el tipo MIME text/plain, el sistema Android lo ejecutará; si coincide más de una aplicación, el sistema mostrará un diálogo que permita al usuario elegir una aplicación. Si llamas al método Intent.createChooser() de la intención, Android mostrará siempre el diálogo de selección. Esto tiene algunas ventajas:

  • El selector se mostrará incluso aunque el usuario seleccionara una acción por defecto para esta intención anteriormente.
  • Si no coincide ninguna aplicación, Android mostrará un mensaje de sistema.
  • Puedes especificar un título para el diálogo de selección.

Este es el código actualizado:

Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "Este es mi texto a enviar.");
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));

El diálogo resultante se muestra en la figura 1.

Opcionalmente, puedes establecer algunos extras estándar para la intención: EXTRA_EMAIL, EXTRA_CC, EXTRA_BCC, EXTRA_SUBJECT. Si la aplicación receptora no ha sido diseñada para usarlos, no pasará nada. También puedes utilizar extras personalizados, pero no tendrán ningún efecto a menos que la aplicación receptora los entienda. Típicamente, querrás usar extras personalizados definidos por la propia aplicación receptora.

Nota: Algunas aplicaciones de correo electrónico, como Gmail, esperan un String[] para algunos extras como EXTRA_EMAIL y EXTRA_CC, utiliza putExtra(String, String[]) para añadirlo a tu intención.

Enviar datos binarios


Los datos binarios se comparten utilizando la acción ACTION_SEND combinada con el tipo MIME adecuado y una URI a los datos en un campo extra llamado EXTRA_STREAM. Esto se utiliza habitualmente para compartir una imagen pero puede ser utilizado para compartir cualquier tipo de contenido binario:

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));

Ten en cuenta lo siguiente:

  • Puedes usar un tipo MIME "*/*", pero esto seleccionará sólo actividades capaces de manejar flujos de datos genéricos.
  • La aplicación receptora necesita permisos para acceder a los datos a los que apunta la Uri. Hay varias formas de conseguir esto:
    • Guardar los datos en un archivo en almacenamiento externo/compartido (como una tarjeta SD), que pueden leer todas las aplicaciones. Utiliza Uri.fromFile() para crear la Uri que se puede pasar a la intención de compartir. Sin embargo, ten en cuenta que no todas las aplicaciones pueden procesar una Uri de tipo file://.
    • Guardar los datos en un archivo en el propio directorio de tu aplicación usando openFileOutput() con el modo MODE_WORLD_READABLE tras lo cual se puede usar getFileStreamPath() para devolver un objeto File. Como en la opción anterior, Uri.fromFile() creará una Uri de tipo file:// para que puedas añadirla a la intención de compartir.
    • Los archivos multimedia como imágenes, vídeos y audio pueden ser escaneados y añadidos al MediaStore del sistema usando scanFile(). La retrollamada onScanCompleted() devuelve una Uri de tipo content:// adecuada para ser añadida a la intención de compartir.
    • Las imágenes se pueden insertar en el MediaStore del sistema usando insertImage() el cuál devuelve una Uri de tipo content:// apropiada para ser añadida a la intención de compartir.
    • Almacenar los datos en tu propio ContentProvider, asegurándote de que otras aplicaciones tengan los permisos adecuados para acceder a tu proveedor (o utiliza permisos por URI).

Enviar múltiples elementos


Para compartir múltiples elementos, utiliza la acción ACTION_SEND_MULTIPLE junto con una lista de URIs que apunten al contenido. El tipo MIME variará de acuerdo a la mezcla de contenido que estés compartiendo. Por ejemplo, si compartes 3 imágenes JPEG, el tipo seguirá siendo "image/jpeg". Para una mezcla de tipos de imágenes, debería ser "image/*" para que coincida con una actividad que maneje imágenes de todo tipo. Sólo deberías usar "*/*" si estás compartiendo una amplia variedad de tipos. Como se indicó previamente, es tarea de la aplicación receptora procesar tus datos. Aquí tenemos un ejemplo:

ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Añade las URIs de tus imágenes aquí
imageUris.add(imageUri2);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, "Share images to.."));

Como antes, asegúrate de que las URIs proporcionadas apunten a datos a los que la aplicación receptora pueda acceder.