Enviar dados para outros apps

O Android oferece duas maneiras para os usuários compartilharem dados entre apps:

  • O Android Sharesheet foi projetado principalmente para enviar conteúdo para fora do app ou diretamente para outro usuário. Por exemplo, compartilhar um URL com um amigo.
  • O resolvedor de intents do Android é mais adequado para transmitir dados para a próxima etapa de uma tarefa bem definida. Por exemplo, abrir um PDF no app e permitir que os usuários escolham o leitor que preferirem.

Por que usar o Android Sharesheet

Figura 1. O Android Sharesheet.

Use o Android Sharesheet para criar consistência para os usuários em todos os apps. Não mostre a lista de destinos de compartilhamento do seu app nem crie suas próprias variações da Sharesheet.

O Android Sharesheet permite que os usuários compartilhem informações com a pessoa certa, com sugestões de apps relevantes, tudo com um único toque. O Sharesheet pode sugerir destinos indisponíveis para soluções personalizadas e usa uma classificação consistente. Isso ocorre porque a página de compartilhamento pode considerar informações sobre a atividade do app e do usuário que estão disponíveis apenas para o sistema.

O Android Sharesheet também conta com muitos recursos úteis para desenvolvedores. Por exemplo, é possível fazer o seguinte:

Usar o Android Sharesheet

Para todos os tipos de compartilhamento, crie uma intent e defina a ação como Intent.ACTION_SEND. Para mostrar o Android Sharesheet, chame Intent.createChooser(), transmitindo o objeto Intent. Ele retorna uma versão da intent que sempre mostra o Android Sharesheet.

Enviar conteúdo de texto

O uso mais simples e comum do Android Sharesheet é enviar conteúdo de texto de uma Activity para outra. Por exemplo, a maioria dos navegadores pode compartilhar o URL da página exibida no momento como texto com outro app. Isso é útil para compartilhar um artigo ou site com amigos por e-mail ou redes sociais. No Jetpack Compose, recupere o contexto atual usando LocalContext.current e chame context.startActivity(). Veja como fazer isso a seguir:

fun shareText(context: Context) {
    val sendIntent: Intent = Intent().apply {
        action = ACTION_SEND
        putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
        type = "text/plain"
    }

    val shareIntent = Intent.createChooser(sendIntent, null)
    context.startActivity(shareIntent)
}

Se quiser, você pode adicionar extras para incluir mais informações, como destinatários de e-mail (EXTRA_EMAIL, EXTRA_CC, EXTRA_BCC) ou o assunto do e-mail (EXTRA_SUBJECT).

Observação:alguns apps de e-mail, como o Gmail, esperam um String[] para extras como EXTRA_EMAIL e EXTRA_CC. Use putExtra(String, String[]) para adicioná-los à intent.

Enviar conteúdo binário

Compartilhe dados binários usando a ação ACTION_SEND. Defina o tipo MIME apropriado e coloque um URI para os dados no extra EXTRA_STREAM, como mostrado no exemplo a seguir. Isso é usado com frequência para compartilhar uma imagem, mas pode ser usado para compartilhar qualquer tipo de conteúdo binário.

fun shareBinaryContent(context: Context) {
    val shareIntent: Intent = Intent().apply {
        action = ACTION_SEND
        // Example: content://com.google.android.apps.photos.contentprovider/...
        val imageUri: Uri =
            Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1")
        putExtra(Intent.EXTRA_STREAM, imageUri)
        type = "image/jpeg"
    }
    context.startActivity(Intent.createChooser(shareIntent, null))
}

O aplicativo de recebimento precisa de permissão para acessar os dados para os quais o Uri aponta. Há duas maneiras recomendadas de fazer isso:

  • Armazene os dados no seu próprio ContentProvider, garantindo que outros apps tenham a permissão correta para acessar seu provedor. O mecanismo preferencial para fornecer acesso é usar permissões por URI, que são temporárias e só concedem acesso ao aplicativo receptor. Para criar um ContentProvider como esse, use a classe auxiliar FileProvider.
  • Use o sistema MediaStore. O MediaStore é principalmente para tipos MIME de vídeo, áudio e imagem. No entanto, a partir do Android 3.0 (nível 11 da API), ele também pode armazenar tipos que não são de mídia. Para mais informações, consulte MediaStore.Files. Os arquivos podem ser inseridos no MediaStore usando scanFile(). Depois disso, um Uri no estilo content:// adequado para compartilhamento é transmitido ao callback onScanCompleted() fornecido. Depois de adicionado ao MediaStore do sistema, o conteúdo pode ser acessado por qualquer app no dispositivo.

Usar o tipo MIME correto

Forneça o tipo MIME mais específico disponível para os dados que você está enviando. Por exemplo, use text/plain ao compartilhar texto simples. Veja alguns tipos MIME comuns ao enviar dados no Android:

Os destinatários 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

Para determinar o tipo MIME de forma dinâmica no momento da execução em vez de fixá-lo no código, use os seguintes métodos:

Se não for possível determinar um tipo MIME específico, use application/octet-stream para dados binários genéricos ou */* como último recurso.

Para mais informações sobre tipos MIME, consulte o registro oficial da IANA de tipos de mídia MIME.

O Android Sharesheet pode mostrar uma prévia do conteúdo, dependendo do tipo MIME fornecido. Alguns recursos em fase de pré-lançamento estão disponíveis apenas para tipos específicos.

Compartilhar vários conteúdos

Para compartilhar vários conteúdos, use a ação ACTION_SEND_MULTIPLE com uma lista de URIs que apontam para o conteúdo. O tipo MIME varia de acordo com a combinação de conteúdo que você está compartilhando. Por exemplo, se você compartilhar três imagens JPEG, use o tipo "image/jpg". Para uma mistura de tipos de imagem, use "image/*" para corresponder a uma atividade que processa qualquer tipo de imagem. Embora seja possível compartilhar uma combinação de tipos, evite fazer isso, porque não fica claro para o receptor o que você quer enviar. Se for necessário enviar vários tipos, use "*/*". Cabe ao aplicativo receptor analisar e processar seus dados. Veja um exemplo:

fun shareMultiple(context: Context) {
    val imageUris: ArrayList<Uri> = arrayListOf(
        Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/1"),
        Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/2")
    )

    val shareIntent = Intent().apply {
        action = Intent.ACTION_SEND_MULTIPLE
        putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris)
        type = "image/*"
    }
    context.startActivity(Intent.createChooser(shareIntent, null))
}

Verifique se os objetos Uri fornecidos apontam para dados que um aplicativo de recebimento pode acessar.

Adicionar conteúdo avançado às prévias de texto

No Android 10 (nível 29 da API) e versões mais recentes, o Sharesheet do Android mostra uma prévia do texto que está sendo compartilhado. Em alguns casos, o texto compartilhado pode ser difícil de entender. Imagine compartilhar um URL complicado como https://www.google.com/search?ei=2rRVXcLkJajM0PEPoLy7oA4. Uma prévia mais detalhada pode garantir aos usuários o que está sendo compartilhado.

Se você estiver visualizando um texto, poderá definir um título, uma imagem em miniatura ou ambos. Adicione uma descrição a Intent.EXTRA_TITLE antes de chamar Intent.createChooser() e adicione uma miniatura relevante usando ClipData.

Observação:o URI do conteúdo da imagem é fornecido por um FileProvider, geralmente de um <cache-path> configurado. Para mais informações, consulte Como compartilhar arquivos. Dê à Sharesheet as permissões certas para ler qualquer imagem que você queira usar como miniatura. Para mais informações, consulte Intent.FLAG_GRANT_READ_URI_PERMISSION.

Veja um exemplo:

fun richContentToTextPreviewShares(context: Context) {
    val share = Intent.createChooser(
        Intent().apply {
            action = ACTION_SEND
            putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/")

            // (Optional) Here you're setting the title of the content
            putExtra(Intent.EXTRA_TITLE, "Introducing content previews")

            // (Optional) Here you're passing a content URI to an image to be displayed
            data =
                Uri.parse("content://com.google.android.apps.photos.contentprovider/0/1/mediakey/A123456789")
            flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        },
        null
    )
    context.startActivity(share)
}

A prévia é semelhante a esta:

Figura 2. Prévia do conteúdo de texto no Android Sharesheet.

Adicionar ações personalizadas à página de compartilhamento

Figura 3. Ações personalizadas no Android Sharesheet.

No Android 14 (nível 34 da API) e versões mais recentes, os apps podem adicionar ações personalizadas ao Sharesheet do Android. As ações personalizadas são mostradas como pequenos ícones de ação na parte de cima do Android Sharesheet, e os apps podem especificar qualquer Intent como a ação invocada quando o ícone é clicado.

Para adicionar ações personalizadas ao Android Sharesheet, primeiro crie um ChooserAction com ChooserAction.Builder. É possível especificar um PendingIntent como a ação invocada quando o ícone é clicado. Crie uma matriz com todas as suas ações personalizadas e especifique-a como EXTRA_CHOOSER_CUSTOM_ACTIONS da Intent de compartilhamento.

fun sharesheetCustomActions(context: Context, previewText: String) {
    val sendIntent = Intent(ACTION_SEND)
        .setType("text/plain")
        .putExtra(Intent.EXTRA_TEXT, previewText)
    val shareIntent = Intent.createChooser(sendIntent, null)
    val customActions = arrayOf(
        ChooserAction.Builder(
            Icon.createWithResource(context, R.drawable.ic_logo),
            "Custom",
            PendingIntent.getBroadcast(
                context,
                1,
                Intent(Intent.ACTION_VIEW),
                PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT
            )
        ).build()
    )
    shareIntent.putExtra(Intent.EXTRA_CHOOSER_CUSTOM_ACTIONS, customActions)
    context.startActivity(shareIntent)
}

Adicionar segmentações personalizadas

O Android Sharesheet permite especificar até duas intents de atividade personalizadas que são listadas antes das sugestões de apps usando Intent.EXTRA_INITIAL_INTENTS. Para destinos de compartilhamento direto (como conversas ou contatos), publique atalhos dinâmicos usando ShortcutManagerCompat (consulte Fornecer destinos de compartilhamento direto):

Figura 4. Destinos personalizados na página de compartilhamento do Android.

Adicione Intent.EXTRA_INITIAL_INTENTS à sua intent de compartilhamento depois de chamar Intent.createChooser():

val sendIntent = Intent(ACTION_SEND).apply {
    type = "text/plain"
    putExtra(Intent.EXTRA_TEXT, previewText)
}

val customIntent = Intent().apply {
    component = ComponentName(context.packageName, "${context.packageName}.CustomActivity")
}

val shareIntent = Intent.createChooser(sendIntent, null).apply {
    putExtra(
        Intent.EXTRA_INITIAL_INTENTS,
        arrayOf(customIntent)
    )
}
context.startActivity(shareIntent)

Use esse recurso com cuidado. Cada Intent personalizado que você adiciona reduz o número sugerido pelo sistema. Em geral, evite adicionar segmentação personalizada. Um exemplo comum de adição de Intent.EXTRA_INITIAL_INTENTS é fornecer outras ações que os usuários podem realizar no conteúdo compartilhado. Por exemplo, um usuário compartilha imagens, e o Intent.EXTRA_INITIAL_INTENTS é usado para permitir que ele envie um link.

Excluir destinos específicos por componente

É possível excluir destinos específicos fornecendo Intent.EXTRA_EXCLUDE_COMPONENTS. Faça isso apenas para remover destinos que você controla. Um caso de uso comum é ocultar os destinos de compartilhamento do app quando os usuários compartilham de dentro do app, já que a intenção deles provavelmente é compartilhar fora do app.

Adicione Intent.EXTRA_EXCLUDE_COMPONENTS à intent depois de chamar Intent.createChooser():

fun excludeSpecificTargets(context: Context) {
    val share = Intent.createChooser(Intent(ACTION_SEND), null).apply {
        // Only use for components you have control over
        val excludedComponentNames =
            arrayOf(ComponentName("com.example.android", "ExampleClass"))
        putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames)
    }
    context.startActivity(share)
}

Receber informações sobre o compartilhamento

Pode ser útil saber quando os usuários estão compartilhando e qual destino eles selecionam. A Android Sharesheet permite que você receba essas informações fornecendo o ComponentName dos destinos que os usuários selecionam usando um IntentSender.

Primeiro, crie um PendingIntent para um BroadcastReceiver e forneça o IntentSender em Intent.createChooser():

fun infoAboutSharing(context: Context, requestCode: Int) {
    var share = Intent(ACTION_SEND)
    // ...
    val pi = PendingIntent.getBroadcast(
        context, requestCode,
        Intent(context, ShareBroadcastReceiver::class.java),
        PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
    )
    share = Intent.createChooser(share, null, pi.intentSender)
    context.startActivity(share)
}

Receba o callback em MyBroadcastReceiver e procure em Intent.EXTRA_CHOOSER_RESULT:

override fun onReceive(context: Context?, intent: Intent) {
    val TAG = ShareBroadcastReceiver::class.simpleName
    val chooserResult: ChooserResult? = IntentCompat.getParcelableExtra(
        intent,
        Intent.EXTRA_CHOOSER_RESULT,
        ChooserResult::class.java,
    )
    chooserResult?.let {
        Log.i(TAG,
            "Share callback: isShortcut: ${it.isShortcut}, type: ${typeToString(it.type)}, componentName: ${it.selectedComponent}",
        )
    } ?: Log.i(TAG, "chooserResult is null")
}

Para mais informações, consulte o exemplo de compartilhamento de plataforma.

Usar o resolvedor de intents do Android

Figura 5. O ACTION_SEND resolvedor de intents.

O resolvedor de intents do Android é mais adequado para enviar dados para outro app como parte de um fluxo de tarefas bem definido.

Para usar o resolvedor de intents do Android, crie uma intent e adicione extras como faria para chamar o Android Sharesheet. No entanto, não chame Intent.createChooser().

Se houver vários aplicativos instalados com filtros que correspondam a ACTION_SEND e ao tipo MIME, o sistema vai mostrar uma caixa de diálogo de desambiguação chamada resolvedor de intents, que permite ao usuário escolher um destino para o compartilhamento. Se um único aplicativo corresponder, ele será executado.

Veja um exemplo de como usar o resolvedor de intents do Android para enviar texto:

fun intentResolver(context: Context) {
    val sendIntent: Intent = Intent().apply {
        action = ACTION_SEND
        putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
        type = "text/plain"
    }
    context.startActivity(sendIntent)
}

Saiba mais

Para mais informações sobre o envio de dados, consulte Intents e filtros de intents.