X

Permitir que otras Apps inicien tu Actividad

Las dos lecciones anteriores se enfocaban en una parte de la historia: iniciar la actividad de otra app desde tu propia app. Pero si tu app puede realizar una acción que puede ser útil en otra app, tu app debería estar preparada para responder a peticiones de acción de otras apps. Por ejemplo, si creas una app social que puede compartir mensajes o fotos con amigos, es de vital interés para ti dar soporte al intent ACTION_SEND para que los usuarios puedan iniciar la acción “compartir” desde otra app e iniciar tu aplicación para realizar dicha acción.

Para permitir que otras apps inicien tu actividad, necesitas añadir el elemento <intent-filter> en el archivo manifest, en el elemento <activity> correspondiente.

Cuando tu app se instala en un dispositivo, el sistema identifica los filtros intent de la misma y añade esa información al catálogo interno de intents sopotados por todas las apps instaladas. Cuando una app llama startActivity() o startActivityForResult(), con un intent implícito, el sistema encuentra que actividad (o actividades) puede responder a dicho intent.

Añadir un Filtro de Intent

Para definir correctamente que intentos de tu actividad pueden gestionarse, cada filtro de intento que añadas debería ser tan específico como sea posible en términos de que tupo de acción y datos aceptará la actividad.

El sistema puede enviar un Intent dado a una actividad si la misma tiene un filtro de intento que encaje con los siguientes criterios del objeto Intent:

  • Action: Un string nombrando la acción a realizar. Normalmente uno de los valores definidos en la plataforma como ACTION_SEND o ACTION_VIEW. Puedes especificarlo en tu filtro de intent con el elemento <action>. El valor que especifiques en este elemento debe ser el nombre completo del string de la acción, en lugar de la constante de la API (ver ejemplos más abajo).
  • Datos: Una descripción de los datos asociados con el intent. Puedes especificarlo en tu filtro de intent con el elemento <data>. Puedes utilizar uno o más atributos en este elemento, puedes especificar solo el tipo MIME, o solo el prefijo URI, un esquema URI, o una combinación de todos esos y otros que indiquen que tipo de data se acepta.

    Nota: Si no necesitas declarar datos específicos Uri (como cuando tu actividad gestiona otro tipo de data “extra”, en lugar de un URI), puedes especificar solo el atributo android:mimeType ara declarar el tipo de data que tu actividad gestiona, como puede ser text/plain o image/jpg.

  • Categoría: Proporciona una forma adicional para caracterizar la actividad que gestiona el intent, normalmente se relaciona a los gestos del usuario o la ubicación en donde se iniciaron. Hay diferentes categorías soportadas por el sistema, pero la mayoría raramente se utilizan. Sin embargo, todos los intents implicitos se definen con CATEGORY_DEFAULT por defecto. Puedes especificarlo con el elemento <category>.

En tu filtro de intent, puedes declarar que criterios aceptará tu actividad declarándolos con e oscorrespondiente elementos XML anidados en el elemento <intent-filter>.

Por ejemplo, abajo puedes ver una actividad con un filtro de intent que gestiona el intent ACTION_SEND cuando el tipo de datos es texto o 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>

Cada intent entrante especifica solo una acción y un tipo de data, pero es correcto declarar múltiples instancias de los elementos <action><category>, y <data> en cada <intent-filter>.

Si cualquiera de los dos pares de acción y dato son mutuamente exclusivos en sus comportamientos, deberías crear filtros de intento separados para especificar que acciones se pueden aceptar con según que tipo de dato.

Por ejemplo, imagina que tienes una actividad que gestiona tanto texto como imágenes con los intent ACTION_SEND y ACTION_SENDTO. En este caso, debes definidr dos filtros de intent separados para las dos acciones ya que ACTION_SENDTO debe utilizar datos Uri para especificar la dirección utilizando el esquema URI send o sendto.

<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 implicitos, debes incluir la categoría CATEGORY_DEFAULT en el filtro de intent. Los métodos startActivity() y startActivityForResult() tratan todos los intents como si fuesen declarados en la categoría CATEGORY_DEFAULT. Si no lo has declarado en tu filtro de intent, no se resolveránl os intents implicitos en tu actividad.

Para más información sobre enviar y recibir intents que realizan comportamientos relacionados con compartir, visita la lección Recibir Datos Simples desde Otras Apps

Gestionar el Intent en tu Actividad

A la hora de decidir que acción tomar en tu actividad, puedes leer el Intent que se utilizó para iniciarlo.

Al iniciar tu actividad, llama a getIntent() para recibir el Intent que inició la actividad. Puedes hacerlo durante el ciclo de vida de la actividad, pero deberías generalmente hacerlo durante los callbacks tempranos, como puede ser onCreate() o onStart().

Por ejemplo:

@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 ...
    }
}

Devolver un Resultado

Si quieres devolver un resultado a la actividad que llamo a la tuya, simplemente utiliza setResult() para especificar el código e Intent del resultado. Cuando se termina dicha operación y el usuario debería volver a la actividad original, utiliza finish() para cerrar (y destruir) tu actividad. Por ejemplo:

// 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();

Debes especificar siempre un código resultante con el resultado. Generalmente se utiliza tanto RESULT_OK como RESULT_CANCELED. Puedes proporcionar datos adicionales con un Intent, si fuese necesario.

Nota: El resultado es, por defecto, RESULT_CANCELED. Así que si el usuario selecciona el botón atrás antes de terminar la acción y antes de que tu hayas colocado el resultado, la actividad original recibirá el resultado “cancelado”.

Si simplemente necesitas devolver un entero que indica una o varias opciones resultantes, puedes colocar el código resultado con cualquier valor superior a 0. Si es el caso y utilizas el código resultante para enviar un entero y no tienes necesidad de incluirlo en el Intent, puedes llamar a setResult() y pasar exclusivamente el código resultado. Por ejemplo:

If you simply need to return an integer that indicates one of several result options, you can set the result code to any value higher than 0. If you use the result code to deliver an integer and you have no need to include the Intent, you can call setResult() and pass only a result code. For example:

setResult(RESULT_COLOR_RED);
finish();

En este caso, hay solo unos cuantos posibles resultados, así que el código resultante se define localmente como un entero (mayor que 0). Esto funciona bien cuando devuelves un resultado a una actividad en tu propia app, ya que tu actividad puede hacer referencia a la constante pública para determinar el valor del código resultante.

Nota: No hay necesidad de comprobar si tu actividad fue iniciada con startActivity()startActivityForResult(). Simplemente utiliza setResult() si el intent que inició tu actividad puede esperar un resultado. Si la actividad original ha utilizado startActivityForResult(), entonces el sistema envía el resultado que suministraste en setResult(); de otra manera, el resultado es ignorado.

Puedes ver más información sobre Conseguir un Resultado de una Actividad en la página oficial de Google en inglés pulsando aquí.

View Comments (1)

Los comentarios de Disqus están cargando....