O Android 9 (API de nível 28) introduz diversas mudanças ao sistema Android. As seguintes mudanças de comportamento se aplicam a todos os apps quando executados na plataforma Android 9, independentemente do nível da API ao qual eles são destinados. Todos os desenvolvedores precisam analisar essas mudanças e modificar os apps para oferecer suporte a elas, quando aplicável.
Para mudanças que afetam apenas apps direcionados ao nível 28 da API ou mais recente, consulte Mudanças de comportamento: apps direcionados ao nível 28 da API ou mais recente.
Gerenciamento de energia
O Android 9 apresenta novos recursos para melhorar o gerenciamento de energia do dispositivo. Essas mudanças, além dos recursos que já existiam antes do Android 9, ajudam a garantir que os recursos do sistema sejam disponibilizados para os apps que mais precisam deles.
Para saber detalhes, consulte Gerenciamento de energia.
Mudanças de privacidade
Para melhorar a privacidade do usuário, o Android 9 apresenta várias mudanças de comportamento, como limitar o acesso de apps em segundo plano a sensores do dispositivo, restringir informações recuperadas de verificações de Wi-Fi e novas regras e grupos de permissões relacionados a chamadas, estado do smartphone e verificações de Wi-Fi.
Essas mudanças afetam todos os apps executados no Android 9, independentemente da versão do SDK de destino.
Acesso limitado a sensores em segundo plano
O Android 9 limita a capacidade de apps em segundo plano de acessar dados de entrada e sensor do usuário. Se o app estiver em execução em segundo plano em um dispositivo com o Android 9, o sistema aplicará as seguintes restrições:
- O app não pode acessar o microfone nem a câmera.
- Os sensores que usam o modo de relatório contínuo, como acelerômetros e giroscópios, não recebem eventos.
- Os sensores que usam os modos de relatório on-change ou one-shot não recebem eventos.
Se o app precisar detectar eventos de sensor em dispositivos com o Android 9, use um serviço em primeiro plano.
Acesso restrito aos registros de chamadas
O Android 9 apresenta o
grupo de permissões CALL_LOG
e move as permissões
READ_CALL_LOG
,
WRITE_CALL_LOG
e
PROCESS_OUTGOING_CALLS
para esse grupo. Em versões anteriores do Android, essas permissões
estavam localizadas no grupo de permissões PHONE
.
Esse grupo de permissões CALL_LOG
oferece aos usuários mais controle e visibilidade para
apps que precisam acessar informações sensíveis sobre ligações, como
ler registros de ligações e identificar números de telefone.
Se o app precisar de acesso aos registros de chamadas ou precisar processar chamadas de saída, solicite explicitamente essas permissões do
grupo de permissões CALL_LOG
. Caso contrário, uma
SecurityException
ocorrerá.
Observação : como essas permissões mudaram de grupo e são concedidas durante a execução, é possível que o usuário negue o acesso do app às informações de registros de chamadas telefônicas. Nesse caso, o app precisa ser capaz de lidar com a falta de acesso às informações de maneira adequada.
Se o app já segue as práticas recomendadas de permissões de execução, ele pode processar a mudança no grupo de permissões.
Acesso restrito a números de telefone
Os apps executados no Android 9 não podem ler números de telefone ou o estado do telefone sem
adquirir primeiro a permissão
READ_CALL_LOG
, além das outras que os casos de uso do app
exigem.
Os números de telefone associados a chamadas recebidas e efetuadas ficam visíveis no
transmissão de estado
do telefone,
como para chamadas recebidas e efetuadas, e podem ser acessados na classe
PhoneStateListener
.
No entanto, sem a permissão
READ_CALL_LOG
, o campo de número de telefone fornecido nas
transmissões PHONE_STATE_CHANGED
e por PhoneStateListener
fica vazio.
Para ler números de telefone do estado do smartphone, atualize o app para solicitar as permissões necessárias com base no seu caso de uso:
- Para ler números da ação
de intent
PHONE_STATE
, você precisa da permissãoREAD_CALL_LOG
e da permissãoREAD_PHONE_STATE
. - Para ler números de
onCallStateChanged()
, você precisa apenas da permissãoREAD_CALL_LOG
. Você não precisa da permissãoREAD_PHONE_STATE
.
Acesso restrito a informações de localização e conexão Wi-Fi
No Android 9, os requisitos de permissão para que um app realize verificações de Wi-Fi são mais rígidos do que nas versões anteriores. Para saber mais, consulte Restrições de verificação de Wi-Fi.
Restrições semelhantes também se aplicam ao método
getConnectionInfo()
, que retorna um objeto WifiInfo
que descreve a conexão Wi-Fi atual. Só é possível usar os métodos
desse objeto para extrair valores de SSID e BSSID se o app de chamada tiver as seguintes
permissões:
- ACCESS_FINE_LOCATION ou ACCESS_COARSE_LOCATION
- ACCESS_WIFI_STATE
A recuperação do SSID ou BSSID também exige que os serviços de localização estejam ativados no dispositivo (em Configurações > Localização).
Informações removidas dos métodos de serviço de Wi-Fi
No Android 9, os eventos e transmissões a seguir não recebem informações sobre o local do usuário nem dados de identificação pessoal:
- Os métodos
getScanResults()
egetConnectionInfo()
deWifiManager
. - Os métodos
discoverServices()
eaddServiceRequest()
deWifiP2pManager
. - A transmissão
NETWORK_STATE_CHANGED_ACTION
.
A transmissão do sistema NETWORK_STATE_CHANGED_ACTION
do Wi-Fi não contém mais SSID (antes EXTRA_SSID),
BSSID (antes EXTRA_BSSID) ou informações de conexão (antes
EXTRA_NETWORK_INFO). Se o app precisar dessas informações, chame
getConnectionInfo()
.
As informações de telefonia agora dependem da configuração de localização do dispositivo
Se o usuário tiver desativado a localização do dispositivo em um dispositivo com o Android 9, os métodos a seguir não vão gerar resultados:
Restrições para o uso de interfaces que não são do SDK
Para garantir a estabilidade e a compatibilidade do app, a plataforma restringe o uso de alguns métodos e campos que não são do SDK. Essas restrições se aplicam se você tentar acessar esses métodos e campos diretamente, por reflexão ou usando JNI. No Android 9, o app pode continuar acessando essas interfaces restritas. A plataforma usa notificações e entradas de registro para chamar a atenção. Se o app mostrar esse aviso, é importante que você siga uma estratégia de implementação diferente da interface restrita. Se você achar que nenhuma estratégia alternativa é viável, registre um bug para solicitar uma reconsideração da restrição.
Restrições para interfaces que não são SDK contém outras informações importantes. Revise-o para garantir que o app continue funcionando corretamente.
Mudanças no comportamento de segurança
Mudanças na segurança do dispositivo
O Android 9 adiciona vários recursos que melhoram a segurança do app, independentemente da versão para a qual ele é direcionado.
Mudanças na implementação do TLS
A implementação do TLS do sistema passou por várias mudanças no Android 9:
- Se uma instância de
SSLSocket
falhar na conexão durante a criação, o sistema vai gerar umaIOException
em vez de umaNullPointerException
. - A classe
SSLEngine
processa de forma limpa todos os alertasclose_notify
que ocorrem.
Para saber mais sobre como fazer solicitações da Web seguras em um app Android, consulte Um exemplo de HTTPS.
Filtro SECCOMP mais restrito
O Android 9 restringe ainda mais as chamadas de sistema disponíveis aos aplicativos. Esse comportamento é uma extensão do filtro SECCOMP incluído no Android 8.0 (nível 26 da API).
Mudanças criptográficas
O Android 9 introduz várias mudanças na implementação e no processamento de algoritmos criptográficos.
Implementações de parâmetros e algoritmos do Conscrypt
O Android 9 oferece outras implementações de parâmetros de algoritmo no Conscrypt. Esses parâmetros incluem: AES, DESEDE, OAEP e EC. As versões do Bouncy Castle (link em inglês) desses parâmetros e de muitos algoritmos foram descontinuadas no Android 9.
Se o app for destinado ao Android 8.1 (nível 27 da API) ou versões anteriores, você vai receber um aviso
ao solicitar a implementação do Bouncy Castle de um desses algoritmos
descontinuados. No entanto, se você direcionar o Android 9, essas solicitações vão gerar uma
NoSuchAlgorithmException
.
Outras mudanças
O Android 9 apresenta diversas outras alterações relacionadas a criptografia:
- Ao usar chaves PBE, se o Bouncy Castle estiver esperando um vetor de inicialização (IV) e o app não fornecer um, você vai receber um aviso.
- A implementação da Conscrypt da cifra ARC4 permite especificar ARC4/ECB/NoPadding ou ARC4/NONE/NoPadding.
- O provedor de criptografia Java Cryptography Architecture (JCA) foi removido. Como
resultado, se o app chamar
SecureRandom.getInstance("SHA1PRNG", "Crypto")
, umaNoSuchProviderException
ocorrerá. - Se o app analisar chaves RSA de buffers maiores que a estrutura de chaves, uma exceção não vai mais ocorrer.
Para saber mais sobre o uso dos recursos de criptografia do Android, consulte Criptografia.
Os arquivos criptografados com segurança do Android não são mais compatíveis
O Android 9 remove completamente o suporte a arquivos criptografados seguros do Android (ASECs).
No Android 2.2 (nível 8 da API), o Android introduziu ASECs para oferecer suporte à funcionalidade de apps no cartão SD. No Android 6.0 (nível 23 da API), a plataforma apresentou uma tecnologia de dispositivo de armazenamento adotável que os desenvolvedores podem usar no lugar de ASECs.
Atualizações nas bibliotecas de ICU
O Android 9 usa a versão 60 da biblioteca ICU. O Android 8.0 (nível 26 da API) e o Android 8.1 (nível 27 da API) usam a ICU 58.
O ICU é usado para fornecer APIs públicas abaixo do android.icu package
e é usado internamente na plataforma Android para suporte à internacionalização.
Por exemplo, ele é usado para implementar classes do Android em java.util
, java.text
e android.text.format
.
A atualização para a ICU 60 contém muitas mudanças pequenas, mas úteis, incluindo suporte a dados Emoji 5.0 e formatos de data/hora aprimorados, conforme documentado nas notas da versão da ICU 59 e ICU 60.
Estas são algumas mudanças de destaque dessa atualização:
- A forma como a plataforma lida com os fusos horários mudou.
- A plataforma processa GMT e UTC melhor. O UTC não é mais um sinônimo de GMT.
A ICU agora fornece nomes de fusos traduzidos para GMT e UTC. Essa mudança afeta o comportamento de formatação e análise de
android.icu
para zonas como "GMT", "Etc/GMT", "UTC", "Etc/UTC" e "Zulu". - O
java.text.SimpleDateFormat
agora usa o ICU para fornecer nomes de exibição para UTC /GMT, ou seja:- A formatação de
zzzz
gera uma string localizada longa para muitas localidades. Anteriormente, ele produzia "UTC" para UTC e strings como "GMT+00:00" para GMT. - A análise
zzzz
reconhece strings como "Tempo Universal Coordenado" e "Tempo Médio de Greenwich". - Os apps podem ter problemas de compatibilidade se presumirem
que "UTC" ou "GMT+00:00" são a saída para
zzzz
em todos os idiomas.
- A formatação de
- O comportamento de
java.text.DateFormatSymbols.getZoneStrings()
mudou:- Assim como
SimpleDateFormat
, UTC e GMT agora têm nomes longos. As variantes de horário de verão dos nomes de fuso horário para o UTC, como "UTC", "Etc/UTC" e "Zulu", se tornam GMT+00:00, que é a alternativa padrão quando não há nomes disponíveis, em vez da stringUTC
codificada. - Alguns IDs de zona são reconhecidos corretamente como sinônimos de outras
zonas, para que o Android encontre strings para
IDs de zona arcaicas, como
Eire
, que antes não podiam ser resolvidas.
- Assim como
- Asia/Hanoi não é mais uma zona reconhecida. Por esse motivo,
java.util.TimeZones.getAvailableIds()
não retorna esse valor, ejava.util.TimeZone.getTimeZone()
não o reconhece. Esse comportamento é consistente com o comportamentoandroid.icu
atual.
- A plataforma processa GMT e UTC melhor. O UTC não é mais um sinônimo de GMT.
- O método
android.icu.text.NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String)
pode gerar umaParseException
mesmo ao analisar texto de moeda legítimo. Evite esse problema usandoNumberFormat.parseCurrency
, disponível desde o Android 7.0 (nível 24 da API), para o texto de moeda no estiloPLURALCURRENCYSTYLE
.
Mudanças no Android Test
O Android 9 introduz várias mudanças na biblioteca e na estrutura de classes do framework do Android Test. Essas mudanças ajudam os desenvolvedores a usar APIs públicas com suporte a framework, mas também permitem mais flexibilidade na criação e execução de testes usando bibliotecas de terceiros ou lógica personalizada.
Bibliotecas removidas do framework
O Android 9 reorganiza as classes baseadas em JUnit em três bibliotecas:
android.test.base, android.test.runner e android.test.mock.
Essa mudança permite executar testes em uma versão do JUnit que funciona melhor
com as dependências do projeto. Essa versão do JUnit pode ser diferente da
fornecida pelo android.jar
.
Para saber mais sobre como as classes baseadas em JUnit são organizadas nessas bibliotecas e como preparar o projeto do app para escrever e executar testes, consulte Configurar o projeto para o Android Test.
Testar mudanças no build do pacote de testes
O método addRequirements()
na classe
TestSuiteBuilder
foi removido, e a classe TestSuiteBuilder
foi descontinuada.
O método addRequirements()
exigia que os desenvolvedores fornecessem argumentos com
tipos de APIs ocultas, o que tornava a API inválida.
Decodificador UTF do Java
UTF-8 é o conjunto de caracteres padrão no Android. Uma sequência de bytes UTF-8 pode ser decodificada
por um construtor String
, como String(byte[] bytes)
.
O decodificador UTF-8 no Android 9 segue os padrões Unicode de maneira mais rigorosa do que nas versões anteriores. As mudanças são:
- A forma não mais curta de UTF-8, como
<C0, AF>
, é tratada como mal formada. - O formulário substituto do UTF-8, como
U+D800
..U+DFFF
, é tratado como malformado. - A subparte máxima é substituída por um único
U+FFFD
. Por exemplo, na sequência de bytes "41 C0 AF 41 F4 80 80 41
", as subpartes máximas são "C0
", "AF
" e "F4 80 80
". "F4 80 80
" pode ser a subseqência inicial de "F4 80 80 80
", mas "C0
" não pode ser a subseqência inicial de nenhuma sequência de unidade de código bem formada. Assim, a saída será "A\ufffd\ufffdA\ufffdA
". - Para decodificar uma sequência UTF-8 / CESU-8 modificada no Android 9 ou versões mais recentes, use o método
DataInputStream.readUTF()
ou o método JNINewStringUTF()
.
Verificação de nome de host usando um certificado
O RFC 2818 descreve dois
métodos para fazer a correspondência de um nome de domínio com um certificado: usando os nomes
disponíveis na extensão subjectAltName
(SAN
) ou, na ausência de uma
extensão SAN
, voltando para a commonName
(CN
).
No entanto, o fallback para CN
foi descontinuado no RFC 2818. Por esse motivo,
o Android não usa mais o CN
. Para verificar um nome de host, o servidor
precisa apresentar um certificado com um SAN
correspondente. Os certificados que não
contêm um SAN
correspondente ao nome do host não são mais confiáveis.
As pesquisas de endereço de rede podem causar violações de rede
As pesquisas de endereço de rede que exigem resolução de nome podem envolver E/S de rede e, portanto, são consideradas operações de bloqueio. Bloquear operações na linha de execução principal pode causar pausas ou instabilidade.
A classe StrictMode
é uma ferramenta de desenvolvimento que ajuda
os desenvolvedores a detectar problemas no código.
No Android 9 e versões mais recentes, o StrictMode
detecta violações
de rede causadas por pesquisas de endereços de rede que exigem resolução de nome.
Não envie seus apps com StrictMode
ativado. Se você fizer isso, seus
apps poderão ter exceções, como
NetworkOnMainThreadException
ao usar os métodos
detectNetwork()
ou
detectAll()
para receber uma
política que detecta violações de rede.
A resolução de um endereço IP numérico não é considerada uma operação de bloqueio. A resolução de endereço IP numérico funciona da mesma forma que nas versões anteriores ao Android 9.
Inclusão de tag de soquete
Em versões de plataforma anteriores ao Android 9, se um soquete for
marcado usando o
método setThreadStatsTag()
,
ele será desmarcado quando for enviado para outro processo usando
binder IPC
com um contêiner ParcelFileDescriptor
.
No Android 9 e versões mais recentes, a tag do socket é mantida quando enviada para outro
processo usando o IPC de vinculação. Essa mudança pode afetar as estatísticas de tráfego de rede, por
exemplo, ao usar o
método queryDetailsForUidTag()
.
Se você quiser manter o comportamento das versões anteriores, que removem as tags de um
soquete enviado para outro processo, chame
untagSocket()
antes de enviar o
soquete.
Quantidade informada de bytes disponíveis no socket
O método available()
retorna 0
quando é chamado
após invocar o método shutdownInput()
.
Relatórios mais detalhados sobre recursos de rede para VPNs
No Android 8.1 (nível 27 da API) e versões anteriores, a
classe NetworkCapabilities
só informava um conjunto limitado de
informações para VPNs, como
TRANSPORT_VPN
, mas omitindo
NET_CAPABILITY_NOT_VPN
. Essas informações limitadas
dificultou a determinação se o uso de uma VPN resultaria em cobranças
para o usuário do app. Por exemplo, a verificação de
NET_CAPABILITY_NOT_METERED
não
determinaria se as redes subjacentes foram medidas ou não.
No Android 9 e versões mais recentes, quando uma VPN chama o
método
setUnderlyingNetworks()
, o sistema Android mescla os transportes e os recursos de qualquer
rede subjacente e retorna o resultado como os recursos de rede efetivos
da rede VPN.
No Android 9 e versões mais recentes, os apps que já verificam
NET_CAPABILITY_NOT_METERED
recebem os recursos de rede da VPN e das
redes de suporte.
Os arquivos na pasta xt_qtaguid não estão mais disponíveis para apps.
A partir do Android 9, os apps não podem ter acesso de leitura
direto a arquivos na pasta /proc/net/xt_qtaguid
. O motivo é
garantir a consistência com alguns dispositivos que não têm esses arquivos.
As APIs públicas que dependem desses arquivos, TrafficStats
e
NetworkStatsManager
, continuam funcionando conforme o esperado.
No entanto, as funções
cutils
sem suporte, como
qtaguid_tagSocket()
,
podem não funcionar conforme o esperado ou nem funcionar em dispositivos diferentes.
O requisito FLAG_ACTIVITY_NEW_TASK agora é aplicado
No Android 9, não é possível iniciar uma atividade em um
contexto que não seja de atividade, a menos que você transmita a flag de intent
FLAG_ACTIVITY_NEW_TASK
.
Se você tentar iniciar uma atividade sem transmitir essa flag, a
atividade não será iniciada e o sistema vai imprimir uma mensagem no registro.
Mudanças na rotação da tela
A partir do Android 9, há mudanças significativas no modo de rotação retrato. No Android 8.0 (nível 26 da API), os usuários podiam alternar entre os modos de rotação automático e retrato usando um Bloco de configurações rápidas ou as configurações de exibição. O modo retrato foi renomeado para bloqueio de rotação e fica ativo quando o giro automático está desativado. Não há mudanças no modo de giro automático.
Quando o dispositivo está no modo de bloqueio de rotação, os usuários podem bloquear a tela para qualquer
rotação compatível com a atividade visível na parte de cima. Uma atividade não pode presumir
que será renderizada sempre no modo retrato. Se a atividade principal puder ser renderizada em
várias rotações no modo de rotação automática, as mesmas opções estarão disponíveis no
modo de rotação bloqueada, com algumas exceções com base na configuração
screenOrientation
da atividade (consulte a tabela abaixo).
Atividades que solicitam uma orientação específica (por exemplo,
screenOrientation=landscape
) ignoram a preferência de bloqueio do usuário e se comportam
da mesma forma que no Android 8.0.
A preferência de orientação da tela pode ser definida no nível da atividade no Android Manifest ou programaticamente com setRequestedOrientation().
O modo de bloqueio de rotação funciona definindo a preferência de rotação do usuário que o WindowManager usa ao processar a rotação da atividade. A preferência de rotação do usuário pode ser alterada nos seguintes casos. Há uma tendência de retornar à rotação natural do dispositivo, que normalmente é retrato para dispositivos com formato de smartphone:
- Quando o usuário aceita uma sugestão de rotação, a preferência de rotação muda para a sugestão.
- Quando o usuário alterna para um app forçado em modo retrato (incluindo a tela de bloqueio ou a tela de início), a preferência de rotação muda para retrato.
A tabela a seguir resume o comportamento de rotação para as orientações de tela comuns:
Orientação da tela | Comportamento |
---|---|
não especificado, usuário | No bloqueio de rotação e rotação automática, a atividade pode ser renderizada em modo retrato ou paisagem (e vice-versa). Espere oferecer suporte para layouts no modo retrato e no modo paisagem. |
userLandscape | No bloqueio de rotação e rotação automática, a atividade pode ser renderizada no modo paisagem ou paisagem invertida. Espere oferecer suporte apenas para layouts no modo paisagem. |
userPortrait | No bloqueio de rotação e rotação automática, a atividade pode ser renderizada em retrato ou retrato invertido. Espere oferecer suporte apenas para layouts no modo retrato. |
fullUser | No bloqueio de rotação e rotação automática, a atividade pode ser renderizada em modo retrato ou paisagem (e vice-versa). É necessário oferecer suporte aos layouts de retrato e paisagem. Os usuários com bloqueio de rotação têm a opção de bloquear o modo retrato invertido, geralmente 180º. |
sensor, fullSensor, sensorPortrait, sensorLandscape | A preferência do modo de bloqueio de rotação é ignorada e tratada como se a rotação automática estivesse ativa. Use isso somente em circunstâncias excepcionais considerando a experiência do usuário com muito cuidado. |
A suspensão de uso do cliente HTTP Apache afeta apps com ClassLoader não padrão
Com o Android 6.0,
removemos o suporte ao cliente Apache HTTP.
Essa mudança não afeta a grande maioria dos apps que não são destinados
ao Android 9 ou versões mais recentes. No entanto, a mudança pode afetar determinados apps que
usam uma estrutura ClassLoader
não padrão,
mesmo que não sejam destinados ao Android 9 ou versões mais recentes.
Um app pode ser afetado se usar uma ClassLoader
não padrão que delegue explicitamente
para a ClassLoader
do sistema. Esses apps precisam delegar ao app
ClassLoader
ao procurar classes em org.apache.http.*
. Se eles
delegarem para o ClassLoader
do sistema, os apps vão falhar no Android 9 ou versões mais recentes
com uma NoClassDefFoundError
,
porque essas classes não são mais conhecidas pelo ClassLoader
do sistema. Para
evitar problemas semelhantes no futuro, os apps precisam, em geral, carregar classes
pelo ClassLoader
do app em vez de acessar o ClassLoader
do sistema
diretamente.
Enumerar câmeras
Os apps executados em dispositivos Android 9 podem descobrir todas as câmeras disponíveis chamando
getCameraIdList()
.
Um app não pode presumir que o dispositivo tem apenas uma câmera traseira ou apenas uma
câmera frontal.
Por exemplo, se o app tiver um botão para alternar entre as câmeras frontal e traseira, talvez haja mais de uma câmera frontal ou traseira para escolher. Você precisa percorrer a lista de câmeras, examinar as características de cada uma e decidir quais câmeras serão expostas ao usuário.