Receber dados de outros apps

Assim como um app pode enviar dados para outros apps, ele também pode receber dados de outros apps. Pense em como os usuários interagem com seu aplicativo e quais tipos de dados você quer receber de outros aplicativos. Por exemplo, um aplicativo de rede social pode ter interesse em receber conteúdo de texto, como um URL da Web interessante, de outro app.

Em um app que usa a navegação do Compose, o recebimento de dados enviados por outro app é um processo de três etapas:

  1. Declare um <intent-filter> no manifesto: ainda é necessário adicionar um filtro de intent à sua atividade no arquivo AndroidManifest.xml. Isso informa ao SO Android que seu aplicativo pode receber ações específicas (como ACTION_SEND) e tipos MIME (como text/plain).

  2. Defina um navDeepLink no gráfico de navegação do Compose: anexe um navDeepLink que corresponda à ação e ao tipo MIME diretamente ao destino combinável que deve mostrar o conteúdo. O NavController intercepta automaticamente a intent recebida e direciona o usuário diretamente para essa tela.

  3. Extraia o payload de dados recebidos: na tela de destino, acesse os extras de intent (como EXTRA_TEXT ou EXTRA_STREAM) para recuperar o conteúdo compartilhado e atualizar o estado da interface.

Os destinos de compartilhamento direto são links diretos para uma Activity específica no seu app. Eles geralmente representam uma pessoa ou um grupo, e a Android Sharesheet os mostra. Por exemplo, um app de mensagens pode fornecer um destino de compartilhamento direto para uma pessoa que tenha um link direto para uma conversa com ela. Consulte Fornecer destinos de compartilhamento direto para instruções detalhadas.

Oferecer suporte a tipos MIME

O ideal é que um app possa receber a maior variedade possível de tipos MIME. Por exemplo, um app de mensagens projetado para enviar texto, imagens e vídeo oferece suporte ao recebimento de text/*, image/* e video/*. Confira alguns tipos MIME comuns para enviar e receber dados no Android.

Os receptores se registram para Os remetentes enviam
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
image/*
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
Extensões de arquivo compatíveis application/pdf

Consulte o registro oficial de tipos de mídia MIME da IANA (em inglês).

Criar ótimos destinos de compartilhamento

Quando os usuários tocam em um destino de compartilhamento associado a uma atividade específica, permita que eles confirmem e editem o conteúdo compartilhado antes que o app o use. Isso é especialmente importante para dados de texto.

Receber dados no app

O recebimento de dados compartilhados em um app que usa o Compose envolve a declaração de filtros de intent no manifesto, o roteamento de intents recebidas para a tela adequada com links diretos e a extração do payload da intent para atualizar a interface.

Atualizar seu manifesto

Os filtros de intent informam ao sistema quais intents um componente do app aceita. Assim como você criou uma intent com uma ação ACTION_SEND na lição Enviar dados para outros apps, crie filtros de intent para receber intents com essa ação. Você define um filtro de intent no manifesto usando o <intent-filter> elemento. Por exemplo, se o app processar o recebimento de conteúdo de texto, um manifesto que inclua uma ou mais imagens de qualquer tipo será semelhante ao snippet a seguir:

<activity android:name=".ui.MyActivity" android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

Quando outro app tenta compartilhar qualquer um desses itens criando uma intent e transmitindo-a para startActivity(), seu aplicativo é listado como uma opção na Android Sharesheet ou no resolvedor de intents. Se o usuário selecionar seu app, isso iniciará a atividade correspondente (.ui.MyActivity no exemplo anterior). Em seguida, você precisa processar o conteúdo adequadamente no código e na interface.

Na navegação do Compose, anexe um navDeepLink diretamente ao destino combinável que deve mostrar o conteúdo. Quando outro app compartilha dados que correspondem ao filtro de intent, a navegação do Compose direciona o usuário diretamente para esse destino:

O navDeepLink corresponde à ação e ao tipo MIME da intent recebida para navegar até a tela de destino correta. Depois de chegar a esse destino, o gerenciador inspeciona a intent para determinar qual payload foi recebido (como uma única imagem em vez de várias) e extrai os extras correspondentes.

Processar o conteúdo recebido

Para recuperar o conteúdo entregue por um Intent, leia a atividade atual de LocalActivity.current no elemento combinável e examine a intent para determinar o que fazer em seguida. Se essa atividade puder ser iniciada em outras partes do sistema (como o inicializador), considere isso ao examinar a intent.

Tome cuidado extra ao verificar os dados recebidos: o tipo MIME errado pode ser definido ou uma imagem enviada pode ser extremamente grande. Processe dados binários ou operações de E/S pesadas (como decodificar imagens grandes ou gravar arquivos) de forma assíncrona usando corrotinas (como Dispatchers.IO) em vez da linha de execução principal da interface.

@Composable
fun SharesheetHandler() {
    val activity = LocalActivity.current
    val intent = activity?.intent

    when (intent?.action) {
        Intent.ACTION_SEND -> {
            if (intent.type == "text/plain") {
                handleSendText(intent) // Handle text being sent
            } else if (intent.type?.startsWith("image/") == true) {
                handleSendImage(intent) // Handle single image being sent
            }
        }

        Intent.ACTION_SEND_MULTIPLE -> {
            if (intent.type?.startsWith("image/") == true) {
                handleSendMultipleImages(intent) // Handle multiple images being sent
            }
        }

        else -> {
            // Handle other intents, such as being started from the home screen
        }
    }
}

private fun handleSendText(intent: Intent) {
    intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
        // Update UI state with the shared text
    }
}

private fun handleSendImage(intent: Intent) {
    val imageUri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUri?.let {
        // Update UI state with the shared image
    }
}

private fun handleSendMultipleImages(intent: Intent) {
    val imageUris =
        IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUris?.let {
        // Update UI state with the shared images
    }
}

Ao extrair dados binários ou URIs de extras de intent (como EXTRA_STREAM), use IntentCompat.getParcelableExtra() ou IntentCompat.getParcelableArrayListExtra() da biblioteca AndroidX Core, conforme mostrado nas funções handleSendImage e handleSendMultipleImages anteriores. O Android 13 (nível 33 da API) descontinua o método Intent.getParcelableExtra(String) não parametrizado em favor de métodos de tipo seguro que usam o tipo de classe esperado.

A atualização da interface após o recebimento dos dados pode ser tão simples quanto atualizar o estado para preencher um TextField ou tão complexa quanto aplicar um filtro a uma imagem. Depende do seu app o que acontece em seguida.

Compartilhamento de URL de captura de tela

Ao fazer uma captura de tela, você pode compartilhar a captura e qualquer URL associado. Isso proporciona uma experiência do usuário mais rica. Ao receber um URL, extraia o campo EXTRA_TEXT da intent, conforme mostrado no exemplo a seguir:

IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
    // Handle the EXTRA_TEXT as well
    val extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT)
    // Update UI state with the shared image and the EXTRA_TEXT if available
}

Garantir que os usuários reconheçam seu app

O app é representado pelo ícone e rótulo na Android Sharesheet e no resolvedor de intents. Ambos são definidos no manifesto. Você pode definir rótulos de atividade ou filtro de intent para fornecer mais contexto.

No Android 10 (nível 29 da API), a Sharesheet do Android usa apenas ícones definidos no manifesto na tag application. O Android ignora ícones definidos nas tags intent-filter e activity.

Receber conteúdo avançado

Embora as intents ACTION_SEND permitam o recebimento de dados da Android Sharesheet e do resolvedor de intents no nível de Activity ou Navigation, os apps também podem receber conteúdo avançado (como imagens, vídeos, arquivos de áudio e texto estilizado) por interações diretas da interface. Esses mecanismos incluem:

  • Colar da área de transferência (menu de toque e retenção)
  • Inserir mídia diretamente do teclado de software (IME), como adesivos ou GIFs
  • Arrastar e soltar conteúdo de outro app no modo de várias janelas ou tela dividida

Em interfaces baseadas em visualização, o Android 12 (nível 31 da API) e o AndroidX Core 1.7 introduzem a API OnReceiveContentListener unificada. Esse listener consolida o processamento de conteúdo da área de transferência, do teclado e de arrastar e soltar em um único callback. Para obter instruções detalhadas sobre como implementar isso em visualizações, consulte Receber conteúdo avançado.

No Jetpack Compose, é possível processar o recebimento de conteúdo avançado inserido em componentes da interface (como campos de texto) usando o Modifier.contentReceiver modificador ou modificadores de arrastar e soltar.