Alterações de comportamento do Android 8.0

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 todos os apps quando executados na plataforma Android 8.0 (API de nível 26), independentemente do nível de 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.

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 uma IllegalStateException 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 chamem Context.startForegroundService() mesmo quando estiverem em segundo plano. No entanto, o app precisa chamar o método startForeground() 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étodo requestPinShortcut() da classe ShortcutManager.
  • A intent ACTION_CREATE_SHORTCUT agora pode criar atalhos de apps que você gerencia usando a classe ShortcutManager. Essa intent também pode criar atalhos legados da tela de início que não interagem com ShortcutManager. 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 intent ACTION_CREATE_SHORTCUT agora são atalhos de apps completos. Como resultado, os apps agora podem atualizá-los usando os métodos em ShortcutManager.
  • 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 uma NullPointerException, 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 o View. 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 atributo android:defaultFocusHighlightEnabled como false no arquivo XML de layout que contém o View ou transmita false para setDefaultFocusHighlightEnabled() 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
WebViewDatabase
  • Chamar clearFormData() não mais terá efeito.
  • O método hasFormData() agora retorna false. Anteriormente, esse método retornava true quando o formulário continha dados.

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 objetos View. Se o TalkBack ainda não reconhecer os gestos realizados nesses objetos View, modifique performAccessibilityAction().

  • Os serviços de acessibilidade agora reconhecem todas as instâncias de ClickableSpan nos objetos TextView 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çalho Content-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 em http://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:

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 de ANDROID_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.

  • 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) e someMethod(TextView) que usam o resultado de uma chamada para findViewById().
  • 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 objeto WebView 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 e net.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 objeto NetworkRequest ou NetworkCallback. 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ão READ_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 API LauncherApps 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 callback onAudioFocusChange() 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 argumento streamType para o construtor AudioTrack 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:
    1. 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.
    2. 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.
    3. 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.
    4. 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 chamar Collections.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 de List, evite substituir sort().

    Se uma classe mãe implementar sort() de forma inadequada, normalmente é possível substituir List.sort() por uma implementação criada com base em List.toArray(), Arrays.sort() e ListIterator.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, como sortCompat(), em vez de substituir sort().

  • Collections.sort() agora conta como uma modificação estrutural em implementações de List que chamam sort(). Por exemplo, em versões da plataforma anteriores ao Android 8.0 (nível 26 da API), iterar em ArrayList e chamar sort() nela no meio da iteração geraria uma ConcurrentModificationException se a classificação fosse feita chamando List.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.