Alterações de comportamento do Android 8.0

Além de 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ê deve entender e considerar nos seus apps.

A maioria delas afeta todos os apps, independentemente 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 facilitar o entendimento, esta página está 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), independentemente do nível da API de destino. Todos os desenvolvedores precisam analisar essas mudanças e adaptar os apps para que eles ofereçam suporte a 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 eficiência da bateria, quando o app entra no estado armazenado 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 em execução em primeiro plano. Especificamente:

  • Os apps em execução em segundo plano agora têm limites quanto à liberdade de acesso aos serviços de segundo plano.
  • Os apps não podem usar o manifesto para se registrar para receber a maioria das transmissões implícitas, ou seja, aquelas que não são direcionadas especificamente para o aplicativo.

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 apps chamem Context.startForegroundService() mesmo que estejam 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, preservar a experiência do usuário e a integridade do sistema, os apps em segundo plano recebem atualizações de localização com menos frequência quando usados em um dispositivo com 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)
  • Geofencing
  • GNSS Measurements
  • Location Manager
  • Wi-Fi Manager

Para garantir que o aplicativo funcione como o esperado, faça o seguinte:

  • Analise a lógica do seu app e verifique se você está usando as APIs de localização mais recentes.
  • Teste se o app exibe o comportamento esperado para cada caso de uso.
  • Pense em usar o Fused Location Provider (FLP) ou o Geofencing para lidar com os casos de uso que dependem da localização atual do usuário.

Para saber mais sobre essas mudanças, consulte Limites de 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 produz mais nenhum efeito no app, porque agora é implícita e privada. Em vez disso, crie um atalho usando o método requestPinShortcut() da classe ShortcutManager.
  • A intent ACTION_CREATE_SHORTCUT agora pode criar atalhos de teclado, que você gerencia usando a classe ShortcutManager. Essa intent também pode criar atalhos de inicialização herdados que não interagem com ShortcutManager. Antes, essa intent só podia criar atalhos de inicialização herdados.
  • Os atalhos criados usando requestPinShortcut() e os criados em uma atividade que lida com a intent ACTION_CREATE_SHORTCUT agora estão totalmente desenvolvidos. Como resultado, os apps agora podem atualizá-los usando os métodos em ShortcutManager.
  • Os atalhos herdados mantêm a funcionalidade das versões anteriores do Android, mas precisam ser convertidos em atalhos de app manualmente no aplicativo.

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 poder especificar um Locale com categoria padrão, mas algumas APIs continuaram usando o método Locale.getDefault() genérico, sem argumentos, quando deveriam usar o Locale com a categoria DISPLAY padrão. No Android 8.0 (nível 26 da API), os métodos a seguir agora usam Locale.getDefault(Category.DISPLAY) em vez de Locale.getDefault():

Locale.getDisplayScript(Locale) também retorna para Locale.getDefault() quando o valor displayScript especificado para o argumento Locale não está disponível.

Veja a seguir outras mudanças relacionadas à localidade e à internacionalização:

  • Chamar Currency.getDisplayName(null) gera uma NullPointerException, que é um comportamento igual ao documentado.
  • A análise do nome do fuso horário mudou. Antes, os dispositivos Android usavam o valor do relógio do sistema em uma amostra em tempo de inicialização para armazenar em cache os nomes de fuso horário usados para analisar horários e data. Assim, a análise podia ser afetada negativamente se o relógio do sistema estivesse incorreto no tempo de 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 para analisar nomes de fuso horário. Essa mudança fornece resultados mais corretos, que podem diferir das versões anteriores do Android quando o app usa classes como SimpleDateFormat.

  • O Android 8.0 (nível 26 da API) atualiza a ICU para a versão 58.

Janelas de alerta

Se o app usa a permissão SYSTEM_ALERT_WINDOW e um dos seguintes tipos de janela para tentar mostrar alertas sobre outros apps e janelas do sistema:

...essas janelas sempre aparecem sobre as janelas do tipo TYPE_APPLICATION_OVERLAY. Se um app é voltado para o Android 8.0 (nível 26 da API), ele usa o tipo de janela TYPE_APPLICATION_OVERLAY para mostrar alertas.

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 formatos grandes, como tablets, estamos vendo um ressurgimento da navegação pelo teclado em apps Android. No Android 8.0 (nível 26 da API), voltamos a usar o teclado como um dispositivo de entrada de navegação, o que resulta em um modelo mais confiável e previsível de navegação de seta e aba.

Em especial, fizemos as seguintes mudanças no comportamento de foco do elemento:

  • Se você não definiu nenhuma cor para os estados de foco de um objeto View (seja um desenhável de primeiro ou segundo plano), a estrutura agora define uma cor de realce de foco padrão para a View. O realce de foco é um desenhável com efeito de ondulação baseado no tema da atividade.

    Se você não quiser que um objeto View use esse realce padrão quando receber 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 IU do seu app.

  • Para testar como a entrada do teclado afeta o foco do elemento da interface, ative a opção de desenvolvedor Desenho > Mostrar limites de layout. No Android 8.0, essa opção exibe um ícone "X" sobre o elemento que está em foco no momento.

Além disso, todos os elementos da barra de ferramentas no Android 8.0 são automaticamente clusters de navegação por teclado, o que facilita a entrada e a saída da navegação de cada barra de ferramentas como um todo.

Para saber mais sobre como melhorar o suporte à navegação por teclado no seu app, leia o guia Compatibilidade com navegação por teclado.

Preenchimento automático de formulários Web

Agora que a Estrutura de preenchimento automático do Android oferece suporte integrado ao recurso de preenchimento automático, os seguintes métodos relacionados a objetos WebView foram alterados para apps instalados em dispositivos com o Android 8.0 (nível 26 da API):

WebSettings
WebViewDatabase
  • Chamar clearFormData() não tem mais 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 (nível 26 da API) 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 de forma mais parecida com outros serviços de acessibilidade.

    Se os objetos View do app usarem um 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, substitua performAccessibilityAction().

  • Os serviços de acessibilidade agora conhecem todas as instâncias de ClickableSpan nos objetos TextView do seu app.

Para saber mais sobre como tornar o app mais acessível, consulte Acessibilidade.

Redes e conectividade HTTP(S)

O Android 8.0 (nível 26 da API) inclui as seguintes mudanças de comportamento em redes e conectividade HTTP(S):

  • As solicitações OPTIONS sem corpo têm um cabeçalho Content-Length: 0. Antigamente, 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. Por exemplo, ele converte http://example.com em http://example.com/.
  • Um seletor de proxy personalizado configurado por ProxySelector.setDefault() só visa o endereço (esquema, host e porta) do URL solicitado. Com isso, a seleção de proxy pode se basear apenas nesses valores. Um URL transmitido a 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 possibilitava uma alternativa de aceitar rótulos vazios em nomes de host, o que é um uso ilegal dos URIs. Essa solução alternativa era para compatibilidade com versões libcore mais antigas. Os desenvolvedores que usam a API incorretamente vão receber a 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." No Android 8.0, essa alternativa não existe: o sistema retorna nulo para URIs de composição incorreta.

  • A implementação de HttpsURLConnection do Android 8.0 não executa substitutos de versão do protocolo TLS/SSL não seguros.
  • A manipulação de conexões HTTP(S) de túnel foi alterada da seguinte forma:
    • Ao encapsular conexão sobre conexão HTTPS, o sistema coloca o número da porta (:443) corretamente 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 "user-agent" e "proxy-autorização" de uma solicitação em túnel 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 "proxy-authorization" e o envia ao proxy quando esse proxy 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 user agent para essa solicitação.

  • O método send(java.net.DatagramPacket) gera uma SocketException se o método connect() executado anteriormente falhar.
    • DatagramSocket.connect() define uma pendingSocketException se houver um erro interno. Antes do Android 8.0, uma chamada de recv() posterior gerava uma SocketException, mesmo que uma chamada de 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 de eco.
    • Alguns host que bloqueiam a porta 7 (eco de TCP), como o google.com, agora podem ser acessados se aceitarem o protocolo ICMP de eco.
    • Para hosts realmente inacessíveis, essa mudança exige duas vezes mais tempo para receber retornos da chamada.

Bluetooth

O Android 8.0 (nível 26 da API) promove as seguintes mudanças no comprimento dos dados que o método ScanRecord.getBytes() extrai:

  • O método getBytes() não pressupõe o número de bytes recebidos. Portanto, os apps não devem 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 dado que exceda o valor máximo anterior de cerca de 60 bytes.
  • Se um dispositivo remoto não fornecer uma resposta analisada, é possível que se retorne menos de 60 bytes.

Conectividade uniforme

O Android 8.0 (nível 26 da API) faz diversas 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 nas proximidades.

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 a negociação de versão do protocolo TLS de forma incorreta, HttpsURLConnection não recorre mais à alternativa de retroceder a versões antigas do protocolo TLS e tentar novamente.
  • O Android 8.0 (nível 26 da API) aplica um filtro de computação segura (SECCOMP) a todos os apps. A lista de chamadas do sistema permitidas é restrita às expostas por Bionic. Embora haja diversas outras chamadas do sistema para a retrocompatibilidade, não recomendamos usá-las.
  • Os objetos WebView do app agora são executados no modo de vários processos. O conteúdo da Web é tratado em um processo isolado do processo que contém o app, aumentando a segurança.
  • Não é mais possível presumir que os APKs estão em diretórios com nomes que terminam em -1 ou -2. Os apps precisam usar sourceDir para encontrar o diretório, e não confiar no formato do diretório diretamente.
  • Para saber mais sobre as 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) apresenta 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.

Se precisar de mais instruções sobre como tornar o 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 uma 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 a OTA. Para preservar os valores em 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 recebe escopo por chave de assinatura do app e por usuário. O valor de ANDROID_ID é exclusivo para cada combinação de chave de assinatura de app, usuário e dispositivo. Como resultado, apps com diferentes chaves de assinatura executadas 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 será alterado 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, use o ID de publicidade. O ID de publicidade é um sistema padrão simples para gerar receita com apps e é um código exclusivo e reconfigurável pelo usuário para publicidade. Ele é fornecido pelo Google Play Services.

      Outros fabricantes de dispositivos precisam continuar fornecendo ANDROID_ID.

  • Consultar a propriedade do sistema net.hostname gera um resultado nulo.

Registro de exceções não capturadas

Se um app instalar uma Thread.UncaughtExceptionHandler que não faz chamadas pelo Thread.UncaughtExceptionHandler padrão, o sistema não vai encerrar o app quando ocorrer uma exceção não capturada. A partir do Android 8.0 (nível 26 da API), o sistema registra a movimentação de pilha da exceção nessa situação. Nas versões anteriores da plataforma, o sistema não teria registrado a movimentação de pilha da exceção.

Recomendamos que as implementações de Thread.UncaughtExceptionHandler personalizadas sempre chamem o gerenciador padrão. Os apps que seguirem essa recomendação não serão afetados pela mudança no 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 atual tenha um tipo de retorno ambíguo, por exemplo, se houver someMethod(View) e someMethod(TextView) que levem o resultado de uma chamada para findViewById().
  • Ao usar a linguagem de origem Java 8, será necessário fazer uma conversão explícita para View quando o tipo de retorno não tiver 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 de 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 se estabeleceu contato com ele e a última vez que se realizou um contato. Os apps que solicitam a permissão READ_CONTACTS podem ler esses dados.

Os apps ainda podem ler esses dados se solicitarem a permissão READ_CONTACTS. No Android 8.0 (nível 26 da API) 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, 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. Antes, a NullPointerException não era gerada 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 do 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 ao gerenciamento de atualizações do sistema, à verificação de apps e à autenticação para aumentar a integridade do sistema e do dispositivo.
  • Melhorias na experiência do usuário para provisionamento, notificações, a tela "Recentes" e VPN sempre ativa.

Para conferir todas as mudanças empresariais no Android 8.0 (nível 26 da API) e entender 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 (nível 26 da API) ou versões mais recentes. Aplicativos compilados no Android 8.0 ou com targetSdkVersion definida para o Android 8.0 ou mais recente precisam ser modificados para oferecer suporte adequado a esses comportamentos, quando aplicável.

Janelas de alerta

Os apps que usam a permissão SYSTEM_ALERT_WINDOW não podem mais usar os seguintes tipos de janela para mostrar alertas sobre outros apps e janelas do sistema:

Agora, 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 as 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 o 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 a forma como ContentResolver.notifyChange() e registerContentObserver(Uri, boolean, ContentObserver) funcionam para apps com destino ao Android 8.0.

Agora, essas APIs 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 de conteúdo por apps maliciosos e evita o vazamento de dados potencialmente particulares para apps maliciosos.

Foco de visualização

Os objetos View clicáveis agora também podem ser focados por padrão. Se quiser que um objeto View seja clicável, mas não possa receber foco, 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 IU 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 de navegador identifique incorretamente um navegador que não é o Opera como sendo o Opera. Um exemplo dessa correspondência de padrão pode ser:

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 (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. Em vez disso, a permissão Instalar apps desconhecidos gerencia instalações de apps de fontes desconhecidas. Para saber mais sobre essa nova permissão, consulte o guia Permissões de instalação de apps desconhecidos.

Para mais 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 o proprietário das contas ou o usuário conceda esse acesso. A permissão GET_ACCOUNTS não é mais suficiente. Para conseguir acesso a uma conta, os apps precisam usar AccountManager.newChooseAccountIntent() ou um método específico do autenticador. Depois de obter o acesso a contas, o app pode chamar AccountManager.getAccounts() para acessá-las.

O Android 8.0 descontinua LOGIN_ACCOUNTS_CHANGED_ACTION. Em vez disso, os apps precisam usar addOnAccountsUpdatedListener() para receber atualizações sobre as contas durante a execução.

Para mais informações sobre novas APIs e métodos adicionados para acesso à conta e facilidade de descoberta, consulte Detecção da conta e acesso na seção "Novas APIs" deste documento.

Privacidade

As mudanças abaixo 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 encontrar 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. Apps que precisam saber o número de série do hardware precisam usar o novo método Build.getSerial(), que requer a permissão READ_PHONE_STATE.
  • A API LauncherApps não permite mais que apps de perfil de trabalho tragam 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 fosse instalado em outros perfis dentro do mesmo grupo de perfis. Como antes, tentar acessar perfis não relacionados gera SecurityExceptions.

Permissões

Antes do Android 8.0 (API de nível 26), se um app solicitasse uma permissão durante a 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 estavam registradas no manifesto.

Para apps voltados para o Android 8.0, esse comportamento foi corrigido. O app só recebe as permissões que foram explicitamente solicitadas. No entanto, quando o usuário concede uma permissão ao app, todas as solicitações subsequentes de permissões naquele grupo 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 ela pertence ao mesmo grupo de permissão STORAGE e também está registrada no manifesto. Se o app for direcionado ao Android 8.0 (API de nível 26), o sistema concederá somente READ_EXTERNAL_STORAGE nesse momento. No entanto, se o app solicitar WRITE_EXTERNAL_STORAGE posteriormente, o sistema concederá esse privilégio imediatamente sem solicitar ao usuário.

Mídia

  • O framework pode realizar atenuação automática de áudio por conta própria. Nesse caso, quando outro aplicativo solicita a seleção com AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, o aplicativo selecionado reduz o volume, mas geralmente não recebe um callback onAudioFocusChange() e não perde o foco de áudio. Novas APIs estão disponíveis para substituir esse comportamento em aplicativos que precisam pausar em vez de atenuar.
  • Quando o usuário aceita uma chamada telefônica, os fluxos de mídia ativos param pelo tempo de duração da 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 grande, se estiver disponível.
  • No Android 8.0 (nível 26 da API), o processamento de eventos de 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 de 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 rotear 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 ele tiver um.
    4. Para todos os demais casos de uso, o sistema descarta o evento de botão de mídia.

Bibliotecas nativas

Nos apps voltados para o Android 8.0 (nível 26 da API), as bibliotecas nativas não são mais carregadas se contiverem algum segmento para carregar que seja gravável e executável ao mesmo tempo. Alguns apps podem parar de funcionar por causa dessa mudança se tiverem bibliotecas nativas com segmentos de carga incorretos. Essa é uma medida de aumento de segurança.

Para mais informações, 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 do nível da API almejada, o app não conseguirá carregar a biblioteca. Se você está almejando um nível de API inferior ao da API que apresenta a mudança no vinculador, o Logcat mostra um aviso.

Gerenciamento de coleta

No Android 8.0 (nível 26 da API), Collections.sort() é implementado em cima de List.sort(). O contrário acontecia 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() tire vantagem de 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 geraria um estouro de pilha devido à 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 incorreta, normalmente não haverá problema em neutralizar List.sort() com uma implementação criada com base em List.toArray(), Arrays.sort() e ListIterator.set(). 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, é possível substituir List.sort() com uma implementação que delega a outras implementações padrão, dependendo do nível da API. 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 isso apenas porque quer disponibilizar um método sort() 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 em implementações de lista que chamam sort(). Por exemplo, em versões da plataforma anteriores ao Android 8.0 (API de nível 26), iterar em um ArrayList e chamar sort() nele 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: ambas as abordagens agora resultam em uma ConcurrentModificationException.

Comportamento de carregamento de classe

O Android 8.0 (nível 26 da API) verifica se os carregadores de classe não rompem as premissas do tempo de execução ao carregar novas classes. Essas verificações são realizadas mesmo que a classe esteja referenciada em Java (em forName()), bytecode do 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 dos carregadores de classe que estão funcionando bem.

A plataforma verifica se o descritor da classe que o carregador de classe retorna é o descritor esperado. Se o descritor retornado não corresponder, a plataforma vai acionar um erro NoClassDefFoundError e armazenar na exceção uma mensagem detalhada que indica a discrepância.

A plataforma também analisa se os descritores das classes solicitadas são válidos. Essa verificação detecta chamadas de JNI que carregam indiretamente classes como GetFieldID(), transmitindo descritores inválidos a elas. Por exemplo, um campo com a assinatura java/lang/String não é encontrado porque essa assinatura é inválida; ela deveria ser Ljava/lang/String;.

Esse é um caso diferente de uma chamada de 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 oferece suporte a vários carregadores de classes 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 classe".

A DexFile API foi descontinuada. Recomendamos usar um dos carregadores de classe da plataforma, incluindo PathClassLoader ou BaseDexClassLoader.

Observação : é possível criar vários carregadores de classe que referenciam o 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á realizar uma operação mmap neles em vez de extraí-los diretamente. No entanto, se a plataforma precisa extrair o arquivo DEX do contêiner, referenciar um arquivo DEX dessa maneira pode consumir muita memória.

No Android, todos os carregadores de classe são considerados passíveis de paralelismo. Quando vários encadeamentos competem para carregar a mesma classe com o mesmo carregador de classe, o primeiro encadeamento a concluir a operação vence, e o resultado é usado nos outros encadeamentos. Esse comportamento ocorre em qualquer cenário, se o carregador de classe retornou a mesma classe, retornou uma classe diferente ou acionou uma exceção. A plataforma ignora essas exceções silenciosamente.

Atenção : nas 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 de heap devido à confusão de classes e a outros efeitos indesejados.