Cómo permitir que otras apps inicien tu actividad

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Si tu app puede realizar una acción que podría ser útil desde otra app, debe estar preparada para responder a las solicitudes de acción especificando el filtro de intents apropiado en tu actividad.

Por ejemplo, si compilas una aplicación social que puede compartir mensajes o fotos con los amigos del usuario, debes admitir el intent ACTION_SEND. De esta forma, cuando los usuarios inicien una acción de "compartir" desde otra app, la tuya aparecerá como una opción en el diálogo del selector (también conocido como "diálogo de desambiguación"), como se muestra en la figura 1.

Figura 1: Diálogo del selector

Para permitir que otras apps inicien tu actividad de esta forma, debes agregar un elemento <intent-filter> en tu archivo de manifiesto para el elemento <activity> correspondiente.

Si tu app está instalada en un dispositivo, el sistema identifica tus filtros de intents y agrega la información a un catálogo interno de intents admitidos por todas las apps instaladas. Cuando una app invoca a startActivity() o a startActivityForResult() con un intent implícito, el sistema comprueba qué actividad (o actividades) puede responder al intent.

Cómo agregar un filtro de intents

Con el fin de definir de manera adecuada los intents que tu actividad puede procesar, cada filtro de intents que agregues debe ser lo más específico posible en cuanto al tipo de acción y los datos que la actividad acepta.

El sistema puede enviar un Intent determinado a una actividad si esta tiene un filtro de intents según los siguientes criterios del objeto Intent:

Acción
Se trata de una string que indica la acción que se debe realizar. Por lo general, es uno de los valores definidos por la plataforma, como ACTION_SEND o ACTION_VIEW.

Especifica esto en tu filtro de intents con el elemento <action>. El valor que especifiques en este elemento debe ser el nombre completo de la string para la acción, en lugar de la constante de la API (consulta los ejemplos que aparecen a continuación).

Datos
Es una descripción de los datos asociados con el intent.

Especifica esto en tu filtro de intents con el elemento <data>. Si usas uno o más atributos en este elemento, puedes especificar solo el tipo de MIME, solo un prefijo de URI, solo un esquema de URI, o una combinación de estos y otros atributos con el fin de indicar los tipos de datos aceptados.

Nota: Si no necesitas declarar datos específicos sobre el Uri de datos (por ejemplo, cuando tu actividad procesa otro tipo de datos "adicionales" en lugar de un URI), solo debes especificar el atributo android:mimeType para declarar el tipo de datos que tu actividad controla, como text/plain o image/jpeg.

Categoría
Es una forma adicional de caracterizar la actividad que procesa el intent, en general, relacionada con un gesto del usuario o la ubicación desde la que se inicia. El sistema admite varias categorías diferentes, pero la mayoría se usan muy poco. Sin embargo, todos los intents implícitos se definen con CATEGORY_DEFAULT de forma predeterminada.

Especifica esto en tu filtro de intents con el elemento <category>.

En el filtro de intents, puedes declarar qué criterios acepta tu actividad; para ello, decláralos de manera individual con los elementos XML correspondientes anidados en el elemento <intent-filter>.

Por ejemplo, esta es una actividad con un filtro de intents que controla el intent ACTION_SEND cuando el tipo de datos es texto o una imagen:

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
        <data android:mimeType="image/*"/>
    </intent-filter>
</activity>

Sugerencia: Si quieres que el ícono que aparece en el diálogo del selector sea diferente del ícono predeterminado de tu actividad, agrega android:icon en el elemento <intent-filter>.

Cada intent entrante especifica solo una acción y un tipo de datos, pero está bien que declares varias instancias de los elementos <action>, <category> y <data> en cada <intent-filter>.

Si existen dos pares de acción y datos que son mutuamente excluyentes en sus comportamientos, debes crear filtros de intents separados para especificar qué acciones son aceptables cuando están sincronizadas con determinados tipos de datos.

Por ejemplo, supongamos que tu actividad procesa texto e imágenes para los intents ACTION_SEND y ACTION_SENDTO. En este caso, debes definir dos filtros de intents separados para las dos acciones porque un intent ACTION_SENDTO debe usar el Uri de datos para especificar la dirección del destinatario con el esquema de URI send o sendto. Por ejemplo:

<activity android:name="ShareActivity">
    <!-- filter for sending text; accepts SENDTO action with sms URI schemes -->
    <intent-filter>
        <action android:name="android.intent.action.SENDTO"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
    </intent-filter>
    <!-- filter for sending text or images; accepts SEND action and text or image data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

Nota: Para recibir intents implícitos, debes incluir la categoría CATEGORY_DEFAULT en el filtro de intents. Los métodos startActivity() y startActivityForResult() tratan a todos los intents como si declararan la categoría CATEGORY_DEFAULT. Si no la declaras en el filtro de intents, no se resolverá ningún intent implícito en la actividad.

Para obtener más información sobre el envío y la recepción de intents ACTION_SEND relacionados con comportamientos de uso compartido en redes sociales, consulta la lección Cómo recibir datos simples de otras apps. También puedes encontrar información útil sobre cómo compartir datos en Cómo compartir datos simples y Cómo compartir archivos.

Cómo controlar el intent en tu actividad

A fin de decidir la acción que debe realizarse en tu actividad, puedes leer el Intent que se usó para iniciarla.

Al iniciar tu actividad, llama a getIntent() para recuperar el Intent que inició la actividad. Puedes hacerlo en cualquier momento del ciclo de vida de la actividad, pero generalmente debes hacerlo durante las primeras devoluciones de llamadas, como onCreate() o onStart().

Por ejemplo:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.main)

    val data: Uri? = intent?.data

    // Figure out what to do based on the intent type
    if (intent?.type?.startsWith("image/") == true) {
        // Handle intents with image data ...
    } else if (intent?.type == "text/plain") {
        // Handle intents with text ...
    }
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    // Get the intent that started this activity
    Intent intent = getIntent();
    Uri data = intent.getData();

    // Figure out what to do based on the intent type
    if (intent.getType().indexOf("image/") != -1) {
        // Handle intents with image data ...
    } else if (intent.getType().equals("text/plain")) {
        // Handle intents with text ...
    }
}

Cómo mostrar un resultado

Si quieres mostrar un resultado a la actividad que invocó la tuya, simplemente llama al setResult() para especificar el código y el Intent de resultado. Cuando la operación finalice y el usuario deba volver a la actividad original, llama al elemento finish() para cerrar (y destruir) tu actividad. Por ejemplo:

Kotlin

// Create intent to deliver some kind of result data
Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri")).also { result ->
    setResult(Activity.RESULT_OK, result)
}
finish()

Java

// Create intent to deliver some kind of result data
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri"));
setResult(Activity.RESULT_OK, result);
finish();

Siempre debes especificar un código de resultado con el resultado. En general, es RESULT_OK o RESULT_CANCELED. Luego, puedes proporcionar datos adicionales con un Intent, según sea necesario.

Nota: El resultado se establece en RESULT_CANCELED de forma predeterminada. De este modo, si el usuario presiona el botón Atrás antes de completar la acción y antes de que establezcas el resultado, la actividad original recibirá el resultado de "cancelada".

Si solo necesitas mostrar un valor entero que indique una de varias opciones de resultado, puedes establecer el código de resultado en cualquier valor superior a 0. Si usas el código de resultado para entregar un valor entero y no necesitas incluir el Intent, puedes llamar a setResult() y pasar solo un código de resultado. Por ejemplo:

Kotlin

setResult(RESULT_COLOR_RED)
finish()

Java

setResult(RESULT_COLOR_RED);
finish();

En este caso, solo puede haber unos pocos resultados posibles, de modo que el código de resultado es un valor entero definido localmente (mayor que 0). Esto funciona bien cuando muestras un resultado a una actividad en tu propia app, porque la actividad que recibe el resultado puede hacer referencia a la constante pública que determina el valor del código de resultado.

Nota: No es necesario verificar si tu actividad se inició con startActivity() o startActivityForResult(). Simplemente llama a setResult() si el intent que inició tu actividad puede esperar un resultado. Si la actividad inicial llama a startActivityForResult(), el sistema mostrará el resultado que proporciones a setResult(); de lo contrario, se ignorará el resultado.