Como obter resultados de uma atividade

Iniciar outra atividade não precisa ser algo unidirecional. Pode-se também iniciar outra atividade e receber um resultado de volta. Para receber um resultado, chame startActivityForResult() (em vez de startActivity()).

Por exemplo, o aplicativo pode iniciar um aplicativo de câmera e receber a foto capturada como resultado. Ou, ao iniciar o aplicativo Pessoas para que o usuário selecione um contato, você receberá os detalhes do contato como resultado.

Evidentemente, a atividade que responde deve ser projetada para retornar um resultado. Quando isso acontecer, ela enviará o resultado como outro objeto Intent. A atividade recebe o resultado no retorno de chamada onActivityResult().

Observação: Pode-se usar intents explícitos ou implícitos ao chamar startActivityForResult(). Ao iniciar uma de suas atividades para receber um resultado, use um intent explícito para garantir que o resultado esperado seja recebido.

Iniciar a atividade

Não há nada especial no objeto Intent usado para iniciar uma atividade para um resultado, mas é preciso passar um argumento de número inteiro adicional ao método startActivityForResult().

O argumento de número inteiro é um “código de pedido” que identifica o pedido. Quando você recebe o resultado Intent, o retorno de chamada fornece o mesmo código de pedido para que o aplicativo possa identificar adequadamente o resultado e determinar como processá-lo.

Por exemplo, eis como iniciar uma atividade que permite ao usuário escolher um contato:

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

Receber o resultado

Quando o usuário termina a atividade subsequente e retorna, o sistema chama o método onActivityResult() da atividade. Esse método inclui três argumentos:

  • O código de pedido passado para startActivityForResult().
  • Um código de resultado especificado pela segunda atividade. Se a operação for bem-sucedida, isso será RESULT_OK. E será RESULT_CANCELED se o usuário tiver desistido ou a operação tiver falhado por algum motivo.
  • Um Intent que transporta os dados do resultado.

Por exemplo, eis como você pode processar o resultado do intent “escolher um contato”:

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

Nesse exemplo, o resultado Intent retornado pelos aplicativos Contatos ou Pessoas do Android fornece um conteúdo Uri que identifica o contato escolhido pelo usuário.

Para que o resultado seja processado de forma adequada, é preciso saber o formato do resultado Intent. Isso é fácil quando umas das suas atividades retorna o resultado. Os aplicativos incluídos na plataforma Android oferecem as próprias APIs que podem ser usadas para dados de resultado específicos. Por exemplo, o aplicativo Pessoas sempre retorna um resultado com URI de conteúdo que identifica o contato escolhido e o aplicativo Câmera retorna um Bitmap no "data" extra (consulte a lição Captura de fotografias).

Bônus: Ler os dados do contato

O código acima, que mostra como obter um resultado do aplicativo Pessoas, não traz muitos detalhes sobre como exatamente ler os dados do resultado porque é necessária uma discussão mais avançada sobre provedores de conteúdo. No entanto, se você desejar saber mais, aqui estão alguns códigos que mostram como consultar os dados de resultado para obter o número de telefone do contato selecionado:

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

Observação: Antes do Android 2.3 (API de nível 9), executar uma consulta em Contacts Provider (como mostrado acima) exige que o aplicativo declare a permissão READ_CONTACTS (consulte Segurança e permissões). Contudo, a partir do Android 2.3, o aplicativo Contatos/Pessoas dá ao aplicativo permissão temporária para ler do Provedor de Contatos quando ele retorna um resultado. A permissão temporária se aplica apenas a pedidos de contato específicos, portanto não é possível consultar um contato diferente daquele especificado pela Uri do intent a menos que você declare a permissão READ_CONTACTS.