Cómo obtener un resultado de una actividad

El inicio de otra actividad no siempre tiene que ser en un único sentido. También puedes iniciar otra actividad y recibir un resultado. Para recibir un resultado, llama a startActivityForResult() (en lugar de startActivity()).

Por ejemplo, tu app puede iniciar una app de cámara y recibir la fotografía tomada como resultado. O bien, puedes iniciar la app Personas para que el usuario seleccione un contacto, y recibirás los detalles del contacto como resultado.

Por supuesto, la actividad que responde debe estar diseñada para devolver un resultado. Cuando es así, envía el resultado en forma de otro objeto Intent. Tu actividad lo recibe en la devolución de llamada onActivityResult().

Nota: Puedes utilizar intents explícitas o implícitas cuando llamas a startActivityForResult(). Cuando inicias una de tus propias actividades para recibir un resultado, debes utilizar una intent explícita para asegurarte de recibir el resultado esperado.

Iniciar la actividad

El objeto Intent empleado para iniciar una actividad que mostrará un resultado no tiene nada de particular, pero debes pasar un argumento de valor entero adicional al método startActivityForResult().

El argumento de entero es un "código de solicitud" que identifica tu solicitud. Cuando recibes el Intent de resultado, la devolución de llamada proporciona el mismo código de solicitud para que tu app pueda identificar debidamente el resultado y determinar cómo manejarlo.

Por ejemplo, a continuación se indica cómo iniciar una actividad que permite que el usuario elija un contacto:

static final int PICK_CONTACT_REQUEST = 1;  // The request code
...
private void pickContact() {
    Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
    pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
    startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}

Recibir el resultado

Cuando el usuario termina de utilizar la actividad subsiguiente y vuelve, el sistema llama al método onActivityResult() de tu actividad. Este método incluye tres argumentos:

  • El código de solicitud que pasaste a startActivityForResult().
  • Un código de resultado especificado por la segunda actividad. Este código puede ser RESULT_OK si la operación se realizó correctamente o RESULT_CANCELED si el usuario canceló la operación o esta falló por algún motivo.
  • Un Intent con la información del resultado.

Por ejemplo, a continuación se muestra cómo puede manejar el resultado de la intent "elegir un contacto":

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Check which request we're responding to
    if (requestCode == PICK_CONTACT_REQUEST) {
        // Make sure the request was successful
        if (resultCode == RESULT_OK) {
            // The user picked a contact.
            // The Intent's data Uri identifies which contact was selected.

            // Do something with the contact here (bigger example below)
        }
    }
}

En este ejemplo, el resultado Intent devuelto por la app Personas de Android proporciona un Uri de contenido que identifica al contacto que el usuario seleccionó.

Para manejar correctamente el resultado, debes comprender cuál será el formato del Intent del resultado. Esto es fácil cuando la actividad que devuelve el resultado es una de sus propias actividades. Las apps incluidas con la plataforma Android ofrecen sus propias API, que puedes utilizar para obtener datos de resultados específicos. Por ejemplo, la app Personas siempre muestra un resultado con el URI de contenido que identifica al contacto seleccionado, y la app Cámara devuelve un Bitmap en el elemento adicional "data" (consulta la clase Cómo tomar fotos).

Extra: Leer los datos de un contacto

En el código anterior que muestra cómo obtener un resultado de la app Personas, no se explica la manera de leer los datos del resultado porque esto requiere un análisis más avanzado sobre los proveedores de contenido. Sin embargo, si tienes curiosidad, a continuación se incluye un 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) {
    // Check which request it is that we're responding to
    if (requestCode == PICK_CONTACT_REQUEST) {
        // Make sure the request was successful
        if (resultCode == RESULT_OK) {
            // Get the URI that points to the selected contact
            Uri contactUri = data.getData();
            // We only need the NUMBER column, because there will be only one row in the result
            String[] projection = {Phone.NUMBER};

            // Perform the query on the contact to get the NUMBER column
            // We don't need a selection or sort order (there's only one result for the given URI)
            // CAUTION: The query() method should be called from a separate thread to avoid blocking
            // your app's UI thread. (For simplicity of the sample, this code doesn't do that.)
            // Consider using CursorLoader to perform the query.
            Cursor cursor = getContentResolver()
                    .query(contactUri, projection, null, null, null);
            cursor.moveToFirst();

            // Retrieve the phone number from the NUMBER column
            int column = cursor.getColumnIndex(Phone.NUMBER);
            String number = cursor.getString(column);

            // Do something with the phone number...
        }
    }
}

Nota: En versiones de Android anteriores a la 2.3 (nivel de API 9), para ejecutar una consulta en Contacts Provider (como la que se muestra anteriormente), tu app debe declarar el permiso READ_CONTACTS (consulta el documento sobre seguridad y permisos). Sin embargo, a partir de Android 2.3, la app Contactos/Personas otorga a tu app un permiso temporal para leer desde el Proveedor de Contactos cuando este muestra un resultado. El permiso temporal se aplica solo al contacto solicitado, por lo cual no podrás consultar otro contacto que no sea el especificado por el Uri de la intent, a menos que declares el permiso READ_CONTACTS.