O Android 9 (API de nível 28) introduz diversas mudanças ao sistema Android. As mudanças de comportamento a seguir se aplicam a todos os apps quando são executados na plataforma Android 9, independente do nível da API de destino. Todos os desenvolvedores precisam analisar essas mudanças e modificar os apps para que fiquem compatíveis com 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 introduz novos recursos para melhorar o gerenciamento de energia dos dispositivos. Essas mudanças, junto com os recursos que já estavam presentes antes do Android 9, ajudam a garantir que os recursos do sistema sejam disponibilizados aos apps que mais precisam deles.
Saiba mais detalhes em Gerenciamento de energia.
Mudanças de privacidade
Para melhorar a privacidade do usuário, o Android 9 introduz várias mudanças de comportamento, como limitar o acesso de apps em segundo plano aos sensores do dispositivo, restringir informações recuperadas de buscas por Wi-Fi e novas regras e grupos de permissões relacionados a chamadas telefônicas, 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 o acesso de apps em segundo plano aos dados do sensor e à entrada do usuário. Se o app estiver sendo executado em segundo plano em um dispositivo com o Android 9, o sistema aplicará as seguintes restrições a ele:
- O app não pode acessar o microfone ou 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 do sensor em dispositivos com o Android 9, use um serviço em primeiro plano.
Acesso restrito a 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. Nas versões anteriores do Android, essas permissões
ficavam no grupo de permissões PHONE
.
Esse grupo de permissões CALL_LOG
oferece aos usuários melhor controle e visibilidade para
apps que precisam de acesso a informações sensíveis sobre chamadas telefônicas, como
leitura de registros de chamadas e identificação de números de telefone.
Se o app exigir acesso a registros de chamadas ou processar chamadas realizadas, solicite essas permissões explicitamente do grupo de permissões CALL_LOG
. Caso contrário, vai ocorrer uma
SecurityException
.
Observação : como essas permissões mudaram de grupo e são concedidas em tempo de execução, é possível que o usuário negue o acesso do app às informações de registros de chamadas telefônicas. Nesse caso, seu app precisa ser capaz de lidar com a falta de acesso às informações de maneira prática.
Se o app já segue as práticas recomendadas de permissões de execução, ele pode processar a alteração 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 antes adquirir a permissão READ_CALL_LOG
, além das outras permissões exigidas pelos casos de uso do seu app.
Números de telefone associados a chamadas recebidas e realizadas ficam visíveis na
transmissão
pelo estado do telefone,
como para chamadas recebidas e realizadas, e podem ser acessados pela classe
PhoneStateListener
.
No entanto, sem a permissão
READ_CALL_LOG
, o campo do número de telefone fornecido nas
transmissões PHONE_STATE_CHANGED
e por PhoneStateListener
fica vazio.
Para ler números de telefone a partir do estado do telefone, atualize o app para solicitar as permissões necessárias com base no seu caso de uso:
- Para ler os números da ação
da intent
PHONE_STATE
, você precisa das permissõesREAD_CALL_LOG
eREAD_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 local e conexão de Wi-Fi
No Android 9, os requisitos de permissão para que um app execute buscas por Wi-Fi são mais rigorosos do que nas versões anteriores. Para ver detalhes, consulte Restrições de busca por 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 os valores do SSID e do BSSID se o app de chamada tiver as seguintes
permissões:
- ACCESS_FINE_LOCATION ou ACCESS_COARSE_LOCATION
- ACCESS_WIFI_STATE
Para extrair o SSID ou o BSSID, os Serviços de localização também precisam estar 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 a localização ou dados de identificação pessoal do usuário:
- 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
pelo Wi-Fi não contém mais SSID (anteriormente EXTRA_SSID),
BSSID (anteriormente EXTRA_BSSID) ou informações de conexão (anteriormente
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 fornecerão resultados:
Restrições para o uso de interfaces que não fazem parte do SDK
Para garantir a estabilidade e a compatibilidade do app, a plataforma restringe o uso de alguns métodos e campos não SDK. Essas restrições se aplicam se você tenta acessar esses métodos e campos diretamente, por reflexão ou usando JNI. No Android 9, seu app pode continuar acessando essas interfaces restritas. A plataforma usa avisos e entradas de registro para chamar sua atenção. Se o app mostrar esse aviso, é importante seguir uma estratégia de implementação diferente da interface restrita. Se você achar que nenhuma estratégia alternativa é viável, registre um bug para pedir a reconsideração da restrição.
O artigo Restrições para interfaces não SDK contém mais informações importantes. Analise esse documento para garantir que seu 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, independente da versão de destino dele.
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
não se conectar enquanto estiver sendo criada, o sistema vai gerar umaIOException
em vez de umaNullPointerException
. - A classe
SSLEngine
gerencia 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 rígido
O Android 9 restringe ainda mais as chamadas de sistema disponíveis aos aplicativos. Esse comportamento é uma extensão do filtro de 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 do Conscrypt de parâmetros e algoritmos
O Android 9 oferece outras implementações de parâmetros de algoritmo no Conscrypt (link em inglês). 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 a partir do Android 9.
Se o app for direcionado 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 o app for destinado ao Android 9, cada uma dessas solicitações 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 seu app não fornecer um, você receberá um aviso.
- A implementação do Conscrypt da criptografia ARC4 permite especificar ARC4/ECB/NoPadding ou ARC4/NONE/NoPadding.
- O provedor Crypto Java Cryptography Architecture (JCA) foi removido. Como
resultado, se o app chamar
SecureRandom.getInstance("SHA1PRNG", "Crypto")
, ocorrerá umaNoSuchProviderException
. - Se o app analisar as chaves RSA em buffers maiores que a estrutura da chave, uma exceção não ocorrerá mais.
Para saber mais sobre como usar os recursos criptográficos do Android, consulte Criptografia.
Arquivos criptografados protegidos pelo Android não têm mais suporte
O Android 9 remove completamente o suporte a arquivos criptografados protegidos pelo Android (ASECs, na sigla em inglês).
No Android 2.2 (nível 8 da API), o Android introduziu ASECs para oferecer suporte à funcionalidade de apps em cartão SD. No Android 6.0 (nível 23 da API), a plataforma lançou 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.
A ICU é usada para fornecer APIs públicas abaixo de android.icu package
e é usada internamente na Plataforma Android para suporte à internacionalização.
Por exemplo, ela é usada 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 o suporte a dados do Emoji 5.0 e os formatos aprimorados de data/hora, conforme documentado nas notas da versão da ICU 59 e 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 lida melhor com GMT e UTC. UTC não é mais 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". - A
java.text.SimpleDateFormat
agora usa a ICU para fornecer nomes de exibição para UTC /GMT, o que significa:- A formatação
zzzz
gera uma string longa localizada para muitas localidades. Antes, ela produzia "UTC" para UTC e strings como "GMT+00:00" para GMT. - A análise de
zzzz
reconhece strings como "Universal Coordinated Time" e "Greenwich Mean Time". - Os apps poderão ter problemas de compatibilidade se presumirem
que "UTC" ou "GMT+00:00" são saídas para
zzzz
em todos os idiomas.
- A formatação
- O comportamento de
java.text.DateFormatSymbols.getZoneStrings()
mudou:- Assim como em
SimpleDateFormat
, UTC e GMT agora têm nomes longos. As variantes de horário de verão dos nomes de fusos horários para a zona UTC, como "UTC", "Etc/UTC" e "Zulu", se tornam GMT+00:00, que é o substituto padrão quando não há nomes disponíveis, em vez da string codificadaUTC
. - Alguns IDs de zona são reconhecidos corretamente como sinônimos de outras
zonas, de modo que o Android encontra strings para
IDs de zona arcaicos, como
Eire
, que anteriormente não podiam ser resolvidos.
- Assim como em
- Ásia/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
existente.
- A plataforma lida melhor com GMT e UTC. UTC não é mais sinônimo de
GMT.
- O método
android.icu.text.NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String)
pode gerar umaParseException
mesmo ao analisar um texto de moeda legítimo. Evite esse problema usandoNumberFormat.parseCurrency
, disponível desde o Android 7.0 (API de nível 24), para 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 compatíveis com o 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 que você execute testes em uma versão do JUnit que funciona melhor
com as dependências do seu 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 programar e executar testes, consulte Configurar projetos para o Android Test.
Mudanças no build do pacote de testes
O método addRequirements()
na classe
TestSuiteBuilder
foi removido, e o uso da própria classe TestSuiteBuilder
foi descontinuado.
O método addRequirements()
exigia que os desenvolvedores fornecessem argumentos com
tipos que são APIs ocultas, o que tornava a API inválida.
Decodificador de UTF 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 com mais rigor 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 malformada. - A forma substituta de UTF-8, como
U+D800
..U+DFFF
, é tratada como se tivesse sido formada incorretamente. - A subparte máxima é substituída por uma única
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 subsequência inicial de "F4 80 80 80
", mas "C0
" não pode ser a subsequência inicial de qualquer sequência de unidade de código bem formada. Assim, a saída precisa 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 do host usando um certificado
A RFC 2818 (link em inglês) 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 commonName
(CN
).
No entanto, o substituto do CN
foi descontinuado na RFC 2818. Por esse motivo,
o Android não volta mais a usar 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.
Buscas de endereço de rede podem causar violações de rede
As pesquisas de endereços de rede que exigem resolução de nome podem envolver E/S de rede e, portanto, são consideradas operações de bloqueio. Operações de bloqueio na linha de execução principal podem 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, StrictMode
detecta violações
de rede causadas por pesquisas de endereço de rede que exigem resolução de nome.
Não envie seus apps com a StrictMode
ativada. Se você fizer isso, seus
apps poderão apresentar exceções, como
NetworkOnMainThreadException
, ao usar os métodos
detectNetwork()
ou
detectAll()
para receber uma
política que detecta violações de rede.
Resolver um endereço IP numérico não é considerado uma operação de bloqueio. A resolução numérica de endereços IP funciona da mesma forma que nas versões anteriores ao Android 9.
Inclusão de tag de soquete
Nas versões da 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 a
IPC de vinculação
com um contêiner ParcelFileDescriptor
.
No Android 9 e versões mais recentes, a tag de soquete é mantida quando ele é enviado para outro
processo usando um IPC binder. Essa alteração 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 desmarcam um soquete enviado para outro processo, chame untagSocket()
antes de enviar o soquete.
Quantidade informada de bytes disponíveis no soquete
O método available()
retorna 0
quando é chamado
depois de invocar o método shutdownInput()
.
Relatórios de recursos de rede mais detalhados para VPNs
No Android 8.1 (nível 27 da API) e versões anteriores, a
classe NetworkCapabilities
informava apenas um conjunto limitado de
informações para VPNs, como
TRANSPORT_VPN
, mas omitindo
NET_CAPABILITY_NOT_VPN
. Essa limitação
dificultava a determinação de se o uso de uma VPN resultaria em cobranças
para o usuário do app. Por exemplo, verificar
NET_CAPABILITY_NOT_METERED
não
determinaria se as redes são limitadas 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 a
NET_CAPABILITY_NOT_METERED
recebem os recursos de rede da VPN e das
redes subjacentes.
Os arquivos na pasta xt_qtaguid não estão mais disponíveis para apps
No Android 9 e versões mais recentes, os apps não podem ter acesso
direto de leitura aos 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 como esperado (ou não funcionar) em dispositivos diferentes.
O requisito FLAG_ACTIVITY_NEW_TASK agora foi aplicado.
Com o Android 9, não é possível iniciar uma atividade em um
contexto de não atividade, a menos que você transmita a flag de intent
FLAG_ACTIVITY_NEW_TASK
.
Se você tentar iniciar uma atividade sem transmitir essa flag, ela
não será iniciada, e o sistema vai mostrar uma mensagem no registro.
Mudanças na rotação da tela
No Android 9 e versões mais recentes, há mudanças significativas no modo de rotação retrato. No Android 8.0 (API de nível 26), os usuários podiam alternar entre os modos de rotação rotação automática e retrato usando um bloco do Quicksettings ou as configurações da tela. O modo retrato foi renomeado como bloqueio de rotação e fica ativo quando o giro automático é desativado. Não há mudanças no modo de rotação automática.
Quando o dispositivo está no modo de bloqueio de rotação, os usuários podem bloquear a tela em qualquer
rotação compatível com a atividade na parte de cima e visível. Uma atividade não pode presumir
que sempre será renderizada 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 vão estar disponíveis no
modo de rotação bloqueada, com algumas exceções baseadas 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 manifesto do Android ou de forma programática 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 casos a seguir. Há um viés de retorno à 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 na orientação retrato forçada (incluindo a tela de bloqueio ou a tela de início), a preferência de rotação muda para retrato.
A tabela abaixo resume o comportamento de rotação das orientações de tela comuns:
Orientação da tela | Comportamento |
---|---|
não especificado, usuário | Na rotação automática e no bloqueio de rotação, a atividade pode ser renderizada no modo retrato ou paisagem (e vice-versa). Espere oferecer suporte para layouts no modo retrato e no modo paisagem. |
UserLandscape | Na rotação automática e no bloqueio de rotação, a atividade pode ser renderizada no modo paisagem ou paisagem invertida. Espere oferecer suporte apenas para layouts no modo paisagem. |
Retrato | Na rotação automática e no bloqueio de rotação, a atividade pode ser renderizada em retrato ou retrato invertido. Espere oferecer suporte apenas para layouts no modo retrato. |
Usuário completo | Na rotação automática e no bloqueio de rotação, a atividade pode ser renderizada no modo retrato ou paisagem (e vice-versa). Ofereça suporte a layouts de retrato e paisagem. Os usuários de bloqueio de rotação terão a opção de bloquear para retrato invertido, geralmente 180o. |
sensor, fullSensor, sensorPortrait, sensorLandscape | A preferência do modo de bloqueio de rotação é ignorada e tratada como se o giro automático estivesse ativo. Use isso somente em circunstâncias excepcionais considerando a experiência do usuário com muito cuidado. |
A descontinuação do cliente Apache HTTP 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 direcionados
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 eles não sejam direcionados ao Android 9 ou versões mais recentes.
Um app pode ser afetado se usar um ClassLoader
não padrão que delega explicitamente
ao ClassLoader
do sistema. Esses apps precisam ser delegados ao app
ClassLoader
ao procurar classes em org.apache.http.*
. Se eles
delegarem ao 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, em geral, os apps precisam carregar classes
pelo ClassLoader
do app em vez de acessar o ClassLoader
do sistema diretamente.
Enumerar câmeras
Apps executados em dispositivos Android 9 podem descobrir todas as câmeras disponíveis chamando
getCameraIdList()
.
O app não pode presumir que o dispositivo tem apenas uma câmera traseira ou
uma frontal.
Por exemplo, se o app tiver um botão para alternar entre as câmeras frontal e traseira, pode haver mais de uma câmera frontal ou traseira para escolher. Analise a lista de câmeras, examine as características de cada uma e decida quais delas expor ao usuário.