Junto com novos recursos e funcionalidades, o Android 8.0 (API de nível 26) 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 a que eles se destinam. No entanto, várias mudanças afetam apenas os apps destinados ao Android 8.0. Para maximizar 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 (API de nível 26) introduz para melhorar a duração da bateria, quando seu app entra no estado em cache, sem componentes ativos, o sistema libera todos os wake locks que o app tem.
Além disso, para melhorar a performance do dispositivo, o sistema limita determinados comportamentos de apps que não estão em execução em primeiro plano. Especificamente:
- Agora, os apps executados em segundo plano têm limites quanto à liberdade de acesso a 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 Settings, 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.
- Verifique se o app exibe o comportamento esperado para cada caso de uso.
- Considere usar o provedor de localização combinada (FLP, na sigla em inglês) 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 particular. 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 apps completos. Como resultado, os apps agora podem atualizá-los usando os métodos emShortcutManager
. - Os atalhos legados mantêm a funcionalidade das versões anteriores do Android, mas precisam ser convertidos em atalhos de apps manualmente no seu 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 (nível 24 da API) introduziu o conceito de
especificar uma localidade de categoria padrão, mas algumas APIs continuaram usando o
método genérico Locale.getDefault()
sem argumentos, quando precisavam usar 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 de localidade e internacionalização:
- Chamar
Currency.getDisplayName(null)
gera umaNullPointerException
, correspondendo 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 os horários
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 das 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
Quando um app usa 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 daquelas 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 saber mais, consulte a seção Tipos de janela comuns para janelas de alerta nas mudanças de comportamento de apps destinados ao Android 8.0.
Interação e navegação
Com o advento dos apps Android no ChromeOS e em outros grandes formatos, como tablets, estamos vendo um ressurgimento do uso da navegação por teclado em apps Android. No Android 8.0 (nível 26 da API), abordamos novamente o uso do teclado como um dispositivo de entrada de navegação, resultando em um modelo mais confiável e previsível para navegação baseada em setas e guias.
Fizemos as seguintes mudanças no comportamento do foco no elemento:
-
Se nenhuma cor de estado de foco for definida para um objeto
View
(seja o drawable de primeiro ou segundo plano), o framework vai definir uma cor de destaque de foco padrão para oView
. 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 foco, defina o atributoandroid:defaultFocusHighlightEnabled
comofalse
no arquivo XML de layout que contém oView
ou transmitafalse
parasetDefaultFocusHighlightEnabled()
na lógica da interface do app. - Para testar como a entrada do teclado afeta o foco do elemento da interface, ative a opção do desenvolvedor Drawing > Show layoutBounds. 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 no 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
métodos abaixo 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 terá efeito.
- O método
WebViewDatabase
-
- Chamar
clearFormData()
não mais terá 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 mudanças na 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 apenas registrar o gerenciador de cliques usado pelos seus 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 corpo têm um cabeçalho
Content-Length: 0
. Anteriormente, elas não tinham cabeçalhoContent-Length
. - HttpURLConnection normaliza URLs contendo caminhos vazios anexando
uma barra após o nome do host ou da autoridade. Por exemplo, ele
converte
http://example.com
emhttp://example.com/
. - Um seletor de proxy personalizado definido por ProxySeletor.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. Os URLs transmitidos a um seletor de proxy personalizado não incluem 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 para a compatibilidade com versões mais antigas do libcore. Os desenvolvedores que usam a API incorretamente veriam uma mensagem do 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 mudou 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. Antes, 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 para o 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 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 em túnel 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)
vai gerar uma SocketException se o método connect() executado anteriormente falhar.- DatagramSocket.connect() vai definir uma pendingSocketException se houver um erro interno. Antes do Android 8.0, uma chamada recv() subsequente gerava uma SocketException, mesmo que uma chamada send() fosse bem-sucedida. Para dar mais consistência, ambas as chamadas agora geram uma SocketException.
- InetAddress.isReachable() tenta o ICMP antes de recorrer ao protocolo
TCP Echo.
- Alguns hosts que bloqueiam a porta 7 (TCP Echo), 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 de 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 precisam avaliar o comprimento da matriz resultante. - Dispositivos compatíveis com Bluetooth 5 podem retornar comprimento de dados superior ao máximo anterior de 60 bytes.
- Se um dispositivo remoto não fornecer uma resposta de verificação, menos de 60 bytes também poderão ser retornados.
Conectividade uniforme
O Android 8.0 (nível 26 da API) apresenta 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, a 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 mudanças 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 por Bionic. Embora existam várias outras chamadas do sistema fornecidas para compatibilidade com versões anteriores, não recomendamos o uso delas.
- 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 residem 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 do 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 (API de nível 26) introduz as seguintes mudanças relacionadas à instalação de apps desconhecidos de fontes desconhecidas:
- Agora, o valor da configuração legada
INSTALL_NON_MARKET_APPS
é 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 usando 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 já existentes em dispositivos que fizeram upgrade 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 apps desconhecidos.
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 que foram 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 os 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 chaves de assinatura diferentes em execução no mesmo dispositivo não têm 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 enviados com o Google Play Services e o ID de publicidade,
é necessário usar o
ID de publicidade. Um sistema padrão e simples para gerar receita com apps,
o ID de publicidade é um ID exclusivo e reconfigurável pelo usuário para publicidade. Ele é fornecido
pelo Google Play Services.
Outros fabricantes de dispositivos precisam continuar a fornecer
ANDROID_ID
.
-
Para apps que foram 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 uma Thread.UncaughtExceptionHandler
que
não faz chamadas para o Thread.UncaughtExceptionHandler
padrão,
o sistema
não o encerrará quando ocorrer uma exceção não identificada. No
Android 8.0 (nível 26 da API) e versões mais recentes, o sistema registra o stack trace de exceção
nessa situação. Nas versões anteriores da plataforma, o sistema não
registrava 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 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 requer 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 recebam 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 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 de dados de uso retornam
aproximações, em vez de valores exatos. O sistema Android mantém os
valores exatos internamente. Portanto, 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 um NullPointerException
. Antes, 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 empresariais, 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 conferir todas as mudanças empresariais no Android 8.0 (nível 26 da API) e saber como elas podem afetar seu app, leia Android para empresas.
Apps destinados ao Android 8.0
Essas mudanças de comportamento se aplicam exclusivamente a apps destinados ao
Android 8.0 (nível 26 da API) ou versões mais recentes. Os apps compilados no Android 8.0
ou que têm targetSdkVersion
como Android 8.0 ou 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 alertas
sobre 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 abaixo de 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 impedir que um
app exiba janelas de alerta
do tipo
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)
em 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 defender seu app contra mudanças no conteúdo de apps maliciosos e evitar o
vazamento de dados particulares para apps maliciosos.
Foco de visualização
Objetos View
clicáveis agora também são focalizáveis por
padrão Se você quiser que um objeto View
seja clicável, mas não
focável, defina o atributo
android:focusable
como false
no arquivo XML
de 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 (API de nível 26) e versões mais recentes incluem a
string do identificador de build OPR
. Algumas correspondências de padrão podem fazer com que a lógica de detecção do navegador identifique incorretamente um navegador que não seja o Opera como o Opera.
Um exemplo dessa 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 mudanças a seguir afetam a segurança no Android 8.0 (nível 26 da API):
- Se a configuração de segurança de rede do seu app
desativar o 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. A permissão Instalar apps desconhecidos gerencia instalações de apps desconhecidos de fontes desconhecidas. Para saber mais sobre essa nova permissão, consulte o guia Permissões de instalação de apps 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 ter acesso
a 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 o
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 Acesso e detecção de contas na seção "Novas APIs" deste documento.
Privacidade
As mudanças a seguir afetam a privacidade no Android 8.0 (nível 26 da API).
-
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.
Em vez disso, 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 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 nenhum app esteja instalado em outros perfis dentro do mesmo grupo de perfis. 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 solicitasse uma permissão no momento da execução e ela fosse concedida, o sistema também concedia incorretamente ao app as outras permissões que pertenciam ao mesmo grupo de permissões e que foram registradas no manifesto.
Em apps destinados ao Android 8.0, esse comportamento foi corrigido. O app recebe apenas as permissões solicitadas 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 anterior, 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
nesse momento. No entanto, se o app solicitar WRITE_EXTERNAL_STORAGE
posteriormente, o sistema concederá esse privilégio imediatamente sem notificar o usuário.
Mídia
- O framework pode executar
redução de áudio automática
sozinha. 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. Novas APIs estão disponíveis para substituir esse comportamento para aplicativos que precisam pausar em vez de reduzir. - Quando o usuário recebe uma ligação, os fluxos 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 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 processamento de botões de mídia em uma atividade de 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 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 de 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 um nível de API inferior ao da API em que a alteração do vinculador ocorre, o logcat mostrará um aviso.
Gerenciamento de coleta
No Android 8.0 (nível 26 da API),
a Collections.sort()
é implementada
com base na List.sort()
. O contrário
era verdadeiro no Android 7.x (níveis 24 e 25 da API):
a implementação padrão de List.sort()
,
chamada 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 deList
, evite substituirsort()
.Se uma classe mãe implementar
sort()
de forma inadequada, normalmente é possível 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, também é possível substituir
List.sort()
por uma implementação que delega para 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 esta última opção apenas porque quer ter um método
sort()
disponível em todos os níveis da API, considere dar a ele um nome exclusivo, comosortCompat()
, em vez de substituirsort()
.-
Collections.sort()
agora conta como uma modificação estrutural em implementações de List que chamamsort()
. Por exemplo, em versões da plataforma anteriores ao Android 8.0 (nível 26 da API), iterar emArrayList
e chamarsort()
nela no meio da iteração geraria umaConcurrentModificationException
se a classificaçã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 um
ConcurrentModificationException
.
Comportamento de carregamento de classe
O Android 8.0 (nível 26 da API) faz verificações para garantir que os carregadores de classes não violem as suposições do ambiente de execução ao carregar novas classes. Essas verificações são
realizadas se a classe é referenciada em Java (em
forName()
),
no bytecode 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 classes
com comportamento adequado.
A plataforma verifica se o descritor da classe que o carregador de classes retorna
corresponde ao descritor esperado. Se o descritor retornado não corresponder,
a plataforma vai 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 (nível 26 da API) não permite que vários carregadores de classes tentem 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 recomendamos que você use
um dos carregadores de classe da plataforma, incluindo PathClassLoader
ou
BaseDexClassLoader
.
Observação : você pode 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 de 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,
referenciar 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 a concluir a operação ganha, e o resultado é usado para as outras. 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 (nível 26 da API), quebrar essas suposições pode levar à definição da mesma classe várias vezes, à corrupção do heap devido à confusão de classes e a outros efeitos indesejáveis.