A plataforma Android 12 inclui mudanças de comportamento que podem
afetar seu app. As mudanças de comportamento a seguir se aplicam a todos os apps quando
executados no Android 12, independentemente da targetSdkVersion
. Teste
seu app e modifique-o conforme necessário para ficar compatível com essas mudanças, quando
aplicável.
Consulte também a lista de mudanças de comportamento que afetam apenas os apps destinados ao Android 12.
Experiência do usuário
Efeito de rolagem esticada
Em dispositivos com o Android 12 e mais recentes, o comportamento visual dos eventos de rolagem mudou.
No Android 11 e anteriores, um evento de rolagem esticada faz com que os elementos visuais tenham um brilho. No Android 12 e mais recentes, os elementos visuais se esticam e voltam ao normal durante um evento de arrastar, e deslizam de volta ao normal em um evento de deslizamento rápido.
Para ver mais informações, consulte o guia sobre animação de gestos de rolagem.
Telas de apresentação do app
Caso você já tenha implementado uma tela de apresentação personalizada no Android 11 ou
versões anteriores, será necessário migrar o app para a API SplashScreen
a fim de garantir que a tela
seja exibida corretamente a partir do Android 12. Se o app não for migrado, ele terá
uma experiência de inicialização prejudicada ou não intencional.
Veja instruções em Migrar a implementação da tela de apresentação existente para o Android 12.
A partir do Android 12, o sistema sempre aplica a nova tela de apresentação
padrão do sistema Android em
inicializações a frio e
lentas para todos os apps.
Por padrão, a tela de apresentação padrão do sistema é construída usando o elemento de ícone
da tela de início do app e o
windowBackground
do
tema, se ele tiver uma única cor.
Para mais detalhes, consulte o guia do desenvolvedor sobre telas de apresentação.
Resolução de intents da Web
Com o Android 12 (nível 31 da API), intents da Web genéricas são resolvida como uma atividade no app apenas se ele for aprovado para o domínio específico contido na intent. Se o app não for aprovado para o domínio, a intent da Web será resolvida no app de navegação padrão do usuário.
Os apps podem receber essa aprovação de uma destas maneiras:
Verifique o domínio usando Links do app Android.
Em apps direcionados ao Android 12 ou mais recentes, o sistema muda a forma como ele verifica automaticamente os Links do app Android para seu app. Nos filtros de intent do app, verifique se você incluiu a categoria
BROWSABLE
e ofereça suporte ao esquemahttps
.No Android 12 ou mais recente, é possível verificar manualmente os Links do app Android para seu app a fim de testar como essa lógica atualizada o afeta.
Peça ao usuário para associar seu app ao domínio nas configurações do sistema.
Se o app invocar intents da Web, considere adicionar um prompt ou uma caixa de diálogo que pede ao usuário para confirmar a ação.
Melhorias no modo imersivo para navegação por gestos
O Android 12 consolida o comportamento já existente para facilitar a execução de comandos de navegação por gestos no modo imersivo. Além disso, o Android 12 oferece comportamento de compatibilidade com versões anteriores para o modo imersivo fixo.
Display#getRealSize e getRealMetrics: descontinuação e restrições
Os dispositivos Android estão disponíveis em vários formatos, como telas
grandes, tablets e dobráveis. Para renderizar conteúdo corretamente em cada
dispositivo, o app precisa determinar o tamanho da tela ou da exibição. Com
o tempo, o Android forneceu APIs diferentes para extrair essas informações. No Android
11, introduzimos a API WindowMetrics
e descontinuamos estes métodos:
No Android 12, continuamos a recomendar o uso da WindowMetrics
e
descontinuamos estes métodos:
A fim de mitigar o comportamento dos apps que usam APIs Display para extrair os
limites do app, o Android 12 restringe os valores retornados pelas APIs
para apps que não são totalmente redimensionáveis. Isso pode afetar os
apps que usam essas informações com MediaProjection
.
Os apps precisam usar as APIs WindowMetrics
para consultar os limites da
janela e Configuration.densityDpi
para consultar a densidade atual.
Para oferecer compatibilidade com versões mais antigas do Android, use a
biblioteca WindowManager
do Jetpack, que
inclui uma classe WindowMetrics
compatível com o Android 4.0 (nível 14 da API) e versões mais recentes.
Exemplos de como usar a WindowMetrics
Primeiro, confira se as atividades do seu app são totalmente redimensionáveis.
Uma atividade precisa depender das WindowMetrics
de um contexto de atividade para qualquer
trabalho relacionado à IU, especialmente
WindowManager.getCurrentWindowMetrics()
ou
WindowMetricsCalculator.computeCurrentWindowMetrics()
.
Se o app criar uma MediaProjection
, os limites precisarão ser dimensionados corretamente,
já que a projeção captura a partição de exibição na qual o app projetor
está sendo executado.
Se o app for totalmente redimensionável, o contexto da atividade retornará os limites corretos, como em:
Kotlin
val projectionMetrics: WindowMetrics = activityContext .getSystemService(WindowManager::class.java).maximumWindowMetrics
Java
WindowMetrics projectionMetrics = activityContext .getSystemService(WindowManager.class).getMaximumWindowMetrics();
Se o app não for totalmente redimensionável, ele precisará consultar uma instância do WindowContext
e extrair as WindowMetrics
dos limites de atividade usando o
WindowManager.getMaximumWindowMetrics()
ou o método do Jetpack
WindowMetricsCalculator.computeMaximumWindowMetrics()
.
Kotlin
val windowContext = context.createWindowContext(mContext.display!!, WindowManager.LayoutParams.TYPE_APPLICATION, null) val projectionMetrics = windowContext.getSystemService(WindowManager::class.java) .maximumWindowMetrics
Java
Context windowContext = context.createWindowContext(mContext.getDisplay(), WindowManager.LayoutParams.TYPE_APPLICATION, null); WindowMetrics projectionMetrics = windowContext.getSystemService(WindowManager.class) .getMaximumWindowMetrics();
Todos os apps no modo de várias janelas
O Android 12 usa o modo de várias janelas como o comportamento padrão.
Em telas grandes (maiores ou iguais a 600dp), a plataforma oferece suporte a todos os apps no
modo de várias janelas, independente da configuração do app. Se a definição for
resizeableActivity="false"
,
o app será colocado no modo de compatibilidade quando necessário para acomodar as dimensões de
exibição.
Em telas pequenas (com menos de 600dp), o sistema verifica a
minWidth
e a
minHeight
de uma atividade para determinar se ela pode ser executada no modo de várias janelas. Se a definição for
resizeableActivity="false"
,
o app não poderá ser executado no modo de várias janelas, independente da
largura e altura mínimas.
Para mais informações, consulte suporte a várias janelas.
Visualização da câmera em telas grandes
Os apps de câmera geralmente presumem uma relação fixa entre a orientação do dispositivo e a proporção da visualização da câmera. No entanto, formatos de telas grandes, como dispositivos dobráveis, e modos de exibição, como várias janelas e várias telas, não seguem essa suposição.
No Android 12, os apps de câmera que solicitam uma orientação específica da tela
e não são redimensionáveis (resizeableActivity="false"
) entram automaticamente
no modo retrato inserido, o que garante a orientação e a proporção
corretas da visualização da câmera. Em dobráveis e outros dispositivos que têm uma camada
de abstração de hardware (HAL) da câmera,
a rotação extra é aplicada à saída da câmera para compensar a orientação do sensor
da câmera, e a saída da câmera será cortada para corresponder à proporção
da visualização do app da câmera. O corte e a rotação extra garantem uma apresentação
adequada da visualização da câmera, independente da orientação e do estado dobrado
ou desdobrado do dispositivo.
Atraso na UX para notificações de serviços em primeiro plano
Para oferecer uma experiência simplificada a serviços em primeiro plano de curta duração, os dispositivos com o Android 12 ou mais recentes podem atrasar a exibição de notificações de serviço em primeiro plano por 10 segundos, com algumas exceções. Essa mudança possibilita que as tarefas de curta duração sejam concluídas antes que as notificações sejam exibidas.
Desempenho
Bucket restrito para apps em espera
O Android 11 (nível 30 da API) introduziu o bucket restrito como um bucket para apps em espera. A partir do Android 12, esse bucket é ativado por padrão. O bucket restrito tem a prioridade mais baixa e as restrições mais altas de todos os buckets. Os buckets em ordem de prioridade da mais alta para a mais baixa são:
- Ativo: o app está sendo usado ou foi usado recentemente.
- Grupo de trabalho: o app está em uso regular.
- Frequente: o app costuma ser usado, mas não todos os dias.
- Raro: o app não é usado com frequência.
- Restrito: o app consome uma grande quantidade de recursos do sistema ou pode apresentar comportamento indesejado.
O sistema considera o comportamento do app, além dos padrões de uso, para decidir se ele será colocado no bucket restrito.
Seu app terá menos probabilidade de ser colocado no bucket restrito se usar os recursos do sistema com mais responsabilidade. O sistema colocará o app em um bucket menos restrito se o usuário interagir diretamente com ele.
Conferir se o app está no bucket restrito
Para conferir se o sistema colocou o app no bucket restrito, chame
getAppStandbyBucket()
.
Se o valor de retorno desse método for STANDBY_BUCKET_RESTRICTED
, significa que o app
está no bucket restrito.
Testar o comportamento do bucket restrito
Para testar como o app se comporta quando o sistema o coloca no bucket restrito, mova o app manualmente para esse bucket. Para fazer isso, execute o comando abaixo em uma janela de terminal:
adb shell am set-standby-bucket PACKAGE_NAME restricted
Segurança e privacidade
Local aproximado
Em dispositivos com o Android 12 ou versões mais recentes, os usuários podem solicitar que o app tenha acesso apenas a informações de local aproximado.
Se o app solicitar a permissão de execução
ACCESS_FINE_LOCATION
,
também vai ser necessário solicitar a permissão
ACCESS_COARSE_LOCATION
para processar casos em que o usuário concede acesso apenas ao
local aproximado. Inclua as duas permissões em uma única solicitação de
execução.
A caixa de diálogo de permissões do sistema inclui as opções abaixo para o usuário, conforme mostrado na Figura 1:
- Exato: fornece acesso a informações de local exato.
- Aproximado: fornece acesso apenas a informações de local aproximado.
Desativação do microfone e da câmera
Em dispositivos com suporte ao Android 12 ou mais recentes, os usuários podem ativar e desativar o acesso à câmera e ao microfone para todos os apps pressionando uma única opção de alternância. Os usuários podem acessar as opções de alternância nas Configurações rápidas, como mostrado na Figura 1, ou na Tela de privacidade nas configurações do sistema.
Saiba mais sobre essas opções de
alternância e como verificar
se o app segue as práticas recomendadas em relação às
permissões
CAMERA
e
RECORD_AUDIO
.
Indicadores de microfone e câmera
Em dispositivos com o Android 12, quando um app acessa o microfone ou a câmera, um ícone é exibido na barra de status.
Saiba mais sobre esses
indicadores e como
verificar se o app segue as práticas recomendadas em relação às
permissões
CAMERA
e
RECORD_AUDIO
.
Visibilidade do pacote de permissões
Em dispositivos com o Android 12 ou mais recentes, os apps direcionados ao Android 11 (nível 30 da API) ou mais recentes e que chamam um dos métodos abaixo recebem um conjunto filtrado de resultados, com base na visibilidade do pacote do app:
Remoção das implementações do Bouncy Castle
O Android 12 remove muitas implementações do BouncyCastle (link em inglês) de algoritmos criptográficos que foram descontinuados, incluindo todos os algoritmos AES. Em vez disso, o sistema usa as implementações Conscrypt (link em inglês) desses algoritmos.
Essa mudança afetará o app se alguma das condições a seguir for verdadeira:
- O app usa tamanhos de chave de 512 bits. O Conscrypt não é compatível com esse tamanho de chave. Se necessário, atualize a lógica de criptografia do app para usar tamanhos de chave diferentes.
O app usa tamanhos de chave inválidos com o
KeyGenerator
. A implementação do Conscrypt doKeyGenerator
executa outras validações em parâmetros de chave, em comparação com o BouncyCastle. Por exemplo, o Conscrypt não permite que o app gere uma chave AES de 64 bits porque o AES é compatível apenas com chaves de 128, 192 e 256 bits.O BouncyCastle possiblita gerar chaves de tamanhos inválidos, mas isso falhará mais tarde se elas forem usadas com uma
Cipher
. O Conscrypt falha antes.As criptografias dos modos Galois/Counter (GCM, na sigla em inglês) são inicializadas usando um tamanho diferente de 12 bytes. A implementação da
GcmParameterSpec
do Conscrypt exige uma inicialização de 12 bytes, de acordo com o recomendado pela NIST.
Notificações de acesso à área de transferência
No Android 12 e mais recentes, quando um app chama o método
getPrimaryClip()
para acessar dados da área de transferência de um app
diferente pela primeira vez, uma mensagem
de aviso notifica o usuário sobre o acesso.
O texto da mensagem de aviso contém este formato:
APP pasted from your clipboard.
Informações sobre texto na descrição do clipe
No Android 12 e mais recentes, o método getPrimaryClipDescription()
pode
detectar estes detalhes:
- Texto estilizado usando
isStyledText()
. - Classificações diferentes de texto, como URLs, usando
getConfidenceScore()
.
Apps não podem fechar caixas de diálogo do sistema
Para melhorar o controle do usuário ao interagir com apps e com o sistema, a
ação da intent ACTION_CLOSE_SYSTEM_DIALOGS
foi suspensa a partir do Android 12. Com a exceção de
alguns casos específicos, quando seu app tenta invocar
uma intent que contém essa ação, o
sistema realiza uma das ações abaixo, com base na versão do SDK de destino do app:
- Se o app for direcionado ao Android 12 ou mais recentes,
ocorrerá uma
SecurityException
. Se o app for destinado ao Android 11 (nível 30 da API) ou versões anteriores, a intent não será executada e a mensagem a seguir será exibida no Logcat:
E ActivityTaskManager Permission Denial: \ android.intent.action.CLOSE_SYSTEM_DIALOGS broadcast from \ com.package.name requires android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, \ dropping broadcast.
Exceções
O app ainda pode fechar caixas de diálogo do sistema no Android 12 ou mais recentes:
- O app está executando um teste de instrumentação.
O app é destinado ao Android 11 ou versões anteriores e está exibindo uma janela que sobrepõe a gaveta de notificações.
O app é destinado ao Android 11 ou versões anteriores. Além disso, o usuário interagiu com uma notificação, possivelmente usando os botões de ação da notificação, e o app está processando um serviço ou broadcast receiver em resposta à ação do usuário.
O app é destinado ao Android 11 ou versões anteriores e tem um serviço de acessibilidade ativo. Se o app for direcionado ao Android 12 e quiser fechar a barra de notificações, use a ação de acessibilidade
GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE
.
Eventos de toque não confiáveis estão bloqueados
Para preservar a segurança do sistema e uma boa experiência do usuário, o Android 12 impede que os apps consumam eventos de toque em que uma sobreposição oculte o app de forma não segura. Em outras palavras, o sistema bloqueia toques que são transmitidos por determinadas janelas, com algumas exceções.
Apps afetados
Essa mudança afeta os apps que optam por permitir que toques sejam transmitidos pelas janelas,
por exemplo, usando a
sinalização
FLAG_NOT_TOUCHABLE
. Alguns exemplos incluem os seguintes:
- Sobreposições que exigem
a permissão
SYSTEM_ALERT_WINDOW
, como janelas que usamTYPE_APPLICATION_OVERLAY
e a sinalizaçãoFLAG_NOT_TOUCHABLE
. - Janelas de atividade que usam a sinalização
FLAG_NOT_TOUCHABLE
.
Exceções
Os toques de transmissão são permitidos nos seguintes casos:
- Interações dentro do app. O app exibe a sobreposição, que aparece somente quando o usuário está interagindo com o próprio app.
Janelas confiáveis. Essas janelas incluem, entre outras:
Janelas invisíveis. A visualização raiz da janela é
GONE
ouINVISIBLE
.Janelas totalmente transparentes. A propriedade
alpha
da janela é 0.0.Janelas de alerta do sistema translúcidas o suficiente. O sistema considera que um conjunto de janelas de alerta do sistema é translúcido o suficiente quando a opacidade combinada é menor ou igual à opacidade máxima de ofuscação para toques. No Android 12, essa opacidade máxima é 0,8 por padrão.
Detectar quando um toque não confiável está bloqueado
Se uma ação de toque for bloqueada pelo sistema, o Logcat registrará a seguinte mensagem:
Untrusted touch due to occlusion by PACKAGE_NAME
Testar a mudança
Os toques não confiáveis são bloqueados por padrão em dispositivos com o Android 12 ou mais recentes. Para permitir toques não confiáveis, execute o comando ADB abaixo em uma janela de terminal:
# A specific app adb shell am compat disable BLOCK_UNTRUSTED_TOUCHES com.example.app # All apps # If you'd still like to see a Logcat message warning when a touch would be # blocked, use 1 instead of 0. adb shell settings put global block_untrusted_touches 0
Para reverter o comportamento para o padrão (toques não confiáveis bloqueados), execute o comando abaixo:
# A specific app adb shell am compat reset BLOCK_UNTRUSTED_TOUCHES com.example.app # All apps adb shell settings put global block_untrusted_touches 2
Ciclo de vida da atividade
As atividades raiz da tela de início não são mais concluídas ao pressionar o botão "Voltar"
O Android 12 muda o gerenciamento padrão das atividades da tela de início quando o botão "Voltar" do sistema é pressionado na raiz das tarefas. Nas versões anteriores, o sistema concluía essas atividades ao pressionaro botão "Voltar". No Android 12, o sistema agora move a atividade e a tarefa para o segundo plano em vez de concluir a atividade. O novo comportamento corresponde ao comportamento atual ao sair de um app usando o botão "Página inicial" ou o gesto.
Para a maioria dos apps, essa mudança significa que os usuários que usam a opção "Voltar" para sair do app podem retomar o app mais rapidamente em um estado quente, em vez de precisar o reiniciar completamente de um estado frio.
Recomendamos testar seus apps com essa mudança. Caso seu app modifique
onBackPressed()
para processar a
navegação de retorno e concluir a Activity
, atualize a implementação para chamar o método
super.onBackPressed()
, em vez de finalizar a atividade. Chamar
super.onBackPressed()
move a atividade e a tarefa para o segundo plano, quando
adequado, e oferece uma experiência de navegação mais consistente aos usuários
em todos os apps.
Observe também que, em geral, recomendamos usar as APIs de atividade do AndroidX para
fornecer navegação de retorno personalizada,
em vez de modificar onBackPressed()
. As APIs Activity do AndroidX
adiam automaticamente o comportamento adequado do sistema se não houver
componentes que interceptem o pressionamento do botão "Voltar" do sistema.
Gráficos e imagens
Melhorias na alternância da taxa de atualização
No Android 12, mudanças na taxa de atualização usando
setFrameRate()
podem acontecer se a tela for compatível com uma transição uniforme para
a nova taxa de atualização. Uma transição uniforme é aquela que não apresenta interrupções
visuais, como uma tela preta por um ou dois segundos. Anteriormente, se a
tela não tivesse suporte a transições uniformes, ela continuaria usando
a mesma taxa de atualização após chamar setFrameRate()
. É possível determinar com
antecedência se a transição para a nova atualização será contínua
chamando o método getAlternativeRefreshRates()
.
Geralmente, o callback onDisplayChanged()
é chamado após a taxa de atualização mudar, mas para algumas
telas conectadas externamente, ele é chamado durante uma transição uniforme.
Veja um exemplo de como implementar isso:
Kotlin
// Determine whether the transition will be seamless. // Non-seamless transitions may cause a 1-2 second black screen. val refreshRates = this.display?.mode?.alternativeRefreshRates val willBeSeamless = Arrays.asList<FloatArray>(refreshRates).contains(newRefreshRate) // Set the frame rate even if the transition will not be seamless. surface.setFrameRate(newRefreshRate, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS)
Java
// Determine whether the transition will be seamless. // Non-seamless transitions may cause a 1-2 second black screen. Display display = context.getDisplay(); // API 30+ Display.Mode mode = display.getMode(); float[] refreshRates = mode.getAlternativeRefreshRates(); boolean willBeSeamless = Arrays.asList(refreshRates).contains(newRefreshRate); // Set the frame rate even if the transition will not be seamless. surface.setFrameRate(newRefreshRate, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS);
Conectividade
Atualizações do Passpoint
As APIs a seguir foram adicionadas ao Android 12:
isPasspointTermsAndConditionsSupported()
: os Termos e Condições são um recurso do Passpoint que possibilita que as implantações de rede substituam o portal cativo não seguro, que usa redes abertas, por uma rede do Passpoint segura. O usuário recebe uma notificação quando ele for solicitado a aceitar os Termos e Condições. Os apps que sugerem redes de Passpoint controladas por Termos e Condições, precisam chamar essa API primeiro para ter certeza de que o dispositivo é compatível com a funcionalidade. Se o dispositivo não for compatível com o recurso, ele não poderá se conectar a essa rede, e será necessário sugerir uma rede alternativa ou legada.isDecoratedIdentitySupported()
: ao autenticar em redes com uma decoração prefixada, o prefixo de identidade decorado possibilita que os operadores de rede atualizem o identificador de acesso à rede (NAI, na sigla em inglês) para executar o roteamento explícito usando vários proxies dentro de uma rede AAA. Consulte RFC 7542 (link em inglês) para saber mais sobre isso.O Android 12 implementa esse recurso para estar em conformidade com as especificações da WBA para extensões PPS-MO (link em inglês). Os apps que sugerem redes do Passpoint que exigem uma identidade decorada, precisam chamar essa API primeiro para garantir que dispositivo é compatível com a funcionalidade. Se o dispositivo não for compatível com o recurso, a identidade não será decorada e a autenticação na rede pode falhar.
Para criar uma sugestão de Passpoint, os apps precisam usar as classes
PasspointConfiguration
,
Credential
e HomeSp
. Essas
classes descrevem o perfil do Passpoint, definido na especificação do Passpoint
do Wi-Fi
Alliance (em inglês).
Para mais informações, consulte API de sugestão de Wi-Fi para conectividade com a Internet.
Atualização das restrições da interface não SDK
O Android 12 inclui listas atualizadas de interfaces não SDK restritas com base na colaboração de desenvolvedores do Android e nos testes internos mais recentes. Antes de restringirmos interfaces não SDK, sempre que possível, garantimos que haja alternativas públicas disponíveis.
Caso seu app não seja destinado ao Android 12, é possível que algumas dessas mudanças não afetem você imediatamente. No entanto, embora atualmente seja possível usar algumas interfaces não SDK (dependendo do nível da API de destino do app), o uso de qualquer método ou campo não SDK sempre apresenta um alto risco de corromper o app.
Se você não sabe se o app usa interfaces não SDK, é possível testá-lo para descobrir. Se ele depende de interfaces não SDK, planeje uma migração para alternativas SDK. No entanto, entendemos que alguns apps têm casos de uso válidos para interfaces não SDK. Caso você não encontre uma alternativa para deixar de usar uma interface não SDK em um recurso no app, solicite uma nova API pública.
Para saber mais sobre as mudanças dessa versão do Android, consulte Atualizações para restrições de interfaces não SDK no Android 12. Para saber mais sobre interfaces não SDK em geral, consulte Restrições para interfaces não SDK.