Os usuários adoram imagens, vídeos e outros conteúdos expressivos, mas inserir e mover esses conteúdos em apps nem sempre é fácil. Para facilitar o recebimento de conteúdo avançado pelos apps, o Android 12 (nível 31 da API) introduz uma API unificada que permite que o app aceite conteúdo de qualquer fonte: área de transferência, teclado ou ação de arrastar.
É possível anexar uma interface, como
OnReceiveContentListener
,
a componentes de interface e receber um callback quando o conteúdo for inserido usando qualquer
mecanismo. O callback passa a ser o único local em que o código processa
o recebimento de todos os conteúdos, desde textos simples e estilizados até marcações, imagens, vídeos,
arquivos de áudio e outros.
Para compatibilidade com versões anteriores do Android, essa API também está disponível no AndroidX, a partir do Core 1.7 e da AppCompat 1.4, que recomendamos que você use ao implementar essa funcionalidade.
Informações gerais
Com outras APIs já existentes, cada mecanismo de interface, como o menu de tocar e pressionar ou de arrastar, tem a própria API correspondente. Isso significa que você precisa integrar cada API separadamente, adicionando um código semelhante para cada mecanismo que insere conteúdo:
A API OnReceiveContentListener
unificada consolida esses diferentes caminhos de código,
criando uma única API para implementação. Assim, você pode se concentrar na lógica
específica do app e deixar a plataforma cuidar do restante:
Essa abordagem também significa que, quando novas maneiras de inserir conteúdo forem adicionadas à plataforma, não será necessário fazer outras mudanças no código para ativar o suporte ao seu app. Se o app precisar implementar uma personalização completa para um caso de uso específico, você ainda poderá usar as APIs já existentes, que continuam funcionando da mesma forma.
Implementação
A API é uma interface de listener com um único método, o
OnReceiveContentListener
.
Para oferecer compatibilidade com versões anteriores da plataforma Android, recomendamos o uso
da interface
OnReceiveContentListener
correspondente na biblioteca AndroidX Core.
Para usar a API, implemente o listener especificando os tipos de conteúdo que o app pode processar:
Kotlin
object MyReceiver : OnReceiveContentListener { val MIME_TYPES = arrayOf("image/*", "video/*") // ... override fun onReceiveContent(view: View, payload: ContentInfoCompat): ContentInfoCompat? { TODO("Not yet implemented") } }
Java
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; // ... }
Depois de especificar todos os tipos MIME de conteúdo compatíveis com o app, implemente o restante do listener:
Kotlin
class MyReceiver : OnReceiveContentListener { override fun onReceiveContent(view: View, contentInfo: ContentInfoCompat): ContentInfoCompat { val split = contentInfo.partition { item: ClipData.Item -> item.uri != null } val uriContent = split.first val remaining = split.second if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining } companion object { val MIME_TYPES = arrayOf("image/*", "video/*") } }
Java
public class MyReceiver implements OnReceiveContentListener { public static final String[] MIME_TYPES = new String[] {"image/*", "video/*"}; @Override public ContentInfoCompat onReceiveContent(View view, ContentInfoCompat contentInfo) { Pairsplit = contentInfo.partition( item -> item.getUri() != null); ContentInfo uriContent = split.first; ContentInfo remaining = split.second; if (uriContent != null) { // App-specific logic to handle the URI(s) in uriContent. } // Return anything that your app didn't handle. This preserves the // default platform behavior for text and anything else that you aren't // implementing custom handling for. return remaining; } }
Se o app já oferece suporte ao compartilhamento com intents, você pode reutilizar a lógica específica do app para processar URIs de conteúdo. Retorne todos os dados restantes para delegar o processamento desses dados à plataforma.
Depois de implementar o listener, defina-o nos elementos de IU adequados no app:
Kotlin
class MyActivity : Activity() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... val myInput = findViewById(R.id.my_input) ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, MyReceiver()) } }
Java
public class MyActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { // ... AppCompatEditText myInput = findViewById(R.id.my_input); ViewCompat.setOnReceiveContentListener(myInput, MyReceiver.MIME_TYPES, new MyReceiver()); } }
Permissões de URI
As permissões de leitura são concedidas e liberadas automaticamente pela plataforma para todos os
URIs de conteúdo no
payload transmitido ao OnReceiveContentListener
.
Normalmente, o app processa URIs de conteúdo em um serviço ou uma atividade. Para
processamento de longa duração, use o
WorkManager. Ao implementar
isso, estenda as permissões ao serviço ou à atividade de destino transmitindo o
conteúdo usando
Intent.setClipData
e definindo a flag
FLAG_GRANT_READ_URI_PERMISSION
.
Como alternativa, você pode usar uma linha de execução em segundo plano no contexto atual para
processar o conteúdo. Nesse caso, é necessário manter uma referência ao
objeto payload
recebido pelo listener para ajudar a garantir que as permissões não sejam
revogadas prematuramente pela plataforma.
Visualizações padrão
Caso seu app use uma subclasse View
personalizada, verifique se a
OnReceiveContentListener
não é ignorada.
Se a classe View
substituir o método
onCreateInputConnection
,
use a API Jetpack
InputConnectionCompat.createWrapper
para configurar a InputConnection
.
Se a classe View
substituir o método
onTextContextMenuItem
, delegue a Super quando o item de menu for
R.id.paste
ou
R.id.pasteAsPlainText
.
Comparação com a API de imagem de teclado
Pense na API OnReceiveContentListener
como a próxima versão da
API de imagem do teclado existente. Essa API
unificada é compatível com a funcionalidade da API de imagem do teclado e com alguns
outros recursos. A compatibilidade com dispositivos e recursos varia de acordo com o uso
da biblioteca do Jetpack ou das APIs nativas do SDK do Android.
Ação ou recurso | Compatível com a API de imagem do teclado | Compatível com a API unificada |
---|---|---|
Inserir conteúdo pelo teclado | Sim (nível 13 da API e versões mais recentes) | Sim (nível 13 da API e versões mais recentes) |
Inserir usando "Colar" do menu "Tocar e manter pressionado" | Não | Sim |
Inserir usando o recurso de arrastar e soltar | Não | Sim (nível 24 da API e versões mais recentes) |
Ação ou recurso | Compatível com a API de imagem do teclado | Compatível com a API unificada |
---|---|---|
Inserir conteúdo pelo teclado | Sim (nível 25 da API e versões mais recentes) | Sim (Android 12 ou versões mais recentes) |
Inserir usando "Colar" do menu "Tocar e manter pressionado" | Não | |
Inserir conteúdo usando o recurso de arrastar e soltar | Não |