Os usuários adoram imagens, vídeos e outros conteúdos expressivos, mas inserir e mover esse conteúdo em apps nem sempre é fácil. Para que os apps possam receber conteúdo avançado, 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.
Você pode anexar uma interface, como
OnReceiveContentListener
,
componentes de IU e receber um retorno de chamada quando o conteúdo for inserido por meio de
mecanismo de atenção. 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 oferecer compatibilidade com versões anteriores do Android, essa API também é disponíveis no AndroidX, a partir da Core 1.7 e AppCompat 1.4, que recomendamos usar ao implementar essa funcionalidade.
Visão geral
Com outras APIs existentes, cada mecanismo de interface do usuário, como as APIs de toque e menu suspenso ou 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 formas de inserir conteúdo são adicionadas plataforma, não é preciso fazer outras alterações no código para ativar o suporte no seu app. Caso seu aplicativo precise implementar personalização completa para um caso de uso específico, você ainda poderá usar as APIs 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 os o app pode lidar com:
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) { Pair<ContentInfoCompat, ContentInfoCompat> split = 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; } }
Caso seu app já seja compatível com o compartilhamento com intents, você poderá reutilizar o lógica específica do app para lidar com 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 qualquer
URIs de conteúdo na
payload transmitido para OnReceiveContentListener
.
Normalmente, o app processa URIs de conteúdo em um serviço ou uma atividade. Para
processamento de longa duração, use
WorkManager Ao implementar
estenda as permissões para o serviço ou a atividade de destino passando o
conteúdo usando
Intent.setClipData
e defina a sinalização.
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, você deve manter uma referência ao
Objeto payload
recebido pelo listener para ajudar a garantir que as permissões não sejam
revogados prematuramente pela plataforma.
Visualizações padrão
Caso seu app use uma subclasse View
personalizada, verifique se a propriedade
OnReceiveContentListener
não é ignorado.
Se a classe View
substituir o método
onCreateInputConnection
,
use a API Jetpack
InputConnectionCompat.createWrapper
para configurar a InputConnection
.
Se a classe View
substituir a
onTextContextMenuItem
, delegue para "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 colando com o toque em & menu suspenso | Não | Sim |
Inserir usando o recurso de arrastar e soltar | Não | Sim (API de nível 24 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 colando com o toque em & menu suspenso | Não | |
Inserir conteúdo usando o recurso de arrastar e soltar | Não |