Restrições para interfaces não SDK

A partir do Android 9 (nível 28 da API), a plataforma restringe quais interfaces de fora do SDK seu app pode usar. Essas restrições são aplicadas sempre que um app se refere a uma interface externa ao SDK ou tenta buscar o identificador dela usando reflexão ou JNI. As limitações foram implementadas para ajudar a melhorar a experiência do usuário e do desenvolvedor e reduzir os riscos de falhas para os usuários e lançamentos de emergência para os desenvolvedores. Para saber mais sobre essa decisão, consulte como reduzir o uso de interfaces externas ao SDK para melhorar a estabilidade (em inglês).

Diferenciar interfaces SDK e externas ao SDK

De um modo geral, as interfaces públicas do SDK são aquelas encontradas documentadas no índice de pacotes do framework Android. O processamento de interfaces externas ao SDK é um detalhe de implementação que a API abstrai. Portanto, essas interfaces estão sujeitas a mudanças sem aviso prévio.

Para evitar falhas e comportamentos inesperados, os apps só podem usar as partes oficialmente documentadas das classes no SDK. Isso também significa que não é permitido acessar métodos ou campos que não estejam listados no SDK ao interagir com uma classe usando mecanismos como reflexão.

Listas de APIs externas ao SDK

A cada versão do Android, mais interfaces externas ao SDK são restritas. Sabemos que essas limitações podem afetar o fluxo de trabalho da sua versão e queremos garantir que você tenha as ferramentas para detectar o uso de interfaces de fora do SDK, uma oportunidade de dar feedback e tempo para planejar e se ajustar às novas políticas.

Para minimizar o impacto das restrições de interfaces externas ao SDK no seu fluxo de trabalho de desenvolvimento, essas interfaces são divididas em listas que definem até que ponto o uso é restrito, dependendo de qual nível da API está sendo segmentado. A tabela abaixo descreve cada uma dessas listas:

Listar Tags de código Descrição
Lista de bloqueio
  • blocked
  • Descontinuado: blacklist
São interfaces externas ao SDK que não podem ser usadas, independente do nível da API de destino do app. Caso seu app tente acessar uma delas, o sistema gera um erro.
Bloqueio condicional
  • max-target-x
  • Descontinuado: greylist-max-x

No Android 9 (nível 28 da API) e versões mais recentes, cada nível da API tem interfaces externas ao SDK restritas caso sejam a API de destino do app.

Essas listas são rotuladas pelo nível máximo da API (max-target-x) que pode ser o destino do app antes de ele não conseguir mais acessar as interfaces externas ao SDK incluídas nelas. Por exemplo, uma interface externa ao SDK que não estava bloqueada no Android Pie, mas agora está bloqueada no Android 10, faz parte da lista max-target-p (greylist-max-p), em que "p" " significa Pie ou Android 9 (nível 28 da API).

Caso o app tente acessar uma interface restrita no nível da API de destino, o sistema se comportará como se ela estivesse na lista de bloqueio.

Sem suporte
  • unsupported
  • Descontinuado: greylist
São interfaces externas ao SDK que não são restritas e podem ser usadas pelo app. No entanto, elas não têm suporte e estão sujeitas a mudanças sem aviso prévio. Pressuponha que essas interfaces serão bloqueadas condicionalmente em versões futuras do Android por uma lista max-target-x.
SDK
  • public-api e sdk
  • Descontinuado: public-api e whitelist
São interfaces que podem ser usadas livremente e agora são aceitas como parte do Índice de pacote do framework do Android oficialmente documentado.
APIs de teste
  • test-api
Interfaces usadas para testes internos do sistema, como APIs que facilitam o teste pelo conjunto de teste de compatibilidade (CTS). As APIs de teste não fazem parte do SDK. No Android 11 (nível 30 da API) e versões mais recentes, as APIs de teste são incluídas na lista de bloqueio. Por isso, os apps não podem usá-las, independente do nível desejado da API. Nenhuma das APIs de teste têm suporte e estão sujeitas a mudanças sem aviso prévio, seja qual for o nível da API da plataforma.

Embora dependendo do nível da API de destino do app seja possível usar algumas interfaces externas ao SDK, o uso de qualquer método ou campo delas sempre implica um alto risco de corromper o app. Se ele depender de interfaces externas, comece a planejar uma migração para opções do SDK ou outras alternativas. Se você não encontrar uma alternativa para deixar de usar uma interface externa ao SDK em um recurso no app, solicite uma nova API pública.

Determinar a que lista uma interface pertence

As listas de interfaces externas ao SDK são criadas como parte da plataforma. Consulte as seções abaixo para saber mais sobre cada versão do Android.

Android 14 (Beta)

No Android 14 (nível 34 da API), você pode fazer o download deste arquivo que descreve todas as interfaces externas ao SDK e as listas correspondentes:

Arquivo: hiddenapi-flags.csv

Checksum SHA-256: 7e00db074cbe51c51ff4b411f7b48e98692951395c5c17d069c822cc1d0eae0f

Para saber mais sobre as mudanças na lista de APIs externas ao SDK no Android 14, consulte Atualizações para restrições de interface não SDK no Android 14.

Android 13

No Android 13 (nível 33 da API), você pode fazer o download do seguinte arquivo, que descreve todas as interfaces não SDK e as listas correspondentes:

Arquivo: hiddenapi-flags.csv

Checksum SHA-256: 233a277aa8ac475b6df61bffd95665d86aac6eb2ad187b90bf42a98f5f2a11a3

Para saber mais sobre as mudanças na lista de APIs externas ao SDK do Android 13, incluindo sugestões de alternativas públicas para APIs que são bloqueadas condicionalmente nele, consulte Atualizações para restrições de interface não SDK no Android 13.

Android 12

No Android 12 (nível 31 da API), você pode fazer o download do arquivo abaixo que descreve todas as interfaces externas ao SDK e as listas correspondentes:

Arquivo: hiddenapi-flags.csv

Checksum SHA-256: 40674ff4291eb268f86561bf687e69dbd013df9ec9531a460404532a4ac9a761

Para saber mais sobre as mudanças na lista de APIs externas ao SDK no Android 12, incluindo sugestões de alternativas públicas para APIs que são bloqueadas condicionalmente nele, consulte Mudanças de lista do Android 12.

Android 11

No Android 11 (API de nível 30), você pode fazer o download do seguinte arquivo que descreve todas as interfaces não SDK e as listas correspondentes:

Arquivo: hiddenapi-flags.csv

Checksum SHA-256: a19d839f4f61dc9c94960ae977b2e0f3eb30f880ba1ffe5108e790010b477a56

Para saber mais sobre as mudanças na lista de APIs externas ao SDK no Android 11, incluindo sugestões de alternativas públicas para APIs que são bloqueadas condicionalmente nele, consulte Mudanças de lista do Android 11.

Android 10

No Android 10 (API de nível 29), você pode fazer o download do seguinte arquivo que descreve todas as interfaces não SDK e as listas correspondentes:

Arquivo: hiddenapi-flags.csv

Checksum SHA-256: f22a59c215e752777a114bd9b07b0b6b4aedfc8e49e6efca0f99681771c5bfeb

Para saber mais sobre as mudanças na lista de APIs externas ao SDK no Android 10, incluindo sugestões de alternativas públicas para APIs que são bloqueadas condicionalmente nele, consulte Mudanças de lista do Android 10.

Android 9

Este arquivo de texto contém a lista de APIs externas ao SDK que não são restritas no Android 9 (nível 28 da API): hiddenapi-light-greylist.txt.

A lista de bloqueio (blacklist) e a lista de APIs bloqueadas condicionalmente (lista cinza-escuro) são derivadas no tempo de build.

Gerar listas do AOSP

Ao trabalhar com o AOSP, você pode gerar um arquivo hiddenapi-flags.csv que contenha todas as interfaces externas ao SDK e as listas correspondentes. Para fazer isso, faça o download da origem do AOSP e execute este comando:

m out/soong/hiddenapi/hiddenapi-flags.csv

Depois disso, será possível encontrar o arquivo no seguinte local:

out/soong/hiddenapi/hiddenapi-flags.csv

Comportamento esperado quando as interfaces não SDK restritas são acessadas

A tabela a seguir descreve o comportamento esperado caso o app tente acessar uma interface não SDK incluída na lista de bloqueio.

Meios de acesso Resultado
Instrução Dalvik referenciando um campo NoSuchFieldError exibido
Instrução Dalvik referenciando um método Gera um NoSuchMethodError
Reflexão usando Class.getDeclaredField() ou Class.getField() Gera uma NoSuchFieldException
Reflexão usando Class.getDeclaredMethod(), Class.getMethod() Gera uma NoSuchMethodException
Reflexão usando Class.getDeclaredFields(), Class.getFields() Membros externos ao SDK são excluídos dos resultados
Reflexão usando Class.getDeclaredMethods(), Class.getMethods() Membros externos ao SDK são excluídos dos resultados
JNI usando env->GetFieldID() Retorna NULL e gera um NoSuchFieldError
JNI usando env->GetMethodID() Retorna NULL e gera um NoSuchMethodError

Testar se há interfaces que não são do SDK no seu app

Existem vários métodos que você pode usar para testar interfaces externas ao SDK no seu app.

Testar usando um app de depuração

Para testar se há interfaces externas ao SDK, crie e execute um app depurável em um dispositivo ou emulador com o Android 9 (nível 28 da API) ou uma versão mais recente. Confira se o dispositivo ou emulador que você está usando corresponde ao nível da API de destino do seu app.

Ao fazer testes no app, o sistema mostra uma mensagem de registro caso seu app acesse determinadas interfaces externas ao SDK. É possível inspecionar as mensagens de registro do app para encontrar estes detalhes:

  • A classe, o nome e o tipo declarantes (no formato usado pelo ambiente de execução do Android).
  • Os meios de acesso: veiculação, reflexão ou JNI.
  • A que lista a interface externa pertence.

É possível usar o adb logcat para acessar essas mensagens de registro, que aparecem sob o PID do app em execução. Por exemplo, pode haver uma entrada assim no registro:

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)

Testar usando a API StrictMode

Também é possível testar se há interfaces externas ao SDK usando a API StrictMode. Use o método detectNonSdkApiUsage para ativar. Depois de ativar a API StrictMode, você pode receber um callback para cada uso de uma interface externa usando um penaltyListener, em que é possível implementar o processamento personalizado. O objeto Violation fornecido no callback deriva de Throwable, e o stack trace incluído fornece o contexto do uso.

Testar usando a ferramenta veridex

Também é possível executar a ferramenta de análise estática veridex no seu APK. A ferramenta veridex verifica toda a base de código do APK, incluindo qualquer biblioteca de terceiros, e relata todos os usos de interfaces externas ao SDK que encontrar.

Limitações da ferramenta veridex incluem o seguinte:

  • Não é possível detectar invocações por meio do JNI.
  • É possível detectar apenas um subconjunto de invocações por meio da reflexão.
  • A análise para caminhos de código inativos é limitada a verificações no nível da API.
  • Ele só pode ser executado em máquinas compatíveis com as instruções SSE4.2 e POPCNT.

Windows

Os binários nativos do Windows não são fornecidos, mas você pode ativar a ferramenta veridex no Windows executando os binários do Linux com o Windows Subsystem for Linux (WSL). Antes de seguir as etapas nesta seção, instale o WSL e escolha o Ubuntu como a distribuição Linux.

Após a instalação do Ubuntu, inicie um terminal Ubuntu e siga estas etapas:

  1. Faça o download da ferramenta veridex no repositório de elementos pré-criados do Android Runtime.
  2. Extraia o conteúdo do arquivo appcompat.tar.gz.
  3. Na pasta extraída, localize e extraia o arquivo veridex-linux.zip.
  4. Navegue até a pasta descompactada e execute o comando abaixo, em que your-app.apk é o APK que você quer testar:

    ./appcompat.sh --dex-file=your-app.apk
    

macOS

Para ativar a ferramenta veridex no macOS, siga estas etapas:

  1. Faça o download da ferramenta veridex no repositório de elementos pré-criados do Android Runtime.
  2. Extraia o conteúdo do arquivo appcompat.tar.gz.
  3. Na pasta extraída, localize e extraia o arquivo veridex-mac.zip.
  4. Navegue até a pasta descompactada e execute o comando abaixo, em que /path-from-root/your-app.apk é o caminho para o APK que você quer testar, começando do diretório raiz do sistema:

    ./appcompat.sh --dex-file=/path-from-root/your-app.apk
    

Linux

Para ativar a ferramenta veridex no Linux, siga estas etapas:

  1. Faça o download da ferramenta veridex no repositório de elementos pré-criados do Android Runtime.
  2. Extraia o conteúdo do arquivo appcompat.tar.gz.
  3. Na pasta extraída, localize e extraia o arquivo veridex-linux.zip.
  4. Navegue até a pasta descompactada e execute o comando abaixo, em que your-app.apk é o APK que você quer testar:

    ./appcompat.sh --dex-file=your-app.apk
    

Testar usando a ferramenta lint do Android Studio

Sempre que você cria um app no Android Studio, a ferramenta lint inspeciona o código em busca de possíveis problemas. Se o app usar interfaces externas ao SDK, vão aparecer erros ou avisos do build, dependendo da lista a que essas interfaces pertencem.

Também é possível executar a ferramenta lint na linha de comando ou executar inspeções manualmente em um projeto, uma pasta ou um arquivo específico.

Testar usando o Play Console

Ao fazer upload do app para uma faixa de teste no Play Console, o app é automaticamente testado para possíveis problemas, e um relatório de pré-lançamento é gerado. Se o app usar interfaces externas ao SDK, um erro ou aviso vai aparecer no relatório de pré-lançamento, dependendo da lista a que elas pertencem.

Para saber mais, consulte a seção "Compatibilidade do Android" em Usar relatórios de pré-lançamento para identificar problemas.

Solicitar uma nova API pública

Caso você não encontre uma alternativa para deixar de usar uma interface externa ao SDK para um recurso no seu app, é possível solicitar uma nova API pública criando uma solicitação de recurso no Issue Tracker.

Ao criar uma solicitação de recurso, forneça as informações abaixo:

  • Qual API sem suporte você está usando, incluindo o descritor completo que aparece na mensagem do logcat Accessing hidden ....
  • Por que você precisa usar essas APIs, incluindo detalhes sobre o recurso de alto nível para que a API é necessária, e não apenas detalhes de baixo nível.
  • Por que as APIs públicas do SDK relacionadas são insuficientes para seus objetivos.
  • Quaisquer outras alternativas que você tenha tentado e por que elas não funcionaram.

Ao fornecer esses detalhes na sua solicitação de recurso, você aumenta a probabilidade de uma nova API pública ser concedida.

Mais perguntas

Esta seção inclui algumas respostas para outras perguntas que os desenvolvedores realizam com frequência:

Perguntas gerais

Como o Google vai conseguir dar conta das demandas de todos os apps pelo issuetracker?

Criamos as listas iniciais do Android 9 (nível 28 da API) por uma análise estática de apps, que foi complementada usando estes métodos:

  • Teste manual dos principais apps do Google Play e de outras fontes
  • Relatórios internos
  • Coleta automática de dados de usuários internos
  • Relatórios de visualização do desenvolvedor
  • Análise estática adicional que foi projetada para incluir, de modo conservador, mais falsos positivos.

À medida que avaliamos as listas para cada nova versão, consideramos o uso da API e o feedback dos desenvolvedores por meio do rastreador de problemas.

Como posso ativar o acesso a interfaces que não são do SDK?

É possível ativar o acesso a interfaces externas em dispositivos de desenvolvimento usando comandos adb para alterar a política de aplicação da API. Os comandos que você usa variam, dependendo do nível da API. Esses comandos não exigem um dispositivo com acesso root.

Android 10 (nível 29 da API) ou mais recente

Para ativar o acesso, use o comando adb abaixo:

comando:

adb shell settings put global hidden_api_policy  1

Para redefinir a política de aplicação da API para as configurações padrão, use o comando abaixo:

adb shell settings delete global hidden_api_policy
Android 9 (nível 28 da API)

Para ativar o acesso, use os comandos adb abaixo:

adb shell settings put global hidden_api_policy_pre_p_apps  1
adb shell settings put global hidden_api_policy_p_apps 1

Para redefinir a política de aplicação da API para as configurações padrão, use os comandos abaixo:

adb shell settings delete global hidden_api_policy_pre_p_apps
adb shell settings delete global hidden_api_policy_p_apps

Você pode definir o número inteiro na política de aplicação da API como um destes valores:

  • 0: desativa todas as detecções de interfaces não SDK. O uso dessa configuração desativa todas as mensagens de registro para uso de interface externa ao SDK e impede que você teste seu app usando a API StrictMode. Essa configuração não é recomendada.
  • 1: ativa o acesso a todas as interfaces externas ao SDK, mas molstra mensagens de registro com avisos para qualquer uso desse tipo de interface. O uso dessa configuração também permite testar seu app usando a API StrictMode.
  • 2: não permite o uso de interfaces externas ao SDK incluídas na lista de bloqueio ou bloqueadas condicionalmente para o nível da API de destino.

Perguntas sobre listas de interface não SDK

Onde encontro as listas de APIs não SDK na imagem do sistema?

Elas são codificadas nos bits de sinalização de acesso a campo e método nos arquivos dex da plataforma. Não há arquivo separado na imagem do sistema que contenha essas listas.

As APIs não SDK são as mesmas em dispositivos de OEM diferentes que tenham a mesma versão do Android?

Os OEMs podem adicionar suas próprias interfaces à lista de bloqueio, mas não podem removê-las das listas de APIs não SDK do AOSP. O CDD impede essas mudanças, e os testes do CTS garantem que o ambiente de execução do Android aplique a lista.

Existe alguma restrição em interfaces não NDK no código nativo?

O SDK do Android inclui interfaces Java. A plataforma começou a restringir o acesso a interfaces externas ao NDK para códigos C/C++ nativos no Android 7 (nível 26 da API). Para mais informações, consulte como melhorar a estabilidade com restrições de símbolo C/C++ privado no Android N (link em inglês).

Existe algum plano para restringir a manipulação de arquivos dex2oat ou DEX?

Não temos planos ativos para restringir o acesso ao binário dex2oat, mas não pretendemos que o formato de arquivo DEX seja estável ou uma interface pública além das partes que são publicamente especificadas no formato executável Dalvik. Reservamo-nos o direito de modificar ou eliminar o dex2oat e as partes não especificadas do formato DEX a qualquer momento. Os arquivos derivados produzidos pelo dex2oat, como ODEX (também conhecido como OAT), VDEX e CDEX, são formatos não especificados.

E se um SDK de terceiros crucial (por exemplo, um ofuscador) não puder evitar o uso de interfaces que não são do SDK, mas se comprometer a manter a compatibilidade com futuras versões do Android? O Android poderá renunciar aos requisitos de compatibilidade nesse caso?

Não temos planos de renunciar aos requisitos de compatibilidade para SDKs específicos. Se um desenvolvedor de SDK puder manter compatibilidade dependendo apenas das interfaces nas listas sem suporte (anteriormente cinzas), ele precisará começar a planejar a migração para interfaces SDK ou outras alternativas e solicitar uma nova API pública sempre que não puder encontrar uma alternativa ao uso de uma interface externa ao SDK.

As restrições de interface externa ao SDK se aplicam a todos os apps, incluindo apps do sistema e de terceiros, e não somente apps de terceiros?

Sim, mas isentamos apps assinados com a chave da plataforma e alguns apps de imagem do sistema. Essas exceções se aplicam somente a apps que fazem parte da imagem do sistema ou a apps de imagem do sistema atualizados. A lista é destinada somente a apps criados com base nas APIs da plataforma privada, não nas APIs do SDK (em que LOCAL_PRIVATE_PLATFORM_APIS := true).