Alterações de comportamento do Android 8.0

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 todos os apps quando são executados na plataforma Android 8.0 (nível 26 da API), independente do nível de API a que se destinam. Todos os desenvolvedores precisam analisar essas mudanças e modificar os apps para que sejam compatíveis com elas, quando aplicável.

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 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.
  • 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é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 app completos. Como resultado, os apps agora podem atualizá-los usando os métodos em ShortcutManager.
  • 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 uma NullPointerException, 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 para 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 o foco, defina o atributo android:defaultFocusHighlightEnabled como false no arquivo XML do layout que contém o View ou transmita false para setDefaultFocusHighlightEnabled() 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
WebViewDatabase
  • Chamar clearFormData() não mais tem 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 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 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 "body" têm um cabeçalho Content-Length: 0. Anteriormente, elas não tinham cabeçalho Content-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 em http://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:

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

  • 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) e someMethod(TextView) que usam o resultado de uma chamada para findViewById().
  • 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):

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 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. 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 os 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 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 callback onAudioFocusChange() 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 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 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:
    1. 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.
    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 vai 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 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 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 do List, evite modificar sort().

    Se uma classe mãe implementar sort() de forma inadequada, normalmente não há problema em 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, 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, como sortCompat(), em vez de substituir sort().

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