Junto com novos recursos e funcionalidades, o Android 8.0 (nível 26 da API) inclui uma variedade de mudanças de comportamento do sistema e da API. Este documento destaca algumas das principais mudanças que você precisa entender e considerar nos seus apps.
A maioria dessas mudanças afeta todos os apps, independente da versão do Android ao qual eles são destinados. No entanto, várias mudanças afetam apenas os apps destinados ao Android 8.0. Para aumentar a clareza, esta página é dividida em duas seções: Mudanças para todos os apps e Mudanças para apps destinados ao Android 8.0.
Mudanças para todos os apps
Essas mudanças de comportamento se aplicam a
Background execution limits
Como uma das mudanças que o Android 8.0 (nível 26 da API) introduz para melhorar a duração da bateria, quando seu app entra no estado em cache, sem componentes ativos, o sistema libera todos os wakelocks que o app tiver.
Além disso, para melhorar o desempenho do dispositivo, o sistema limita alguns comportamentos de apps que não estão sendo executados em primeiro plano. Especificamente:
- Os apps em execução em segundo plano agora têm limites para a liberdade de acesso aos serviços em segundo plano.
- Os apps não podem usar os manifestos para se registrar para a maioria das transmissões implícitas, ou seja, transmissões que não são direcionadas especificamente para o app.
por padrão, essas restrições só se aplicam a aplicativos destinados ao Android O. No entanto, os usuários podem ativar essas restrições para qualquer app na tela Configurações, mesmo que o app não seja destinado ao O.
O Android 8.0 (API de nível 26) também inclui as seguintes mudanças em métodos específicos:
- O método
startService()
agora gera umaIllegalStateException
se um app destinado ao Android 8.0 tentar usar esse método em uma situação em que não é permitido criar serviços em segundo plano. - O novo método
Context.startForegroundService()
inicia um serviço em primeiro plano. O sistema permite que os apps chamemContext.startForegroundService()
mesmo quando estiverem em segundo plano. No entanto, o app precisa chamar o métodostartForeground()
desse serviço em até cinco segundos após a criação do serviço.
Para mais informações, consulte Limites de execução em segundo plano.
Limites da localização em segundo plano no Android
Para economizar bateria, experiência do usuário e integridade do sistema, os apps em segundo plano recebem atualizações de localização com menos frequência quando usados em um dispositivo com o Android 8.0. Essa mudança de comportamento afeta todos os apps que recebem atualizações de localização, incluindo o Google Play Services.
Essas mudanças afetam as seguintes APIs:
- Fused Location Provider (FLP)
- Fronteira geográfica virtual
- GNSS Measurements
- Location Manager
- Wi-Fi Manager
Para garantir que o aplicativo funcione como o esperado, faça o seguinte:
- Revise a lógica do app e verifique se você está usando as APIs Location mais recentes.
- Teste se o app exibe o comportamento esperado para cada caso de uso.
- Considere usar o provedor de localização combinada (FLP) ou a fronteira geográfica virtual para lidar com os casos de uso que dependem da localização atual do usuário.
Para mais informações sobre essas mudanças, consulte Limites da localização em segundo plano.
Atalhos de apps
O Android 8.0 (API de nível 26) inclui as seguintes mudanças nos atalhos de apps:
- A transmissão
com.android.launcher.action.INSTALL_SHORTCUT
não tem mais nenhum efeito no app, porque agora é implícita e privada. Em vez disso, crie um atalho de app usando o métodorequestPinShortcut()
da classeShortcutManager
. - A intent
ACTION_CREATE_SHORTCUT
agora pode criar atalhos de apps que você gerencia usando a classeShortcutManager
. Essa intent também pode criar atalhos legados da tela de início que não interagem comShortcutManager
. Antes, essa intent podia criar apenas atalhos legados da tela de início. - Os atalhos criados usando
requestPinShortcut()
e aqueles criados em uma atividade que processa a intentACTION_CREATE_SHORTCUT
agora são atalhos de app completos. Como resultado, os apps agora podem atualizá-los usando os métodos emShortcutManager
. - Os atalhos legados mantêm as funcionalidades das versões anteriores do Android, mas precisam ser convertidos em atalhos de apps manualmente no app.
Para saber mais sobre as mudanças nos atalhos de apps, consulte o guia de recursos Fixar atalhos e Widgets.
Localidades e internacionalização
O Android 7.0 (API de nível 24) introduziu o conceito de poder especificar uma localidade de categoria padrão, mas algumas APIs continuaram usando o método genérico Locale.getDefault()
, sem argumentos, quando deveriam ter usado a localidade de categoria DISPLAY
padrão. No Android 8.0 (API de nível 26), os
métodos a seguir agora usam Locale.getDefault(Category.DISPLAY)
em vez de Locale.getDefault()
:
Locale.getDisplayScript(Locale)
também
volta a Locale.getDefault()
quando o valor
displayScript especificado para o argumento Locale
não está disponível.
Veja a seguir outras mudanças relacionadas a localidade e internacionalização:
- Chamar
Currency.getDisplayName(null)
gera umaNullPointerException
, correspondente ao comportamento documentado. - A análise do nome do fuso horário mudou. Antes,
os dispositivos Android usavam o valor do relógio do sistema amostrado no momento da inicialização
para armazenar em cache os nomes de fuso horário usados para analisar e hora
de data. Como resultado, a análise poderia ser afetada negativamente se o relógio do sistema estivesse errado no momento da inicialização ou em outros casos mais raros.
Agora, em casos comuns, a lógica de análise usa ICU e o valor atual do relógio do sistema ao analisar nomes de fuso horário. Essa mudança fornece resultados mais corretos, que podem ser diferentes de versões anteriores do Android quando o app usa classes como
SimpleDateFormat
. - O Android 8.0 (API de nível 26) atualiza a versão da ICU para a versão 58.
Janelas de alerta
Se um app usar a permissão
SYSTEM_ALERT_WINDOW
e um dos tipos de janela abaixo para tentar mostrar
janelas de alerta acima de outros apps e janelas do sistema:
Essas janelas sempre vão aparecer abaixo das
que usam o
tipo de janela TYPE_APPLICATION_OVERLAY
. Se um app for direcionado ao Android 8.0 (nível 26 da API), ele vai usar o
tipo de janela TYPE_APPLICATION_OVERLAY
para mostrar janelas de alerta.
Para mais informações, consulte a seção Tipos de janela comuns para janelas de alerta nas mudanças de comportamento para Apps destinados ao Android 8.0.
Interação e navegação
Com o advento dos apps Android no ChromeOS e em outros formatos grandes, como tablets, estamos vendo um ressurgimento do uso da navegação pelo teclado em apps Android. No Android 8.0 (nível 26 da API), abordamos novamente o uso do teclado como dispositivo de entrada de navegação, resultando em um modelo mais confiável e previsível para navegação baseada em setas e guias.
Especificamente, fizemos as seguintes mudanças no comportamento de foco no elemento:
-
Se você não tiver definido nenhuma cor de estado de foco para um objeto
View
(seja um drawable de primeiro ou segundo plano), o framework agora vai definir uma cor de destaque de foco padrão paraView
. Esse destaque de foco é um drawable de ondulação baseado no tema da atividade.Se você não quiser que um objeto
View
use esse destaque padrão quando receber o foco, defina o atributoandroid:defaultFocusHighlightEnabled
comofalse
no arquivo XML do layout que contém oView
ou transmitafalse
parasetDefaultFocusHighlightEnabled()
na lógica da interface do seu app. - Para testar como a entrada do teclado afeta o foco do elemento da IU, ative a opção de desenvolvedor Drawing > Show layout bounds. No Android 8.0, essa opção exibe um ícone "X" sobre o elemento em foco no momento.
Além disso, todos os elementos da barra de ferramentas no Android 8.0 são clusters de navegação com teclado automaticamente, facilitando a navegação dos usuários para dentro e para fora de cada barra de ferramentas como um todo.
Para saber mais sobre como melhorar o suporte à navegação pelo teclado do app, leia o guia Suporte à navegação pelo teclado.
Preenchimento automático de formulários Web
Agora que o Framework
de preenchimento automático do Android oferece suporte integrado à funcionalidade de preenchimento automático, os
seguintes métodos relacionados a objetos WebView
mudaram
para apps instalados em dispositivos com o Android 8.0 (nível 26 da API):
WebSettings
-
- O método
getSaveFormData()
agora retornafalse
. Anteriormente, esse método retornavatrue
. - Chamar
setSaveFormData()
não mais tem efeito.
- O método
WebViewDatabase
-
- Chamar
clearFormData()
não mais tem efeito. - O
método
hasFormData()
agora retornafalse
. Anteriormente, esse método retornavatrue
quando o formulário continha dados.
- Chamar
Acessibilidade
O Android 8.0 (API de nível 26) inclui as seguintes alterações de acessibilidade:
-
O framework de acessibilidade agora converte todos os gestos de toque duplo em ações
ACTION_CLICK
. Essa mudança permite que o TalkBack se comporte mais como outros serviços de acessibilidade.Caso os objetos
View
do seu app usem o processamento de toque personalizado, verifique se eles ainda funcionam com o TalkBack. Talvez seja necessário registrar o gerenciador de cliques usado pelos objetosView
. Se o TalkBack ainda não reconhecer os gestos realizados nesses objetosView
, modifiqueperformAccessibilityAction()
. - Os serviços de acessibilidade agora reconhecem todas as
instâncias de
ClickableSpan
nos objetosTextView
do seu app.
Para saber mais sobre como tornar seu app mais acessível, consulte Acessibilidade.
Redes e conectividade HTTP(S)
O Android 8.0 (API de nível 26) inclui as seguintes mudanças de comportamento na rede e na conectividade HTTP(S):
- As solicitações OPTIONS sem "body" têm um cabeçalho
Content-Length: 0
. Anteriormente, elas não tinham cabeçalhoContent-Length
. - HttpURLConnection normaliza URLs que contêm caminhos vazios anexando
uma barra após o nome do host ou da autoridade com uma barra. Por exemplo, ele
converte
http://example.com
emhttp://example.com/
. - Um seletor de proxy personalizado definido via ProxySelector.setDefault() só segmenta o endereço (esquema, host e porta) de um URL solicitado. Com isso, a seleção de proxy pode se basear apenas nesses valores. Um URL transmitido para um seletor de proxy personalizado não inclui o caminho, os parâmetros de consulta ou os fragmentos do URL solicitado.
- OS URIs não podem conter rótulos vazios.
Anteriormente, a plataforma oferecia uma solução alternativa para aceitar rótulos vazios em nomes de host, o que é um uso ilegal de URIs. Essa solução alternativa foi usada para compatibilidade com versões mais antigas da libcore. Os desenvolvedores que usam a API incorretamente veriam uma mensagem ADB: "URI example..com tem rótulos vazios no nome do host. Isso está incorreto e não será aceito em versões futuras do Android." O Android 8.0 remove essa solução alternativa. O sistema retorna nulo para URIs malformados.
- A implementação de HttpsURLConnection do Android 8.0 não executa substituto inseguro da versão do protocolo TLS/SSL.
- O processamento de conexões HTTP(S) de encapsulamento foi alterado da seguinte maneira:
- Ao encapsular a conexão HTTPS por conexão, o sistema coloca corretamente o número da porta (:443) na linha do host ao enviar essas informações para um servidor intermediário. Anteriormente, o número da porta só aparecia na linha CONNECT.
- O sistema não envia mais cabeçalhos de user agent e autorização de proxy
de uma solicitação encapsulada ao servidor proxy.
O sistema não envia mais um cabeçalho de autorização de proxy em uma Http(s)URLConnection encapsulada ao proxy ao configurar o túnel. Em vez disso, o sistema gera um cabeçalho de autorização de proxy e o envia ao proxy quando ele envia HTTP 407 em resposta à solicitação inicial.
Da mesma forma, o sistema não copia mais o cabeçalho do user agent da solicitação encapsulada para a solicitação de proxy que configura o túnel. Em vez disso, a biblioteca gera um cabeçalho de user agent para essa solicitação.
- O método
send(java.net.DatagramPacket)
gerará uma SocketException se o método connect() executado anteriormente falhar.- DatagramSocket.connect() vai definir umaçaPendingSocketException quando houver um erro interno. Antes do Android 8.0, uma chamada de recv() subsequente gerava uma SocketException, mesmo que uma chamada send() tivesse sido bem-sucedida. Para dar mais consistência, ambas as chamadas agora geram uma SocketException.
- InetAddress.isReachable() tenta o ICMP antes de retornar ao protocolo TCP Echo.
- Alguns hosts que bloqueiam a porta 7 (Echo TCP), como google.com, podem agora ficar acessíveis se aceitarem o protocolo ICMP Echo.
- Para hosts realmente inacessíveis, essa mudança significa que o dobro do tempo é gasto antes do retorno da chamada.
Bluetooth
O Android 8.0 (API de nível 26) faz as seguintes mudanças no comprimento dos dados que o método ScanRecord.getBytes()
recupera:
- O método
getBytes()
não presume o número de bytes recebidos. Portanto, os apps não podem depender de nenhum número mínimo ou máximo de bytes retornados. Em vez disso, eles devem avaliar o comprimento da matriz resultante. - Dispositivos compatíveis com Bluetooth 5 podem retornar comprimento de dados que exceda o máximo anterior de cerca de 60 bytes.
- Se um dispositivo remoto não fornecer uma resposta de verificação, talvez menos de 60 bytes sejam retornados.
Conectividade uniforme
O Android 8.0 (nível 26 da API) faz várias melhorias nas configurações de Wi-Fi para facilitar a escolha da rede Wi-Fi que oferece a melhor experiência do usuário. Mudanças específicas incluem:
- Melhorias de estabilidade e confiabilidade.
- Uma IU de leitura mais intuitiva.
- Um só menu consolidado de preferências de Wi-Fi.
- Em dispositivos compatíveis, ativação automática do Wi-Fi quando uma rede salva de alta qualidade estiver próxima.
Segurança
O Android 8.0 inclui as seguintes alterações relacionadas à segurança:
- A plataforma não oferece mais suporte a SSLv3.
- Ao estabelecer uma conexão HTTPS com um servidor que implementa incorretamente a negociação da versão do protocolo TLS, o
HttpsURLConnection
não tenta mais a solução alternativa de recorrer a versões anteriores do protocolo TLS e tentar novamente. - O Android 8.0 (API de nível 26) aplica um filtro de computação segura (SECCOMP, na sigla em inglês) a todos os apps. A lista de chamadas do sistema permitidas é restrita às expostas pelo Bionic. Embora existam várias outras chamadas do sistema fornecidas para compatibilidade com versões anteriores, recomendamos não usá-las.
- Os objetos
WebView
do seu app agora são executados no modo multiprocesso. O conteúdo da Web é processado em um processo separado e isolado do processo do app que o contém para aumentar a segurança. -
Não é mais possível presumir que os APKs estejam em diretórios com nomes terminados
em -1 ou -2. Os apps precisam usar
sourceDir
para acessar o diretório e não depender diretamente do formato de diretório. - Para saber mais sobre melhorias de segurança relacionadas ao uso de bibliotecas nativas, consulte Bibliotecas nativas.
Além disso, o Android 8.0 (nível 26 da API) introduz as seguintes mudanças relacionadas à instalação de apps desconhecidos de fontes desconhecidas:
- O valor da configuração legada
INSTALL_NON_MARKET_APPS
agora é sempre 1. Para determinar se uma fonte desconhecida pode instalar apps usando o instalador do pacote, use o valor de retorno decanRequestPackageInstalls()
. - Se você tentar mudar o valor de
INSTALL_NON_MARKET_APPS
usandosetSecureSetting()
, umaUnsupportedOperationException
será gerada. Para evitar que os usuários instalem apps desconhecidos com fontes desconhecidas, aplique a restrição de usuárioDISALLOW_INSTALL_UNKNOWN_SOURCES
. -
Perfis gerenciados criados em dispositivos com o Android 8.0 (nível 26 da API) têm a
restrição de usuário
DISALLOW_INSTALL_UNKNOWN_SOURCES
ativada automaticamente. Para perfis gerenciados existentes em dispositivos atualizados para o Android 8.0, a restrição de usuárioDISALLOW_INSTALL_UNKNOWN_SOURCES
será ativada automaticamente, a menos que o proprietário do perfil tenha desativado explicitamente essa restrição (antes de fazer upgrade) definindoINSTALL_NON_MARKET_APPS
como 1.
Para mais detalhes sobre a instalação de apps desconhecidos, consulte o guia Permissões de instalação de app desconhecidas.
Para ver outras diretrizes sobre como tornar seu app mais seguro, consulte Segurança para desenvolvedores Android.
Privacidade
O Android 8.0 (nível 26 da API) faz as seguintes mudanças relacionadas à privacidade na plataforma:
- Agora, a plataforma gerencia identificadores de forma diferente.
-
Para apps instalados antes de um OTA para uma versão do
Android 8.0 (nível 26 da API)
(nível 26 da API), o valor de
ANDROID_ID
permanece o mesmo, a menos que seja desinstalado e reinstalado após o OTA. Para preservar os valores entre desinstalações após o OTA, os desenvolvedores podem associar os valores antigos e novos usando o Backup de chave-valor. - Para apps instalados em um dispositivo com o Android 8.0, o valor de
ANDROID_ID
agora é delimitado por chave de assinatura do app e por usuário. O valor deANDROID_ID
é exclusivo para cada combinação de chave de assinatura do app, usuário e dispositivo. Como resultado, apps com diferentes chaves de assinatura executados no mesmo dispositivo não veem mais o mesmo ID do Android, mesmo para o mesmo usuário. - O valor de
ANDROID_ID
não muda na desinstalação ou reinstalação do pacote, desde que a chave de assinatura seja a mesma (e o app não tenha sido instalado antes de um OTA para uma versão do Android 8.0). - O valor de
ANDROID_ID
não muda, mesmo que uma atualização do sistema faça com que a chave de assinatura do pacote mude. - Em dispositivos que incluem o Google Play Services e o ID de publicidade,
é necessário usar o
ID de publicidade. O ID de publicidade é um ID exclusivo e reconfigurável pelo usuário para publicidade,
que é um sistema simples e padrão para gerar receita com apps. Ele é fornecido
pelo Google Play Services.
Outros fabricantes de dispositivos precisam continuar a fornecer
ANDROID_ID
.
-
Para apps instalados antes de um OTA para uma versão do
Android 8.0 (nível 26 da API)
(nível 26 da API), o valor de
- Consultar a propriedade do sistema
net.hostname
produz um resultado nulo.
Registro de exceções não capturadas
Se um app instalar um Thread.UncaughtExceptionHandler
que
não faz chamadas para o Thread.UncaughtExceptionHandler
padrão,
o sistema não
elimina o app quando ocorrer uma exceção não capturada. No
Android 8.0 (nível 26 da API) e versões mais recentes, o sistema registra o stack trace de exceção.
Em versões anteriores da plataforma, o sistema não teria
registrado o stack trace de exceção.
Recomendamos que as implementações personalizadas de Thread.UncaughtExceptionHandler
sempre chamem o gerenciador padrão. Os apps que seguirem essa recomendação não serão afetados pela
mudança do Android 8.0.
Mudança de assinatura findViewById()
Todas as instâncias do método findViewById()
agora retornam
<T extends View> T
, em vez de View
. Essa mudança
tem as seguintes implicações:
- Isso pode fazer com que o código existente agora tenha um tipo de retorno ambíguo,
por exemplo, se houver
someMethod(View)
esomeMethod(TextView)
que usam o resultado de uma chamada parafindViewById()
. - Ao usar a linguagem de origem Java 8, isso exige uma transmissão explícita para
View
quando o tipo de retorno não tem restrições (por exemplo,assertNotNull(findViewById(...)).someViewMethod())
). - As substituições de métodos
findViewById()
não finais (por exemplo,Activity.findViewById()
) precisarão que o tipo de retorno seja atualizado.
Mudança de estado de uso do provedor de contatos
Nas versões anteriores do Android, o componente Provedor de contatos
permite que os desenvolvedores coletem dados de uso para cada contato. Esses dados de uso expõem informações de cada endereço de e-mail e número de telefone associado a um contato, incluindo o número de vezes que o contato foi contatado e a última vez com que foi contatado. Os apps que solicitam a permissão
READ_CONTACTS
podem ler esses dados.
Os apps ainda poderão ler esses dados se solicitarem a
permissão
READ_CONTACTS
. No Android 8.0 (API de nível 26) e versões mais recentes, as consultas para dados de uso retornam
aproximações, em vez de valores exatos. O sistema Android mantém os valores exatos internamente, então essa mudança não afeta a API de preenchimento automático.
Essa mudança de comportamento afeta os seguintes parâmetros de consulta:
Gerenciamento de coleta
AbstractCollection.removeAll()
e AbstractCollection.retainAll()
agora sempre geram uma NullPointerException
. Anteriormente, o
NullPointerException
não era gerado quando a coleção estava
vazia Essa mudança deixa o comportamento mais coerente com a documentação.
Android empresarial
O Android 8.0 (nível 26 da API) muda o comportamento de algumas APIs e recursos para apps corporativos, incluindo os controladores de política de dispositivo (DPCs). As mudanças incluem:
- Novos comportamentos para ajudar os aplicativos a dar suporte a perfis de trabalho em dispositivos totalmente gerenciados.
- Mudanças no gerenciamento de atualizações do sistema, verificação de apps e autenticação para aumentar a integridade do dispositivo e do sistema.
- Melhorias na experiência do usuário para provisionamento, notificações, tela "Recentes" e VPN sempre ativa.
Para ver todas as mudanças corporativas no Android 8.0 (nível 26 da API) e saber como elas podem afetar seu app, leia Android no Enterprise.
Apps destinados ao Android 8.0
Essas mudanças de comportamento se aplicam exclusivamente a apps destinados ao
Android 8.0 (API de nível 26) ou versões mais recentes. Apps compilados com o Android 8.0
ou com a definição targetSdkVersion
para o Android 8.0 ou versão mais recente precisam ser modificados
para oferecer suporte a esses comportamentos de forma adequada, quando aplicável.
Janelas de alerta
Apps que usam a permissão SYSTEM_ALERT_WINDOW
não podem mais usar os tipos de janela abaixo para mostrar janelas de alerta
acima de outros apps e janelas do sistema:
Em vez disso, os apps precisam usar um novo tipo de janela chamado
TYPE_APPLICATION_OVERLAY
.
Ao usar o
tipo de janela TYPE_APPLICATION_OVERLAY
para exibir janelas de alerta para seu app, lembre-se das seguintes características
do novo tipo de janela:
- As janelas de alerta de um app sempre aparecem sob janelas críticas do sistema, como a barra de status e os IMEs.
- O sistema pode mover ou redimensionar janelas que usam o
tipo de janela
TYPE_APPLICATION_OVERLAY
para melhorar a apresentação na tela. - Ao abrir a aba de notificações, os usuários podem acessar as configurações para bloquear
a exibição de janelas de alerta por um app usando o
tipo de janela
TYPE_APPLICATION_OVERLAY
.
Notificações de alteração de conteúdo
O Android 8.0 (nível 26 da API) muda o comportamento
de ContentResolver.notifyChange()
e registerContentObserver(Uri, boolean, ContentObserver)
para apps destinados ao Android 8.0.
Essas APIs agora exigem que um ContentProvider
válido seja definido para a autoridade em todos os URIs. Definir um ContentProvider
válido com permissões relevantes ajuda
a proteger o app contra mudanças de conteúdo por parte de apps maliciosos e evita o
vazamento de dados particulares para apps maliciosos.
Foco de visualização
Objetos View
clicáveis agora também podem ser focados por
padrão Caso você queira que um objeto View
seja clicável, mas não
focalizável, defina o atributo
android:focusable
como false
no arquivo
XML do layout que contém o View
ou transmita false
para setFocusable()
na lógica da interface
do app.
Correspondência de user agent na detecção do navegador
O Android 8.0 (nível 26 da API) e versões mais recentes incluem a
string do identificador de build OPR
. Algumas correspondências de padrões podem
fazer com que a lógica de detecção do navegador identifique incorretamente um navegador que não é o Opera.
Um exemplo desse tipo de correspondência de padrão seria:
if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}
Para evitar problemas decorrentes dessa identificação incorreta, use uma string diferente de
OPR
como uma correspondência de padrão para o navegador Opera.
Segurança
As seguintes mudanças afetam a segurança no Android 8.0 (API de nível 26):
- Se a configuração de segurança de rede do app
não
oferecer suporte ao tráfego de texto não criptografado, os objetos
WebView
do app não poderão acessar sites por HTTP. Cada objetoWebView
precisa usar HTTPS. - A configuração do sistema Permitir fontes desconhecidas foi removida. No lugar dela, a permissão Instalar apps desconhecidos gerencia instalações de apps desconhecidas de fontes desconhecidas. Para saber mais sobre essa nova permissão, consulte o guia Permissões de instalação de app desconhecidas.
Para ver outras diretrizes sobre como tornar seu app mais seguro, consulte Segurança para desenvolvedores Android.
Detectabilidade e acesso a contas
No Android 8.0 (nível 26 da API), os apps não podem mais acessar
contas de usuário, a menos que o autenticador seja proprietário das contas ou o
usuário conceda esse acesso. A
permissão GET_ACCOUNTS
não é mais suficiente. Para receber acesso a uma conta, os apps precisam
usar AccountManager.newChooseAccountIntent()
ou um método específico do
autenticador. Depois de receber o acesso às contas, o app pode chamar
AccountManager.getAccounts()
para acessá-las.
O Android 8.0 descontinua a
LOGIN_ACCOUNTS_CHANGED_ACTION
. Em vez disso,
os apps precisam usar
addOnAccountsUpdatedListener()
para receber atualizações sobre contas durante a execução.
Para informações sobre novas APIs e métodos adicionados para acesso e detecção de contas, consulte Detecção e acesso à conta na seção "Novas APIs" deste documento.
Privacidade
As mudanças a seguir afetam a privacidade no Android 8.0 (API de nível 26).
-
As propriedades do sistema
net.dns1
,net.dns2
,net.dns3
enet.dns4
não estão mais disponíveis, uma mudança que melhora a privacidade na plataforma. -
Para acessar informações de rede, como servidores DNS, os apps com
a permissão
ACCESS_NETWORK_STATE
podem registrar um objetoNetworkRequest
ouNetworkCallback
. Essas classes estão disponíveis no Android 5.0 (API de nível 21) e em versões posteriores. -
Build.SERIAL está obsoleta.
Os apps que precisam saber o número de série do hardware precisam
usar o novo método
Build.getSerial()
, que exige a permissãoREAD_PHONE_STATE
. -
A API
LauncherApps
não permite mais que os apps do perfil de trabalho recebam informações sobre o perfil principal. Quando um usuário está em um perfil de trabalho, a APILauncherApps
se comporta como se não houvesse apps instalados em outros perfis do mesmo grupo. Como antes, tentativas de acessar perfis não relacionados causam SecurityExceptions.
Permissões
Em versões anteriores ao Android 8.0 (API de nível 26), se um app solicitava uma permissão no momento da execução e ela era concedida, o sistema também concedeva incorretamente ao app as outras permissões que pertenciam ao mesmo grupo de permissões e que estavam registradas no manifesto.
Em apps destinados ao Android 8.0, esse comportamento foi corrigido. O app recebe apenas as permissões que ele solicitou explicitamente. No entanto, depois que o usuário concede uma permissão ao app, todas as solicitações subsequentes para permissões nesse grupo de permissões são concedidas automaticamente.
Por exemplo, suponha que um app liste READ_EXTERNAL_STORAGE
e WRITE_EXTERNAL_STORAGE
no manifesto.
O app solicita READ_EXTERNAL_STORAGE
e
o usuário a concede. Se o app for direcionado ao nível 25 da API ou a versões anteriores, o sistema também
concederá WRITE_EXTERNAL_STORAGE
ao mesmo
tempo, porque ele pertence ao mesmo grupo de permissões STORAGE
e também está
registrado no manifesto. Se o app for direcionado ao Android 8.0 (API de nível 26), o sistema concederá apenas READ_EXTERNAL_STORAGE
no momento. No entanto, se o app solicitar WRITE_EXTERNAL_STORAGE
posteriormente, o sistema concederá imediatamente esse privilégio sem notificar o usuário.
Mídia
- O framework pode executar
redução automática de áudio
sozinho. Nesse caso, quando outro app solicita a seleção com
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
, o app em foco reduz o volume, mas geralmente não recebe um callbackonAudioFocusChange()
e não perde a seleção de áudio. Há novas APIs disponíveis para modificar esse comportamento no caso de aplicativos que precisam pausar em vez de reduzir. - Quando o usuário recebe uma chamada telefônica, os streams de mídia ativos são silenciados durante a chamada.
- Todas as APIs relacionadas a áudio precisam usar
AudioAttributes
em vez de tipos de stream de áudio para descrever o caso de uso de reprodução de áudio. Continue a usar tipos de stream de áudio somente para controles de volume. Outros usos de tipos de stream ainda funcionam, por exemplo, o argumentostreamType
para o construtorAudioTrack
descontinuado, mas o sistema registra isso como um erro. - Ao usar um
AudioTrack
, se o aplicativo solicitar um buffer de áudio grande o suficiente, o framework vai tentar usar a saída do buffer profundo, se ela estiver disponível. - No Android 8.0 (API de nível 26), o processamento de eventos do botão de mídia é diferente:
- O gerenciamento de botões de mídia em uma atividade da interface não mudou: as atividades em primeiro plano ainda têm prioridade no processamento de eventos do botão de mídia.
- Se a atividade em primeiro plano não processar o evento do botão de mídia, o sistema vai encaminhar o evento para o app que reproduziu áudio localmente por último. O status ativo, as sinalizações e o estado de reprodução de uma sessão de mídia não são considerados ao determinar qual app recebe eventos do botão de mídia.
- Se a sessão de mídia do app tiver sido liberada,
o sistema vai enviar o evento do botão de mídia para o
MediaButtonReceiver
do app, se houver um. - Para todos os demais casos de uso, o sistema descarta o evento de botão de mídia.
Bibliotecas nativas
Em apps destinados ao Android 8.0 (nível 26 da API), as bibliotecas nativas não são mais carregadas se tiverem algum segmento de carregamento que seja gravável e executável. Alguns apps podem parar de funcionar devido a essa mudança se tiverem bibliotecas nativas com segmentos de carregamento incorretos. Essa é uma medida de aumento da segurança.
Para saber mais, consulte Segmentos graváveis e executáveis.
As mudanças no vinculador são ligadas ao nível da API com que o aplicativo visa a trabalhar. Se houver uma mudança no vinculador no nível da API de destino, o app não vai poder carregar a biblioteca. Se você estiver segmentando uma API de nível inferior ao da API em que ocorre a alteração do vinculador, o logcat mostrará um aviso.
Gerenciamento de coleta
No Android 8.0 (API de nível 26),
a Collections.sort()
é implementada
com base em List.sort()
. O contrário
era verdadeiro no Android 7.x (API de níveis 24 e 25):
a implementação padrão de List.sort()
denominou Collections.sort()
.
Essa mudança permite que Collections.sort()
aproveite as implementações otimizadas de List.sort()
, mas tem as seguintes restrições:
As implementações de
List.sort()
não podem chamarCollections.sort()
, porque isso resultaria em estouro de pilha devido a recursão infinita. Em vez disso, se você quiser o comportamento padrão na implementação doList
, evite modificarsort()
.Se uma classe mãe implementar
sort()
de forma inadequada, normalmente não há problema em substituirList.sort()
por uma implementação criada com base emList.toArray()
,Arrays.sort()
eListIterator.set()
. Por exemplo:@Override public void sort(Comparator<? super E> c) { Object[] elements = toArray(); Arrays.sort(elements, c); ListIterator<E> iterator = (ListIterator<Object>) listIterator(); for (Object element : elements) { iterator.next(); iterator.set((E) element); } }
Na maioria dos casos, você também pode substituir
List.sort()
por uma implementação que delega a diferentes implementações padrão, dependendo do nível da API. Por exemplo:@Override public void sort(Comparator<? super E> comparator) { if (Build.VERSION.SDK_INT <= 25) { Collections.sort(this); } else { super.sort(comparator); } }
Se você estiver fazendo o último caso só porque quer ter um método
sort()
disponível em todos os níveis da API, dê a ele um nome exclusivo, comosortCompat()
, em vez de substituirsort()
.-
Collections.sort()
agora conta como uma modificação estrutural nas implementações de List que chamamsort()
Por exemplo, em versões da plataforma anteriores ao Android 8.0 (API de nível 26), a iteração sobre umaArrayList
e a chamada desort()
no meio da iteração geraria umaConcurrentModificationException
se a ordenação fosse feita chamandoList.sort()
.Collections.sort()
não gerou uma exceção.Essa mudança torna o comportamento da plataforma mais consistente: qualquer uma das abordagens agora resulta em uma
ConcurrentModificationException
.
Comportamento de carregamento de classe
O Android 8.0 (API de nível 26) verifica se os carregadores de classes não quebram as suposições do tempo de execução ao carregar novas classes. Essas verificações são
realizadas se a classe é referenciada em Java (em
forName()
),
bytecodes Dalvik ou JNI. A plataforma não intercepta chamadas diretas do Java para o
método loadClass()
nem verifica
os resultados dessas chamadas. Esse comportamento não afeta o funcionamento de carregadores de classe
com comportamento adequado.
A plataforma verifica se o descritor da classe retornada pelo carregador de classes
corresponde ao descritor esperado. Se o descritor retornado não corresponder,
a plataforma gerará um erro NoClassDefFoundError
e armazenará na
exceção uma mensagem detalhada observando a discrepância.
A plataforma também analisa se os descritores das classes solicitadas são válidos. Essa
verificação captura chamadas JNI que carregam indiretamente classes como GetFieldID()
,
transmitindo descritores inválidos para essas classes. Por exemplo, um campo com a assinatura
java/lang/String
não é encontrado porque essa assinatura é inválida.
Ela precisa ser Ljava/lang/String;
.
Isso é diferente de uma chamada JNI para FindClass()
,
em que java/lang/String
é um nome totalmente qualificado válido.
O Android 8.0 (API de nível 26) não é compatível com vários carregadores de classe tentando definir classes
usando o mesmo objeto DexFile. Uma tentativa de fazer isso faz com que o ambiente de execução do Android gere um erro
InternalError
com a mensagem "Tentativa de registrar o arquivo dex <filename>
com vários carregadores de classes".
A API DexFile foi descontinuada, e é altamente recomendável usar
um dos carregadores de classe da plataforma, incluindo PathClassLoader
ou
BaseDexClassLoader
.
Observação : é possível criar vários carregadores de classes que fazem referência ao
mesmo contêiner de arquivos APK ou JAR do sistema de arquivos. Isso normalmente não
resulta em muita sobrecarga da memória: se os arquivos DEX no contêiner forem armazenados em vez de
compactados, a plataforma poderá executar uma operação mmap
neles em vez de
extraí-los diretamente. No entanto, se a plataforma precisar extrair o arquivo DEX do contêiner,
fazer referência a um arquivo DEX dessa maneira poderá consumir muita memória.
No Android, todos os carregadores de classe são considerados passíveis de paralelismo. Quando várias linhas de execução disputam para carregar a mesma classe com o mesmo carregador de classes, a primeira linha a concluir a operação vence, e o resultado é usado para as outras linhas de execução. Esse comportamento ocorre independentemente de o carregador de classes ter retornado a mesma classe, retornado uma classe diferente ou gerado uma exceção. A plataforma ignora essas exceções silenciosamente.
Cuidado : em versões da plataforma anteriores ao Android 8.0 (API de nível 26), quebrar essas suposições pode levar à definição da mesma classe várias vezes, corrupção de heap devido à confusão de classes e outros efeitos indesejáveis.