Mudanças de comportamento: todos os apps

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:

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:

  1. Ativo: o app está sendo usado ou foi usado recentemente.
  2. Grupo de trabalho: o app está em uso regular.
  3. Frequente: o app costuma ser usado, mas não todos os dias.
  4. Raro: o app não é usado com frequência.
  5. 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

A caixa de diálogo tem dois conjuntos de opções, uma
         acima da outra
Figura 1. Caixa de diálogo de permissões do sistema que permite que o usuário conceda acesso a informações de 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.

Os blocos das Configurações rápidas são rotulados como "Acesso à câmera" e
         "Acesso ao Microfone"
Figura 2. Desativação do microfone e da câmera nas Configurações rápidas.
Um retângulo arredondado no canto direito de cima,
         que inclui um ícone da câmera e um ícone do microfone
Figura 3. Indicadores de microfone e câmera, que mostram o acesso recente aos dados.

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 do KeyGenerator 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:

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:

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 ou INVISIBLE.

  • 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.