Mudanças de comportamento: apps destinados ao Android 12

Como nas versões anteriores, o Android 12 inclui mudanças de comportamento que podem afetar seu app. As seguintes mudanças de comportamento se aplicam exclusivamente a apps destinados ao Android 12 ou versão mais recente. Caso seu app seja destinado ao Android 12, faça modificações para torná-lo compatível com esses comportamentos, quando aplicável.

Consulte também a lista de mudanças de comportamento que afetam todos os apps executados no Android 12.

Experiência do usuário

Melhorias no comportamento do picture-in-picture

O Android 12 introduz melhorias de comportamento no modo picture-in-picture (PiP). Consulte Melhorias do modo picture-in-picture para ver mais informações.

Notificações personalizadas

O Android 12 muda a aparência e o comportamento das notificações personalizadas. Antes, as notificações personalizadas podiam usar toda a área de notificações e utilizar layouts e estilos próprios. Isso gerava uma falta de padrão que podia confundir o usuário ou causar problemas de compatibilidade de layout em dispositivos diferentes.

Em apps destinados ao Android 12, as notificações com visualizações de conteúdo personalizadas deixarão de usar toda a área da notificação. Em vez disso, o sistema aplicará um modelo padrão. Esse modelo garante que as notificações personalizadas tenham o mesmo estilo que outras notificações em todos os estados, como o ícone da notificação e os recursos de expansão (no estado recolhido) e o ícone, o nome do app e o recurso de recolhimento da notificação (no estado expandido). Esse comportamento é quase idêntico ao comportamento de Notification.DecoratedCustomViewStyle.

Dessa forma, o Android 12 torna todas as notificações visualmente consistentes e fáceis de verificar, com uma expansão de notificação reconhecível e familiar para os usuários.

A ilustração a seguir mostra uma notificação personalizada no modelo padrão:

Os exemplos a seguir mostram como as notificações personalizadas são renderizadas no estado recolhido e expandido:

A mudança no Android 12 afeta os apps que definem subclasses personalizadas de Notification.Style ou que usam os métodos setCustomContentView(RemoteViews), setCustomBigContentView(RemoteViews) e setCustomHeadsUpContentView(RemoteViews) de Notification.Builder.

Se o app usa notificações totalmente personalizadas, recomendamos testar com o novo modelo o quanto antes.

  1. Ative a mudança nas notificações personalizadas:

    1. Mude a targetSdkVersion do app para S para ativar o novo comportamento.
    2. Recompile.
    3. Instale o app em um dispositivo ou emulador com o Android 12.
  2. Teste todas as notificações que usam visualizações personalizadas, verificando se elas apresentam a aparência esperada. Ao testar, considere o seguinte e faça as mudanças necessárias:

    • As dimensões das visualizações personalizadas mudaram. Em geral, a altura permitida para notificações personalizadas é menor do que a anterior. No estado recolhido, a altura máxima do conteúdo personalizado diminuiu de 106 dp para 48 dp. Além disso, há menos espaço na horizontal.

    • Todas as notificações podem ser expandidas em apps direcionados ao Android 12. Normalmente, isso significa que, se você estiver usando o método setCustomContentView, também convém usar setBigCustomContentView para garantir que os estados recolhido e expandido sejam consistentes.

    • Para garantir que o estado "Atenção" tenha a aparência esperada, não se esqueça de aumentar a importância do canal de notificações para "ALTA" (exibir na tela).

Em apps direcionados ao Android 12, o sistema faz várias mudanças na forma como os Links do app Android são verificados. Essas mudanças melhoram a confiabilidade da experiência de vinculação de apps e oferecem mais controle para os desenvolvedores e usuários finais.

Se o app é destinado ao Android 12 e depende da verificação do recurso Links do app Android para abrir links da Web no app, atualize as declarações do Links do app Android para oferecer compatibilidade com o processo de verificação mudado. É possível invocar manualmente a verificação de domínio para testar a confiabilidade das declarações.

Privacidade

Local aproximado

A caixa de diálogo tem dois conjuntos de opções, uma
         acima da outra
Figura 1. As caixas de diálogo de permissões do sistema aparecem quando o app é direcionado ao Android 12 e solicita ACCESS_FINE_LOCATION e ACCESS_COARSE_LOCATION em uma única solicitação durante a execução.

Ao usar um app destinado ao Android 12, os usuários podem solicitar que ele tenha acesso apenas às informações de localização aproximadas.

Se o app for direcionado ao Android 12 e solicitar a permissão de execução ACCESS_FINE_LOCATION, você também precisa solicitar a permissão ACCESS_COARSE_LOCATION. Você precisa incluir as duas permissões em uma única solicitação de execução.

Quando o app solicitar ACCESS_FINE_LOCATION e ACCESS_COARSE_LOCATION, a caixa de diálogo de permissões do sistema incluirá as novas opções a seguir para o usuário, conforme mostrado na Figura 1:

  • Exata: oferece a precisão da localização fornecida pela permissão ACCESS_FINE_LOCATION.
  • Aproximada: oferece a precisão da localização fornecida pela permissão ACCESS_COARSE_LOCATION.

Saiba mais sobre a localização aproximada no Android 12.

Hibernação do app

O Android 12 aprofunda o comportamento de redefinição automática de permissões introduzido no Android 11 (nível 30 da API). Se o app for direcionado ao Android 12 e o usuário não interagir com ele por alguns meses, o sistema redefinirá automaticamente todas as permissões concedidas e o colocará em um estado de hibernação.

Um app que está em hibernação tem estas características:

  • O sistema otimiza o espaço de armazenamento em vez do desempenho. Todos os arquivos no cache do app são removidos.
  • O app não pode executar tarefas ou alertas em segundo plano.
  • O app não recebe notificações push, incluindo mensagens de alta prioridade que são enviadas pelo Firebase Cloud Messaging.

Quando o usuário interagir com o app, ele sairá da hibernação e poderá criar jobs, alertas e notificações novamente. No entanto, será necessário reprogramar todos os jobs, alertas e notificações que foram programados antes da hibernação do app. Esse fluxo de trabalho é parecido com o de quando o usuário força o fechamento do app manualmente nas configurações do sistema. Para facilitar esse fluxo de trabalho, use o WorkManager. Também é possível adicionar a lógica de reprogramação no broadcast receiver ACTION_BOOT_COMPLETED, que é invocada quando o app sai da hibernação e após a inicialização do dispositivo.

Solicitar que o usuário desative a hibernação

Se você antecipar que um caso de uso do app será afetado pela hibernação, envie ao usuário uma solicitação para conceder uma exceção à hibernação e permitir a redefinição automática de permissões. Essa exceção é útil para situações em que os usuários esperam que o app funcione, principalmente em segundo plano, mesmo que não interajam com ele, por exemplo, quando o app realiza uma ou mais das ações a seguir:

  • Fornecer segurança familiar, informando periodicamente a localização dos membros da família.
  • Sincronizar dados entre um dispositivo e o servidor do app.
  • Comunicar-se com dispositivos inteligentes, como uma TV.
  • Parear com dispositivos complementares, como um smartwatch.

Para solicitar uma exceção, invoque uma intent contendo a ação da intent Intent.ACTION_APPLICATION_DETAILS_SETTINGS. Na tela exibida, os usuários podem desativar a opção Remover permissões e liberar espaço.

Testar o comportamento da hibernação

Para colocar o app no estado de hibernação para testes, faça o seguinte:

  1. Ative o comportamento no dispositivo:

    adb shell device_config put app_hibernation app_hibernation_enabled true
    
  2. Mude o estado do app para que ele entre em hibernação. O comando que inclui a sinalização --global força o app a entrar em "hibernação completa" para simular a situação em que o sistema colocou o app em hibernação para todos os usuários em um dispositivo multiusuário.

    adb shell cmd app_hibernation set-state PACKAGE-NAME true && \
      adb shell cmd app_hibernation set-state --global PACKAGE-NAME true
    

Limitação de taxa dos sensores de movimento

Para proteger informações potencialmente confidenciais sobre os usuários, se o app for direcionado ao Android 12, o sistema estabelecerá um limite na taxa de atualização de dados de determinados sensores de movimento e sensores de posição. Esses dados incluem valores gravados pelo acelerômetro, giroscópio e sensor de campo geomagnético do dispositivo.

O limite da taxa de atualização depende de como você acessa os dados do sensor:

  • Se você chamar o método registerListener(), a taxa de amostragem do sensor será limitada a 200 Hz. Isso vale para todas as variantes sobrecarregadas do método registerListener().
  • Se você usar a classe SensorDirectChannel, a taxa de amostragem do sensor ficará limitada a RATE_NORMAL, que é geralmente cerca de 50 Hz.

Se o app for direcionado ao Android 12 e precisar coletar dados do sensor de movimento com uma taxa maior, você precisará declarar a permissão HIGH_SAMPLING_RATE_SENSORS. Caso contrário, se o app tentar coletar dados do sensor de movimento em uma taxa maior sem declarar essa permissão, ocorrerá uma SecurityException.

Auditoria de acesso a dados

A API de acesso a dados, introduzida no Android 11 (nível 30 da API), possibilita criar tags de atribuição com base nos casos de uso do app. Essas tags facilitam determinar qual parte do app executa um tipo específico de acesso a dados.

Se o app for direcionado ao Android 12, será necessário declarar essas tags de atribuição no arquivo de manifesto dele usando o formato mostrado no snippet de código a seguir. Se o app for direcionado ao Android 12 e você tentar usar uma tag de atribuição não declarada no arquivo de manifesto dele, o sistema criará uma tag null para você e registrará uma mensagem no Logcat.


<manifest ...>
    <!-- The value of "android:tag" must be a literal string, and the
         value of "android:label" must be a resource. The value of
         "android:label" should be user-readable. -->
    <attribution android:tag="sharePhotos"
                 android:label="@string/share_photos_attribution_label" />
    ...
</manifest>

Cookies SameSite modernos no WebView

O componente WebView do Android é baseado no Chromium (link em inglês), o projeto de código aberto que alimenta o navegador Chrome do Google. No ano passado, o Chromium introduziu mudanças no processamento de cookies de terceiros para proporcionar mais segurança e privacidade e oferecer aos usuários mais transparência e controle. Essas mudanças já foram lançadas para muitos usuários do Chrome. A partir do Android 12, as mudanças chegam ao WebView.

O atributo SameSite de um cookie controla se ele pode ser enviado com qualquer solicitação ou apenas com solicitações do mesmo site. A versão base do WebView no Android 12 (versão 89.0.4385.0) inclui as seguintes mudanças de proteção de privacidade que melhoram o processamento padrão de cookies de terceiros e ajudam na proteção contra o compartilhamento não intencional entre diferentes sites:

  • Cookies sem um atributo SameSite são tratados como SameSite=Lax.
  • Cookies com SameSite=None também precisam especificar o atributo Secure. Isso significa que eles exigem um contexto seguro e precisam ser enviados por HTTPS.
  • Os links entre versões HTTP e HTTPS de um site agora são tratados como solicitações entre diferentes sites. Portanto, os cookies só serão enviados se estiverem marcados como SameSite=None; Secure.

Para desenvolvedores, a orientação geral é identificar as dependências de cookies entre sites nos fluxos de usuários importantes e garantir que o atributo SameSite seja definido explicitamente com os valores adequados, quando necessário. É preciso especificar explicitamente os cookies que têm permissão para trabalhar entre diferentes sites ou em navegações em um mesmo site que passam de HTTP para HTTPS.

Para ver orientações completas para desenvolvedores da Web sobre essas mudanças, consulte SameSite Cookies Explained e Schemeful Scheme SameSite (links em inglês).

Testar comportamentos do SameSite no app

Se o seu app usa o WebView ou se você gerencia um site ou serviço que usa cookies, recomendamos testar seus fluxos no WebView do Android 12. Caso encontre problemas, pode ser necessário atualizar os cookies para oferecer compatibilidade com os novos comportamentos do SameSite.

Monitore problemas de login e conteúdo incorporado, bem como de fluxos de login, compras e outros fluxos de autenticação em que o usuário inicia em uma página não segura e passa para uma página segura.

Para testar um app com o WebView, é necessário ativar os novos comportamentos de SameSite para o app que será testado, seguindo uma destas etapas:

  • Ative manualmente os comportamentos do SameSite no dispositivo de teste alternando a sinalização de IU webview-enable-modern-cookie-same-site no devtools do WebView.

    Essa abordagem permite que você faça testes em qualquer dispositivo com o Android 5.0 (API de nível 21) ou versão mais recente, incluindo o Android 12, e com o WebView 89.0.4385.0 ou versão mais recente.

  • Compile o app para destiná-lo ao Android 12 pela targetSdkVersion.

    Caso você use essa abordagem, é necessário utilizar um dispositivo com o Android 12 e o WebView 89.0.4385.0 ou versão mais recente.

Para saber mais sobre a depuração remota do WebView no Android, consulte Primeiros passos com a depuração remota de dispositivos Android.

Outros recursos

Para ver mais informações sobre os comportamentos modernos do SameSite e o lançamento para o Chrome e o WebView, visite a página de atualizações do SameSite do Chromium (link em inglês). Caso encontre um bug no WebView ou no Chromium, informe o problema no Issue Tracker público do Chromium (link em inglês).

Restrição de backup do ADB

Para ajudar a proteger os dados particulares do app, o Android 12 muda o comportamento padrão do comando adb backup. Em apps destinados ao Android 12, quando o usuário executar o comando adb backup, os dados do app serão excluídos de todos os outros dados do sistema exportados do dispositivo.

Caso os fluxos de trabalho de teste ou desenvolvimento dependam de dados do app que usam adb backup, é possível exportar os dados do app, definindo android:debuggable como true no arquivo de manifesto do app.

Segurança

Exportar componentes de forma mais segura

Caso o app seja destinado ao Android 12 e contenha atividades, serviços ou broadcast receivers que usam filtros de intent, declare explicitamente o atributo android:exported para esses componentes do app.

O snippet de código a seguir mostra o exemplo de um serviço que contém um filtro de intent e está configurado corretamente para o Android 12:

<service android:name="com.example.app.backgroundService"
         android:exported="false">
    <intent-filter>
        <action android:name="com.example.app.START_BACKGROUND" />
    </intent-filter>
</service>

Mensagens no Android Studio

Se o app tiver uma atividade, um serviço ou um broadcast receiver que usa filtros de intent, mas não declarar android:exported, as mensagens de aviso a seguir serão exibidas, dependendo da versão do Android Studio que você usar:

Android Studio 2020.3.1 Canary 11 ou versões mais recentes

As mensagens a seguir são exibidas:

  1. O aviso de lint a seguir é exibido no arquivo de manifesto:

    When using intent filters, please specify android:exported as well
    
  2. Ao tentar compilar o app, a mensagem de erro de compilação a seguir é exibida:

    Manifest merger failed : Apps targeting Android 12 and higher are required \
    to specify an explicit value for android:exported when the corresponding \
    component has an intent filter defined.
    
Versões mais antigas do Android Studio

Se você tentar instalar o app, o Logcat exibirá a mensagem de erro a seguir:

Installation did not succeed.
The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE
List of apks:
[0] '.../build/outputs/apk/debug/app-debug.apk'
Installation failed due to: 'null'

Mutabilidade de intents pendentes

Caso o app seja destinado ao Android 12, especifique a mutabilidade de cada objeto PendingIntent criado pelo app. Esse novo requisito melhora a segurança do app.

Para declarar que determinado objeto PendingIntent é mutável ou imutável, use a sinalização PendingIntent.FLAG_MUTABLE ou PendingIntent.FLAG_IMMUTABLE, respectivamente. Caso o app tente criar um objeto PendingIntent sem definir uma sinalização de mutabilidade, o sistema gerará uma IllegalArgumentException e a mensagem a seguir será exibida no Logcat:

PACKAGE_NAME: Targeting S+ (version 10000 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.

Criar intents pendentes imutáveis sempre que possível

Na maioria dos casos, o app precisa criar objetos PendingIntent imutáveis, conforme mostrado no snippet de código a seguir. Se um objeto PendingIntent for imutável, o app não poderá modificar a intent para ajustar o resultado da invocação da intent.

Kotlin

val pendingIntent = PendingIntent.getActivity(applicationContext,
        REQUEST_CODE, intent,
        /* flags */ PendingIntent.FLAG_IMMUTABLE)

Java

PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
        REQUEST_CODE, intent,
        /* flags */ PendingIntent.FLAG_IMMUTABLE);

No entanto, alguns apps precisam criar objetos PendingIntent mutáveis:

Se o app criar um objeto PendingIntent mutável, é altamente recomendável que você use uma intent explícita e preencha o ComponentName. Dessa forma, todas as vezes que outro app invocar PendingIntent e devolver o controle ao seu app, o mesmo componente será iniciado.

Testar a mudança de mutabilidade da intent pendente

Para determinar se faltam declarações de mutabilidade no app, procure o seguinte aviso de lint no Android Studio:

Warning: Missing PendingIntent mutability flag [UnspecifiedImmutableFlag]

Durante a Visualização do desenvolvedor, é possível desativar esse comportamento de sistema para fins de teste, desativando a sinalização de compatibilidade do app PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED.

Inicializações de intents não seguras

Para melhorar a segurança da plataforma, o Android 12 oferece um recurso de depuração que gera um aviso se o app realizar uma inicialização não segura de uma intent. Por exemplo, o app pode executar uma inicialização não segura de uma intent recriada de um URI ou uma inicialização não segura de uma intent aninhada, que é definida na próxima seção.

Sobre intents aninhadas

Intents aninhadas são aquelas transmitidas como um extra de outra intent. Caso o app execute as duas ações a seguir, ocorrerá uma violação de StrictMode.

Configurar o app para detectar inicializações de intents não seguras

Para verificar se há inicializações de intents não seguras no app, chame detectUnsafeIntentLaunch() ao configurar o VmPolicy, conforme mostrado no snippet de código a seguir. Caso o app detecte uma violação de StrictMode, é recomendado interromper a execução para proteger informações possivelmente confidenciais.

Kotlin

fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        // Other StrictMode checks that you've previously added.
        // ...
        .detectUnsafeIntentLaunch()
        .penaltyLog()
        // Consider also adding penaltyDeath()
        .build())
}

Java

protected void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
        // Other StrictMode checks that you've previously added.
        // ...
        .detectUnsafeIntentLaunch()
        .penaltyLog()
        // Consider also adding penaltyDeath()
        .build());
}

Usar intents de forma mais responsável

O app pode iniciar intents aninhadas para navegar entre componentes dentro do app ou para executar uma ação em nome de outro app. Para minimizar a possibilidade de encontrar uma violação de StrictMode em qualquer uma das situações, faça o seguinte:

  • Copie apenas os extras essenciais nas intents e execute todas as limpezas e validações necessárias. O app pode copiar os extras de uma intent para outra usada para iniciar um novo componente. Isso ocorre quando o app chama putExtras(Intent) ou putExtras(Bundle). Se o app executar uma dessas operações, copie apenas os extras esperados pelo componente de recebimento. Se a outra intent (que recebe a cópia) iniciar um componente que não foi exportado, limpe e valide os extras antes de copiá-los para a intent que inicia o componente.
  • Lançamento interno de intent aninhada: verifique se esses componentes não são exportados.
  • Lançamento de intent aninhada entre apps diferentes: use uma PendingIntent em vez de uma intent aninhada. Dessa forma, quando a PendingIntent não for separada da Intent, um componente do app poderá iniciar a PendingIntent usando a identidade do processo de chamada. Essa configuração permite que um app do provedor envie um callback para qualquer componente do app de chamada, incluindo um componente não exportado.

    Para ver mais informações sobre como identificar essa situação e fazer mudanças no app, leia a postagem do blog Android Nesting Intents (link em inglês) no Medium.

Desempenho

Restrições de inicialização de serviços em primeiro plano

Os apps destinados ao Android 12 não podem mais iniciar serviços em primeiro plano enquanto são executados em segundo plano, exceto em alguns casos específicos. Se um app tente iniciar um serviço em primeiro plano durante a execução em segundo plano, uma exceção será gerada (exceto em alguns casos específicos). Considere usar o WorkManager para programar e iniciar o trabalho enquanto o app é executado em segundo plano.

Para saber mais sobre como o app é afetado e como você pode atualizá-lo com base nessas mudanças, leia o guia sobre restrições de inicialização de serviços em primeiro plano. Você também pode consultar WorkManagerSample (link em inglês) no GitHub.

Permissão de alarme exato

Para incentivar os apps a economizar os recursos do sistema, o Android 12 exige acesso especial aos "Alarmes e lembretes" para os apps direcionados ao Android 12 que definem alarmes exatos.

Para ter esse acesso especial no app, solicite a permissão SCHEDULE_EXACT_ALARM no manifesto.

Os alarmes exatos precisam ser usados apenas para recursos voltados ao usuário, como uma das situações descritas na seção Casos de uso aceitáveis.

O usuário e o sistema podem revogar o acesso especial do app aos "Alarmes e lembretes". Quando o acesso especial aos "Alarmes e lembretes" do app é revogado, ele é interrompido e todos os alarmes exatos futuros são cancelados.

Quando o acesso especial aos "Alarmes e lembretes" é concedido ao app, o sistema envia a transmissão ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED. O app precisa implementar um broadcast receiver que faz o seguinte:

  1. Confirma se o app ainda tem o acesso especial. Para fazer isso, chame o método canScheduleExactAlarms().
  2. Reprograma os alarmes exatos necessário para o app com base no estado atual. Essa lógica precisa ser parecida com a de quando o app recebe a transmissão ACTION_BOOT_COMPLETED.

Se o app tentar usar APIs que definem alarmes exatos, mas não recebem o acesso especial, ocorrerá uma SecurityException.

Considere se o caso de uso do app realmente exige alarmes exatos, como em uma das situações descritas na seção de casos de uso aceitáveis. Para realizar um trabalho mais longo ou que exige acesso à rede, use o WorkManager ou o JobScheduler. Para realizar o trabalho enquanto o dispositivo está no modo Soneca, crie um alarme impreciso usando setAndAllowWhileIdle() e inicie um job com o alarme.

Alarmes exatos e imprecisos

O app define um alarme exato chamando métodos como estes:

Por outro lado, você define alarmes imprecisos ao chamar métodos como estes:

Casos de uso aceitáveis para essa permissão

A opção &quot;Autorizar a definição de alarmes e lembretes&quot;
Figura 2. Página de acesso especial aos "Alarmes e lembretes" nas configurações do sistema, onde os usuários podem autorizar o app a definir alarmes exatos.

O app precisa usar alarmes exatos e declarar as permissões e os broadcast receivers associados apenas se uma função voltada para o usuário exigir ações no momento certo, como nas situações a seguir:

  • O app é de despertador ou timer.
  • O app possibilita que os usuários programem ações com precisão, como notificações de tarefas e eventos.

O Android 12 considera alarmes exatos como interrupções críticas urgentes. Por esse motivo, os alarmes exatos não são afetados pelas novas restrições de inicialização de serviços em primeiro plano.

Pedir aos usuários para conceder acesso ao app

Se necessário, é possível direcionar os usuários para a tela Alarmes e lembretes nas configurações do sistema, como mostrado na Figura 2. Para isso, siga os seguintes passos:

  1. Na IU do app, explique ao usuário por que o app precisa programar alarmes exatos.
  2. Invoque uma intent que inclua a ação da intent ACTION_REQUEST_SCHEDULE_EXACT_ALARM.

Ativar a mudança de comportamento

Para ativar a mudança de comportamento para fins de teste, siga um destes procedimentos:

  • Na tela de configuração Opções do desenvolvedor, selecione Mudanças na compatibilidade do app. Na tela exibida, toque no nome do app e ative a REQUIRE_EXACT_ALARM_PERMISSION.
  • Em uma janela do terminal na máquina de desenvolvimento, execute o comando a seguir:

    adb shell am compat enable REQUIRE_EXACT_ALARM_PERMISSION PACKAGE_NAME
    

Restrições de trampolins de notificação

Quando o usuário interage com notificações, alguns apps respondem ao toque na notificação iniciando um componente de app que iniciará a atividade que o usuário visualiza e com a qual interage. Esse componente de app é conhecido como notificação em trampolim.

Para melhorar o desempenho e a UX, apps destinados ao Android 12 não podem iniciar atividades em serviços ou broadcast receivers usados como notificações em trampolim. Em outras palavras, depois que o usuário toca em uma notificação ou em um botão de ação na notificação, o app não pode chamar startActivity() dentro de um serviço ou broadcast receiver.

Quando o app tentar iniciar uma atividade em um serviço ou broadcast receiver que atua como uma notificação em trampolim, o sistema impedirá que a atividade seja iniciada e a mensagem a seguir será exibida no Logcat:

Indirect notification activity start (trampoline) from PACKAGE_NAME, \
this should be avoided for performance reasons.

Identificar quais componentes do app funcionam como trampolins de notificação

Ao testar o app, depois de tocar em uma notificação, você pode identificar qual serviço ou broadcast receiver atuou como o trampolim da notificação no app. Para fazer isso, observe a saída do comando do terminal a seguir:

adb shell dumpsys activity service \
  com.android.systemui/.dump.SystemUIAuxiliaryDumpService

Uma seção da saída inclui o texto "NotifInteractionLog". Esta seção contém as informações necessárias para identificar o componente que é iniciado como resultado de um toque de notificação.

Atualizar o app

Se o app iniciar atividades em um serviço ou broadcast receiver que atua como uma notificação em trampolim, siga estas etapas de migração:

  1. Crie um objeto PendingIntent associado à atividade que os usuários veem depois de tocar na notificação.
  2. Use o objeto PendingIntent criado na etapa anterior como parte da criação da notificação.

Para identificar a origem da atividade, de forma a executar a geração de registros, por exemplo, use extras ao postar a notificação. Para geração de registros centralizada, use ActivityLifecycleCallbacks ou os observadores de ciclo de vida do Jetpack.

Ativar ou desativar o comportamento

Ao testar o app durante a Visualização do desenvolvedor, é possível ativar e desativar essa restrição usando a sinalização de compatibilidade de app NOTIFICATION_TRAMPOLINE_BLOCK.

Backup e restauração

O Android 12 muda a forma como o backup e a restauração funcionam em apps que são executados e direcionados a ele ou a versões mais recentes. Para mais informações, consulte Mudanças no backup e restauração.

Conectividade

Conexões ponto a ponto e de Internet simultâneas

Com o Android 12, os dispositivos compatíveis com conexões ponto a ponto e de Internet simultâneas podem manter conexões Wi-Fi simultâneas com o dispositivo de conectado ponto a ponto e com a rede principal que fornece a Internet, tornando a experiência do usuário mais unificada. Esse recurso é ativado automaticamente para todos os apps destinados ao nível 31 da API e mais recentes. Os apps direcionados a níveis de API anteriores ainda apresentam o comportamento legado, em que a rede Wi-Fi principal é desconectada antes de fazer a conexão ponto a ponto do dispositivo.

Compatibilidade

O método WifiManager.getConnectionInfo() pode retornar as WifiInfo para apenas uma rede. Por isso, o comportamento da API mudou desta maneira no Android 12:

  • Se apenas uma rede Wi-Fi estiver disponível, as WifiInfo dela serão retornadas.
  • Se mais de uma rede Wi-Fi estiver disponível e o app de chamada tiver acionado uma conexão ponto a ponto, as WifiInfo correspondentes ao dispositivo conectado ponto a ponto serão retornadas.
  • Se mais de uma rede Wi-Fi estiver disponível e o app de chamada não tiver acionado uma conexão ponto a ponto, as WifiInfo da conexão de Internet principal serão retornadas.

Para oferecer uma melhor experiência do usuário em dispositivos compatíveis com duas redes Wi-Fi simultâneas, recomendamos que todos os apps, especialmente os que acionam conexões ponto a ponto, migrem da chamada WifiManager.getConnectionInfo(). Em vez dessa chamada, use NetworkCallback.onCapabilitiesChanged() para acessar todos os objetos WifiInfo que correspondem à NetworkRequest usada para registrar o NetworkCallback. O método getConnectionInfo() foi descontinuado a partir do Android 12.

O exemplo de código a seguir mostra como receber o WifiInfo em uma NetworkCallback:

Kotlin

val networkCallback = object : ConnectivityManager.NetworkCallback() {
  ...
  override fun onCapabilitiesChanged(
           network : Network,
           networkCapabilities : NetworkCapabilities) {
    val transportInfo = networkCapabilities.getTransportInfo()
    if (transportInfo !is WifiInfo) return
    val wifiInfo : WifiInfo = transportInfo
    ...
  }
}

Java

final NetworkCallback networkCallback = new NetworkCallback() {
  ...
  @Override
  public void onCapabilitiesChanged(
         Network network,
         NetworkCapabilities networkCapabilities) {
    final TransportInfo transportInfo = networkCapabilities.getTransportInfo();
    if (!(transportInfo instanceof WifiInfo)) return;
    final WifiInfo wifiInfo = (WifiInfo) transportInfo;
    ...
  }
  ...
};

Permitir pagamentos NFC com a tela desativada

Em apps direcionados ao Android 12 e versões mais recentes, é possível ativar pagamentos NFC com a tela do dispositivo desativada ao configurar requireDeviceScreenOn como false. Para mais informações sobre pagamentos NFC com a tela desativada ou bloqueada, consulte Tela desativada e comportamento da tela de bloqueio.

Bibliotecas do fornecedor

Bibliotecas compartilhadas nativas oferecidas pelo fornecedor

As Bibliotecas compartilhadas nativas não NDK que são oferecidas por fornecedores de componentes eletrônicos ou de dispositivos não poderão ser acessadas por padrão se o app for direcionado ao Android 12 ou versões mais recentes. As bibliotecas só poderão ser acessadas quando forem explicitamente solicitadas usando a tag <uses-native-library>.

Se o app for destinado ao Android 11 ou versões anteriores, a tag <uses-native-library> não será necessária. Nesse caso, qualquer biblioteca compartilhada nativa poderá ser acessada independentemente de ser uma biblioteca do NDK ou não.

Atualização das restrições 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.