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 ello, 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 de Personas para que el usuario seleccione un contacto, y recibirás los detalles de él como resultado.

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

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

Cómo iniciar la actividad

No hay nada especial en relación con el objeto Intent que usas cuando inicias una actividad para obtener un resultado, pero no es necesario que pases un argumento de valor entero adicional al método startActivityForResult().

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

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

Kotlin

    const val PICK_CONTACT_REQUEST = 1  // The request code
    ...
    private fun pickContact() {
        Intent(Intent.ACTION_PICK, Uri.parse("content://contacts")).also { pickContactIntent ->
            pickContactIntent.type = Phone.CONTENT_TYPE // Show user only contacts w/ phone numbers
            startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST)
        }
    }
    

Java

    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);
    }
    

Cómo recibir el resultado

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

  • El código de solicitud que se pasó a startActivityForResult()
  • Un código de resultado especificado por la segunda actividad (se trata de RESULT_OK si se realizó la operación de manera correcta o de RESULT_CANCELED si se retiró el usuario o falló la operación por algún motivo)
  • Un Intent que lleva los datos del resultado

Por ejemplo, a continuación se muestra cómo controlar el resultado del intent para "elegir un contacto":

Kotlin

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
        // Check which request we're responding to
        if (requestCode == PICK_CONTACT_REQUEST) {
            // Make sure the request was successful
            if (resultCode == Activity.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)
            }
        }
    }
    

Java

    @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 Intent del resultado que muestra la app de Contactos o Personas de Android proporciona un Uri de contenido que identifica el contacto que seleccionó el usuario.

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

Actividad adicional: Lee los datos de contacto

En el código anterior que muestra cómo obtener un resultado de la app de Personas, no se explica la manera de leer los datos del resultado, ya que 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 los datos de resultado para obtener el número de teléfono del contacto seleccionado:

Kotlin

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
        // Check which request it is that we're responding to
        if (requestCode == PICK_CONTACT_REQUEST) {
            // Make sure the request was successful
            if (resultCode == Activity.RESULT_OK) {
                // We only need the NUMBER column, because there will be only one row in the result
                val projection: Array<String> = arrayOf(Phone.NUMBER)

                // Get the URI that points to the selected contact
                data.data?.also { contactUri ->
                    // 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 this 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 <code><a href="/reference/android/content/CursorLoader.html">CursorLoader</a></code> to perform the query.
                    contentResolver.query(contactUri, projection, null, null, null)?.apply {
                        moveToFirst()

                        // Retrieve the phone number from the NUMBER column
                        val column: Int = getColumnIndex(Phone.NUMBER)
                        val number: String? = getString(column)

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

Java

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent resultIntent) {
        // 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 = resultIntent.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 <code><a href="/reference/android/content/CursorLoader.html">CursorLoader</a></code> 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 anteriores a Android 2.3 (API nivel 9), realizar una consulta en Contacts Provider (como la que se muestra arriba) requiere que la app declare el permiso READ_CONTACTS (consulta Seguridad y permisos). Sin embargo, a partir de Android 2.3, la app de Contactos/Personas otorga a tu app un permiso temporal para leer desde el Proveedor de contactos cuando se muestra un resultado. El permiso temporal se aplica solo al contacto específico solicitado, por lo que no puede consultar un contacto que no sea el que especifique el Uri del intent, a menos que declares el permiso READ_CONTACTS.

Para obtener información adicional sobre los temas de esta página, consulta los siguientes recursos: