Obteniendo un resultado de una actividad

Esta lección te enseñará a

  1. Iniciar la actividad
  2. Recibir el resultado

También deberías leer

Iniciar otra actividad no tiene por qué ser un camino de una única dirección. También puedes recibir un resultado de la actividad iniciada. Para ello, llama a startActivityForResult() (en lugar de startActivity()).

Por ejemplo, tu aplicación puede iniciar una aplicación de cámara y recibir la fotografía tomada como resultado. O podrías iniciar la aplicación de Contactos para que el usuario elija un contacto y recibir los detalles de esa persona como resultado.

Por supuesto, la actividad que inicies debe estar diseñada para devolver un resultado. Si es así, esta devolverá el resultado en forma de otro objeto Intent. Tu actividad recibirá esta intención en la retrollamada onActivityResult().

Nota: Al llamar a startActivityForResult() puedes utilizar intenciones explícitas o implícitas. Si inicias una de tus propias actividades esperando un resultado, deberías utilizar una intención explícita para asegurarte de que obtienes el resultado esperado.

Iniciar la actividad


El Intent utilizado para iniciar una actividad que va a devolver un resultado no tiene nada de particular, sólo necesitas pasar un parámetro adicional de tipo entero al método startActivityForResult().

Este entero es un "código de petición" con la que identificarla. Cuando recibes el Intent resultado, la retrollamada proporciona este mismo código para que tu aplicación pueda reconocer la petición y determinar cómo manejarla.

Por ejemplo, el siguiente código permite mostrar una actividad con la que el usuario puede escoger un contacto:

static final int PICK_CONTACT_REQUEST = 1;  // El código de petición
...
private void pickContact() {
    Intent pickContactIntent = new Intent(Intent.ACTION_PICK, new Uri("content://contacts"));
    pickContactIntent.setType(Phone.CONTENT_TYPE); // Sólo mostramos los contactos con número de teléfono
    startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}

Recibir el resultado


Cuando el usuario termina de utilizar esta segunda actividad, el sistema llama al método onActivityResult() de la actividad inicial. Este método tiene tres argumentos:

  • El código de petición que pasaste en startActivityForResult().
  • Un código de resultado especificado por la segunda actividad. Este puede ser RESULT_OK si la operación terminó con éxito o RESULT_CANCELED si el usuario canceló la operación o falló por algún motivo.
  • Un Intent con la información de resultado.

Por ejemplo, así es como manejarías el resultado de la intención "escoger un contacto":

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Comprobamos a qué petición estamos respondiendo
    if (requestCode == PICK_CONTACT_REQUEST) {
        // Nos aseguramos de que la petición terminó con éxito
        if (resultCode == RESULT_OK) {
            // El usuario seleccionó un contacto.
            // La Uri del Intent identifica el contacto seleccionado.

            // Hacemos algo con el contacto (ejemplo más detallado a continuación)
        }
    }
}

En este ejemplo, el Intent resultado devuelto por la aplicación de Contactos o la aplicación de Personas de Android proporciona una Uri que identifica el contacto que seleccionó el usuario.

Para gestionar el resultado de manera adecuada, debes saber cuál será el formato del Intent resultado. Esto es fácil cuando la actividad que devuelve el resultado es una de tus actividades. Las aplicaciones incluidas en la plataforma Android ofrecen sus propias APIs en las que puedes confiar para que te devuelvan un resultado específico. Por ejemplo, la aplicación Personas (Contactos en algunas versiones antiguas) siempre devuelve un resultado con una URI de contenido que identifica el contacto seleccionado, y la aplicación de Cámara devuelve un Bitmap en el extra "data" (lee la clase acerca de Tomar fotografías).

Extra: Leer los datos de un contacto

En el ejemplo anterior sobre cómo obtener un resultado de la aplicación Personas no se explica cómo leer los datos del resultado porque esto requiere de una discusión más avanzada acerca de los proveedores de contenido. Sin embargo, si tienes curiosidad, aquí tienes algo más de código que muestra cómo consultar el resultado para obtener el número de teléfono del contacto seleccionado:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Comprobamos a qué petición estamos respondiendo
    if (requestCode == PICK_CONTACT_REQUEST) {
        // Nos aseguramos de que la petición haya tenido éxito
        if (resultCode == RESULT_OK) {
            // Obtenemos la URI que apunta al contacto seleccionado
            Uri contactUri = data.getData();
            // Sólo necesitamos la columna NUMBER, porque sólo habrá una única fila en el resultado
            String[] projection = {Phone.NUMBER};

            // Ejecutamos la consulta en el contacto para obtener la columna NUMBER
            // No necesitamos indicar una selección o un orden (sólo hay un único resultado para la URI dada)
            // PRECAUCIÓN: El método query() debería llamarse desde un hilo aparte para evitar bloquear
            // el hilo de interfaz de usuario de tu aplicación. (Por simplicidad, este código no lo hace.)
            // Considera usar CursorLoader para ejecutar la consulta.
            Cursor cursor = getContentResolver()
                    .query(contactUri, projection, null, null, null);
            cursor.moveToFirst();

            // Obtenemos el número de teléfono de la columna NUMBER
            int column = cursor.getColumnIndex(Phone.NUMBER);
            String number = cursor.getString(column);

            // Hacemos algo con el número de teléfono...
        }
    }
}

Nota: Antes de Android 2.3 (nivel API 9), ejecutar una consulta en el Proveedor de Contactos (como la que se muestra arriba) requeriría que tu aplicación pidiera el permiso READ_CONTACTS (ver Seguridad y permisos). Sin embargo, desde Android 2.3, la aplicación de Contactos/Personas concede a tu aplicación un permiso temporal para leer del Proveedor de Contactos cuando te devuelve un resultado. Este permiso temporal sólo se aplica para el contacto pedido, por lo que no podrás consultar ningún otro contacto que no sea el especificado por la Uri de la intención, a menos que solicites el permiso READ_CONTACTS.