Como permitir que outros apps iniciem sua atividade

Se seu app pode executar uma ação que talvez seja útil para outro app, ele precisa estar preparado para responder às solicitações de ação especificando o filtro de intent apropriado na sua atividade.

Por exemplo, se você criar um aplicativo social que possa compartilhar mensagens ou fotos com os amigos do usuário, precisará oferecer compatibilidade com o intent ACTION_SEND. Assim, quando os usuários iniciarem uma ação de "compartilhamento" a partir de outro app, seu aplicativo aparecerá como uma opção na caixa de diálogo seletora (também conhecida como "caixa de diálogo de desambiguação"), como mostrado na Figura 1.

Figura 1. Caixa de diálogo seletora.

Para permitir que outros apps iniciem sua atividade dessa maneira, é necessário adicionar um elemento <intent-filter> no seu arquivo de manifesto para o elemento <activity> correspondente.

Quando seu app é instalado em um dispositivo, o sistema identifica seus filtros de intent e adiciona as informações a um catálogo interno de intents compatível com todos os apps instalados. Quando um app chama startActivity() ou startActivityForResult(), com um intent implícito, o sistema descobre qual atividade (ou atividades) pode responder ao intent.

Adicionar um filtro de intent

Para definir adequadamente quais intents sua atividade poderá processar, cada filtro de intent adicionado precisará ser o mais específico possível em termos de tipo de ação e dados aceitos pela atividade.

O sistema poderá enviar um determinado Intent para uma atividade se ela tiver um filtro de intent que atenda aos seguintes critérios do objeto Intent:

Ação
String que dá nome à ação a ser executada. Geralmente, um dos valores definidos pela plataforma, como ACTION_SEND ou ACTION_VIEW.

Especifique no seu filtro de intent com o elemento <action>. O valor especificado nesse elemento precisa ser o nome completo da string para a ação, e não a constante da API (veja exemplos abaixo).

Dados
A descrição dos dados associados ao intent.

Especifique no seu filtro de intent com o elemento <data>. Usando um ou mais atributos nesse elemento, você pode especificar apenas o tipo MIME, apenas um prefixo de URI, apenas um esquema de URI ou uma combinação desses e de outros elementos que indicam o tipo de dado aceito.

Observação: se não for necessário especificar o Uri dos dados (como quando a atividade processa outros tipos de dados “extras”, em vez de um URI), especifique apenas o atributo android:mimeType para declarar o tipo de dado que a atividade processa, como text/plain ou image/jpeg.

Categoria
Oferece uma outra forma de caracterizar a atividade que processa o intent, geralmente relacionada ao gesto do usuário ou ao local onde ela foi iniciada. Há diversas categorias compatíveis com o sistema, mas a maioria raramente é usada. No entanto, todos os intents implícitos são definidos com CATEGORY_DEFAULT por padrão.

Especifique no seu filtro de intent com o elemento <category>.

No filtro de intent, declare quais critérios serão aceitos pela atividade declarando cada um deles com elementos XML correspondentes aninhados no elemento <intent-filter>.

Este é um exemplo de atividade com filtro de intent que processa o intent ACTION_SEND quando o tipo de dado é texto ou imagem:

    <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>
    

Dica: se você quer que o ícone na caixa de diálogo seletora seja diferente do ícone padrão da sua atividade, adicione android:icon no elemento <intent-filter>.

Cada intent recebido especifica apenas uma ação e um tipo de dado, mas é possível declarar várias instâncias dos elementos <action>, <category> e <data> em cada <intent-filter>.

Se dois pares de ação e dados forem mutuamente exclusivos no comportamento, crie filtros de intent separados para especificar quais ações são aceitáveis quando pareadas com qual tipo de dado.

Por exemplo, suponha que a atividade processe texto e imagens para os intents ACTION_SEND e ACTION_SENDTO. Nesse caso, é preciso definir dois filtros de intent separados para as duas ações porque um intent ACTION_SENDTO tem que usar o Uri de dados para especificar o endereço do destinatário usando o esquema de URI send ou sendto. Exemplo:

    <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>
    

Observação: para receber intents implícitos, você precisa incluir a categoria CATEGORY_DEFAULT no filtro de intent. Os métodos startActivity() e startActivityForResult() tratam todos os intents como se eles declarassem a categoria CATEGORY_DEFAULT. Se você não a declarar no seu filtro de intent, nenhum intent implícito será resolvido para sua atividade.

Para mais informações sobre como enviar e receber intents ACTION_SEND que realizam comportamentos de compartilhamento em redes sociais, consulte a lição sobre Como receber dados simples de outros apps. Você também pode encontrar informações úteis sobre o compartilhamento de dados em Compartilhamento de dados simples e Compartilhamento de arquivos.

Processar o intent na sua atividade

Para decidir qual ação realizar na sua atividade, leia o Intent que foi usado para iniciá-la.

Quando sua atividade começar, chame getIntent() para recuperar o Intent que a iniciou. É possível fazer isso a qualquer momento durante o ciclo de vida da atividade, mas recomenda-se fazê-lo durante callbacks iniciais, como onCreate() ou onStart().

Exemplo:

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.main)

        val data: Uri? = intent?.data

        // Figure out what to do based on the intent type
        if (intent?.type?.startsWith("image/") == true) {
            // Handle intents with image data ...
        } else if (intent?.type == "text/plain") {
            // Handle intents with text ...
        }
    }
    

Java

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

Retornar um resultado

Se você quiser retornar um resultado para a atividade que invocou a sua, basta chamar setResult() para especificar o código e o Intent do resultado. Quando a operação estiver concluída e o usuário precisar retornar à atividade original, chame finish() para fechar (e destruir) a atividade. Por exemplo:

Kotlin

    // Create intent to deliver some kind of result data
    Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri")).also { result ->
        setResult(Activity.RESULT_OK, result)
    }
    finish()
    

Java

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

Sempre especifique um código de resultado com o resultado. Geralmente, é RESULT_OK ou RESULT_CANCELED. Você pode fornecer outros dados com um Intent, conforme necessário.

Observação: o resultado é definido como RESULT_CANCELED por padrão. Portanto, se o usuário pressionar o botão Voltar antes de concluir a ação e de você definir o resultado, a atividade original receberá o resultado "cancelado".

Se você só precisa retornar um número inteiro que indique uma das várias opções de resultado, defina o código do resultado para qualquer valor maior que 0. Se você usar o código de resultado para entregar um número inteiro e não precisar incluir o Intent, poderá chamar setResult() e passar apenas um código de resultado. Exemplo:

Kotlin

    setResult(RESULT_COLOR_RED)
    finish()
    

Java

    setResult(RESULT_COLOR_RED);
    finish();
    

Nesse caso, talvez existam apenas alguns poucos resultados possíveis. Portanto, o código do resultado é um número inteiro definido localmente (maior que 0). Isso funciona bem ao retornar um resultado para uma atividade no seu app, porque a atividade que recebe o resultado pode fazer uma referência à constante pública para determinar o valor do código de resultado.

Observação: não é necessário verificar se sua atividade foi iniciada com startActivity() ou startActivityForResult(). Basta chamar setResult() se o intent que iniciou sua atividade esperar um resultado. Se a atividade inicial tivesse chamado startActivityForResult(), o sistema forneceria o resultado que você forneceu para setResult(). Caso contrário, o resultado é ignorado.