Além de novos recursos e funcionalidades, o Android 7.0 inclui várias 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.
Se você já publicou um app para Android, saiba que ele pode ser afetado por essas mudanças na plataforma.
Bateria e memória
O Android 7.0 inclui mudanças de comportamento do sistema que visam melhorar a duração da bateria dos dispositivos e reduzir o uso de RAM. Essas mudanças podem afetar o acesso do app aos recursos do sistema, além da forma como ele interage com outros apps usando determinadas intents implícitas.
Soneca
Introduzido no Android 6.0 (nível 23 da API), o modo Doze melhora a duração da bateria adiando as atividades da CPU e da rede quando o usuário deixa o dispositivo desconectado, parado e com a tela desligada. O Android 7.0 traz mais melhorias ao modo Doze, aplicando um subconjunto de restrições de CPU e rede enquanto o dispositivo está desconectado com a tela desligada, mas não necessariamente parado, por exemplo, quando um smartphone está no bolso do usuário.
Figura 1. Ilustração de como o modo Soneca aplica um primeiro nível de restrições de atividade do sistema para melhorar a duração da bateria.
Quando um dispositivo está funcionando com bateria e a tela fica desligada por um determinado
tempo, ele entra no modo Soneca e aplica o primeiro subconjunto de restrições: desativa o acesso à rede do app e adia jobs e sincronizações. Se o dispositivo ficar
estacionário por um determinado período após entrar no modo Soneca, o sistema vai aplicar o
restante das restrições do modo Soneca a PowerManager.WakeLock,
alarmes AlarmManager, GPS e verificações de Wi-Fi. Independentemente de
algumas ou todas as restrições do modo Soneca estarem sendo aplicadas, o sistema ativa o
dispositivo para breves janelas de manutenção, durante as quais os aplicativos têm acesso
à rede e podem executar jobs/sincronizações adiados.
Figura 2. Ilustração de como o modo Soneca aplica um segundo nível de restrições de atividade do sistema depois que o dispositivo fica inativo por um determinado período.
Ativar a tela ou conectar o dispositivo ao carregador faz com que ele saia do modo Soneca e remove essas restrições de processamento. O comportamento adicional não afeta as recomendações e práticas recomendadas para adaptar seu app à versão anterior do modo Soneca, introduzida no Android 6.0 (nível 23 da API), conforme discutido em Otimizar para os modos Soneca e App em espera. Ainda é necessário seguir essas recomendações, como usar o Firebase Cloud Messaging (FCM) para enviar e receber mensagens, e começar a planejar atualizações para acomodar o comportamento adicional do modo Soneca.
Project Svelte: otimizações em segundo plano
O Android 7.0 remove três transmissões implícitas para ajudar a otimizar o uso de memória e o consumo de energia. Essa mudança é necessária porque as transmissões implícitas frequentemente iniciam apps que se registraram para detectá-las em segundo plano. A remoção dessas transmissões pode beneficiar significativamente o desempenho do dispositivo e a experiência do usuário.
Os dispositivos móveis passam por mudanças frequentes de conectividade, como ao alternar
entre Wi-Fi e dados móveis. Atualmente, os apps podem monitorar mudanças na
conectividade registrando um receptor para a transmissão implícita CONNECTIVITY_ACTION no
manifesto. Como muitos apps se registram para receber essa transmissão, um único switch de rede pode fazer com que todos eles sejam ativados e processem a transmissão ao mesmo tempo.
Da mesma forma, em versões anteriores do Android, os apps podiam se registrar para receber transmissões implícitas ACTION_NEW_PICTURE e ACTION_NEW_VIDEO de outros apps, como
Câmera. Quando um usuário tira uma foto com o app Câmera, esses apps são ativados
para processar a transmissão.
Para amenizar esses problemas, o Android 7.0 aplica as seguintes otimizações:
- Os apps destinados ao Android 7.0 (nível 24 da API) e versões mais recentes não receberão
transmissões
CONNECTIVITY_ACTIONse declararem o broadcast receiver no manifesto. Os apps ainda receberão transmissõesCONNECTIVITY_ACTIONse registrarem oBroadcastReceivernoContext.registerReceiver()e esse contexto ainda for válido. - O sistema não envia mais transmissões de
ACTION_NEW_PICTUREouACTION_NEW_VIDEO. Essa otimização afeta todos os apps, não apenas aqueles para o Android 7.0.
Caso seu app use qualquer um desses intents, remova as dependências
deles assim que possível para segmentar os dispositivos de destino com o Android 7.0 corretamente.
O framework do Android oferece várias soluções para reduzir a necessidade dessas
transmissões implícitas. Por exemplo, a API JobScheduler fornece um mecanismo robusto para programar
operações de rede quando condições especificadas, como conexão com uma
rede ilimitada, forem atendidas. Você pode até usar JobScheduler para reagir às mudanças nos provedores de conteúdo.
Para mais informações sobre otimizações em segundo plano no Android 7.0 (nível 24 da API) e como adaptar seu app, consulte Otimizações em segundo plano.
Mudanças de permissão
O Android 7.0 inclui mudanças nas permissões que podem afetar seu app.
Mudanças nas permissões do sistema de arquivos
Para melhorar a segurança de arquivos particulares, o diretório particular de
apps destinados ao Android 7.0 ou versões mais recentes tem acesso restrito (0700).
Essa configuração impede o vazamento de metadados de arquivos particulares, como tamanho
ou existência. Essa mudança de permissão tem vários efeitos colaterais:
-
As permissões do arquivo particular não podem mais ser flexibilizadas pelo proprietário,
e uma tentativa de fazer isso usando
MODE_WORLD_READABLEe/ouMODE_WORLD_WRITEABLEvai acionar umaSecurityException.Observação: até o momento, essa restrição não é totalmente aplicada. Os apps ainda podem modificar as permissões do diretório particular usando APIs nativas ou a API
File. No entanto, não recomendamos relaxar as permissões para o diretório particular. -
Transmitir URIs
file://fora do domínio do pacote pode deixar o receptor com um caminho inacessível. Portanto, as tentativas de transmitir um URIfile://acionam umFileUriExposedException. A maneira recomendada de compartilhar o conteúdo de um arquivo particular é usando oFileProvider. -
O
DownloadManagernão pode mais compartilhar arquivos armazenados de forma particular pelo nome do arquivo. Os aplicativos legados podem acabar com um caminho inacessível ao acessarCOLUMN_LOCAL_FILENAME. Os apps destinados ao Android 7.0 ou versões mais recentes acionam umaSecurityExceptionao tentar acessarCOLUMN_LOCAL_FILENAME. Os aplicativos legados que definem o local de download como público usandoDownloadManager.Request.setDestinationInExternalFilesDir()ouDownloadManager.Request.setDestinationInExternalPublicDir()ainda podem acessar o caminho emCOLUMN_LOCAL_FILENAME. No entanto, esse método é altamente desaconselhável. A maneira preferencial de acessar um arquivo exposto peloDownloadManageré usandoContentResolver.openFileDescriptor().
Como compartilhar arquivos entre apps
Para apps destinados ao Android 7.0, o framework do Android aplica
a política da API StrictMode, que proíbe a exposição de URIs file://
fora do app. Se uma intent que contém um URI de arquivo sair do app, ele vai falhar
com uma exceção FileUriExposedException.
Para compartilhar arquivos entre aplicativos, envie um URI content://
e conceda uma permissão de acesso temporário a ele. A maneira mais fácil de conceder essa permissão é
usando a classe FileProvider. Para mais informações
sobre permissões e compartilhamento de arquivos,
consulte Como compartilhar arquivos.
Melhorias na acessibilidade
O Android 7.0 inclui mudanças que visam melhorar a usabilidade da plataforma para usuários com baixa visão ou deficiência visual. Em geral, essas mudanças não exigem alterações no código do app. No entanto, é recomendável analisar esses recursos e testá-los com o app para avaliar possíveis impactos na experiência do usuário.
Zoom da tela
O Android 7.0 permite que os usuários definam o Tamanho de exibição, que amplia ou reduz todos os elementos na tela, melhorando a acessibilidade do dispositivo para usuários com baixa visão. Os usuários não podem aumentar o zoom além de uma largura mínima de tela de sw320dp, que é a largura de um Nexus 4, um smartphone comum de tamanho médio.
Figura 3. A tela à direita mostra o efeito de aumentar o tamanho de exibição de um dispositivo que executa uma imagem do sistema Android 7.0.
Quando a densidade do dispositivo muda, o sistema notifica os apps em execução das seguintes maneiras:
- Se um app for direcionado ao nível desejado da API 23 ou versões anteriores, o sistema vai encerrar automaticamente todos os processos em segundo plano dele. Isso significa que, se um usuário sair de um app para abrir a tela Configurações e mudar a configuração Tamanho de exibição, o sistema vai encerrar o app da mesma maneira que faria em uma situação de pouca memória. Se o app tiver processos em primeiro plano, o sistema vai notificar esses processos sobre a mudança de configuração, conforme descrito em Como processar mudanças no ambiente de execução, como se a orientação do dispositivo tivesse mudado.
- Se um app for direcionado ao Android 7.0, todos os processos dele (em primeiro e segundo plano) serão notificados sobre a mudança de configuração, conforme descrito em Como processar mudanças no ambiente de execução.
A maioria dos apps não precisa fazer mudanças para oferecer suporte a esse recurso, desde que sigam as práticas recomendadas do Android. Itens específicos a serem verificados:
- Teste o app em um dispositivo com largura de tela
sw320dpe verifique se ele funciona adequadamente. - Quando a configuração do dispositivo mudar, atualize todas as informações armazenadas em cache
que dependem da densidade, como bitmaps ou recursos carregados da
rede. Verifique se há mudanças de configuração quando o app é retomado do estado
pausado.
Observação: se você armazenar em cache dados dependentes da configuração, é uma boa ideia incluir metadados relevantes, como o tamanho de tela ou a densidade de pixels apropriados para esses dados. Salvar esses metadados permite que você decida se precisa atualizar os dados armazenados em cache após uma mudança de configuração.
- Evite especificar dimensões com unidades px, já que elas não são dimensionadas com
a densidade da tela. Em vez disso, especifique as dimensões com unidades de pixel independente de densidade (
dp).
Configurações visuais no assistente de configuração
O Android 7.0 inclui as Configurações de visão na tela inicial, em que os usuários podem definir as seguintes configurações de acessibilidade em um novo dispositivo: Gesto de ampliação, Tamanho da fonte, Tamanho de exibição e TalkBack. Essa mudança aumenta a visibilidade de bugs relacionados a diferentes configurações de tela. Para avaliar o impacto desse recurso, teste seus apps com essas configurações ativadas. As configurações estão em Configurações > Acessibilidade.
Apps do NDK vinculados a bibliotecas de plataforma
No Android 7.0 e versões mais recentes, o sistema impede que os apps se vinculem dinamicamente a bibliotecas que não são do NDK, o que pode causar falhas no app. Essa mudança de comportamento tem como objetivo criar uma experiência consistente no app em todas as atualizações da plataforma e em diferentes dispositivos. Mesmo que seu código não esteja vinculado a bibliotecas particulares, é possível que uma biblioteca estática de terceiros no seu app esteja. Portanto, todos os desenvolvedores precisam verificar se os apps não falham em dispositivos com o Android 7.0. Se o app usa código nativo, use apenas APIs NDK públicas.
Há três maneiras de o app tentar acessar APIs de plataforma particulares:
- Seu app acessa diretamente bibliotecas de plataforma particulares. Atualize seu app para incluir uma cópia própria dessas bibliotecas ou use as APIs públicas do NDK.
- Seu app usa uma biblioteca de terceiros que acessa bibliotecas de plataforma particulares. Mesmo que você tenha certeza de que seu app não acessa bibliotecas particulares diretamente, ainda é preciso testar o app para esse cenário.
- O app faz referência a uma biblioteca que não está incluída no APK. Por
exemplo, isso pode acontecer se você tentar usar sua própria cópia do OpenSSL, mas
esquecer de incluí-la no APK do app. O app pode ser executado normalmente em versões
da plataforma Android que incluem
libcrypto.so. No entanto, o app pode falhar em versões mais recentes do Android que não incluem essa biblioteca, como o Android 6.0 e versões mais recentes. Para corrigir isso, agrupe todas as bibliotecas não NDK com o APK.
Os apps não podem usar bibliotecas nativas que não estão incluídas no NDK, porque elas podem mudar ou ser removidas entre diferentes versões do Android. A mudança do OpenSSL para o BoringSSL é um exemplo disso. Além disso, como não há requisitos de compatibilidade para bibliotecas de plataforma não incluídas no NDK, dispositivos diferentes podem oferecer níveis diferentes de compatibilidade.
Para reduzir o impacto que essa restrição pode ter nos apps
lançados atualmente, um conjunto de bibliotecas que têm uso significativo, como
libandroid_runtime.so, libcutils.so,
libcrypto.so e libssl.so, estão temporariamente
acessíveis no Android 7.0 (nível 24 da API) para apps destinados ao nível 23 ou
anterior. Se o app carregar uma dessas bibliotecas, o logcat vai gerar um aviso
e uma mensagem vai aparecer no dispositivo de destino para notificar você. Se você receber esses
avisos, atualize o app para incluir uma cópia própria dessas
bibliotecas ou use apenas as APIs públicas do NDK. As próximas versões da plataforma
Android podem restringir totalmente o uso de bibliotecas privadas e causar falhas
no app.
Todos os apps geram um erro de tempo de execução quando chamam uma API que não é
pública nem temporariamente acessível. O resultado é que
System.loadLibrary e dlopen(3) retornam
NULL, o que pode causar uma falha no app. Revise o código do seu
app para remover o uso de APIs de plataforma particulares e teste seus apps
com um dispositivo ou emulador que execute o Android 7.0 (nível 24 da API). Se você não
sabe se o app usa bibliotecas particulares, verifique o logcat para identificar o erro de tempo de execução.
A tabela a seguir descreve o comportamento esperado de um
app, dependendo do uso de bibliotecas nativas particulares e do nível desejado da API (android:targetSdkVersion).
| Bibliotecas | Nível desejado da API | Acesso ao ambiente de execução usando o vinculador dinâmico | Comportamento do Android 7.0 (nível 24 da API) | Comportamento futuro da plataforma Android |
|---|---|---|---|---|
| NDK público | Qualquer | Acessível | Funciona como esperado | Funciona como esperado |
| Privadas (bibliotecas privadas temporariamente acessíveis) | 23 ou anterior | Acessível temporariamente | Funciona como esperado, mas você recebe um aviso do logcat. | Erro de tempo de execução |
| Privadas (bibliotecas privadas temporariamente acessíveis) | 24 ou mais recente | Restrito | Erro de tempo de execução | Erro de tempo de execução |
| Particular (outro) | Qualquer | Restrito | Erro de tempo de execução | Erro de tempo de execução |
Verificar se o app usa bibliotecas particulares
Para ajudar a identificar problemas ao carregar bibliotecas particulares, o logcat pode gerar um aviso ou erro de tempo de execução. Por exemplo, se o app for destinado ao nível 23 da API ou anterior e tentar acessar uma biblioteca particular em um dispositivo com o Android 7.0, talvez você veja um aviso semelhante a este:
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible
for the namespace "classloader-namespace" - the access is temporarily granted
as a workaround for http://b/26394120
Esses avisos do logcat informam qual biblioteca está tentando acessar uma API de plataforma privada, mas não causam falhas no app. No entanto, se o app for destinado ao nível desejado da API 24 ou mais recente, o Logcat vai gerar o seguinte erro de tempo de execução, e o app poderá falhar:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so"
("/system/lib/libcutils.so") needed or dlopened by
"/system/lib/libnativeloader.so" is not accessible for the namespace
"classloader-namespace"
at java.lang.Runtime.loadLibrary0(Runtime.java:977)
at java.lang.System.loadLibrary(System.java:1602)
Você também poderá ver essas saídas do logcat se o app usar bibliotecas de terceiros
que se vinculam dinamicamente a APIs de plataforma privadas. A ferramenta readelf no
NDK do Android 7.0 permite gerar uma lista de todas as bibliotecas compartilhadas vinculadas dinamicamente
de um determinado arquivo .so executando o seguinte comando:
aarch64-linux-android-readelf -dW libMyLibrary.so
Atualize o app
Veja algumas etapas que você pode seguir para corrigir esses tipos de erro e garantir que o app não falhe em futuras atualizações da plataforma:
- Se o app usa bibliotecas de plataforma privadas, atualize-o para incluir uma cópia própria dessas bibliotecas ou use as APIs públicas do NDK.
- Se o app usa uma biblioteca de terceiros que acessa símbolos particulares, entre em contato com o autor para que ele atualize a biblioteca.
- Empacote todas as bibliotecas que não são do NDK com o APK.
- Use funções JNI padrão em vez de
getJavaVMegetJNIEnvdelibandroid_runtime.so:AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or JavaVM::AttachCurrentThread from <jni.h>.
- Use
__system_property_getem vez do símbolo particularproperty_getdelibcutils.so. Para fazer isso, use__system_property_getcom a seguinte inclusão:#include <sys/system_properties.h>Observação: a disponibilidade e o conteúdo das propriedades do sistema não são testados pelo CTS. Uma correção melhor seria evitar o uso dessas propriedades.
- Use uma versão local do símbolo
SSL_ctrldelibcrypto.so. Por exemplo, vincule estaticamentelibcyrpto.ano arquivo.soou inclua uma versão vinculada dinamicamente delibcrypto.sodo BoringSSL/OpenSSL e empacote-a no APK.
Android for Work
O Android 7.0 contém mudanças para apps que têm o Android for Work como destino, incluindo mudanças na instalação de certificados, redefinição de senha, gerenciamento de usuários secundários e acesso a identificadores de dispositivos. Se você estiver criando apps para ambientes do Android for Work, revise essas mudanças e modifique seu app de acordo com elas.
- É preciso instalar um instalador de certificado delegado antes que o DPC possa
defini-lo. Para apps de perfil e de proprietário do dispositivo destinados ao Android 7.0 (nível 24 da API),
instale o instalador de certificado delegado antes que o controlador de política de dispositivo (DPC) chame
DevicePolicyManager.setCertInstallerPackage(). Se o instalador ainda não estiver instalado, o sistema vai gerar umaIllegalArgumentException. - As restrições de redefinição de senha para administradores de dispositivos agora se aplicam aos proprietários
de perfil. Os administradores de dispositivos não podem mais usar
DevicePolicyManager.resetPassword()para limpar senhas ou mudar as que já estão definidas. Os administradores do dispositivo ainda podem definir uma senha, mas apenas quando o dispositivo não tiver senha, PIN ou padrão. - Os proprietários de dispositivos e perfis podem gerenciar contas mesmo que restrições estejam
definidas. Os proprietários de dispositivos e de perfis podem chamar as APIs Account Management,
mesmo que as restrições de usuário
DISALLOW_MODIFY_ACCOUNTSestejam em vigor. - Os proprietários de dispositivos podem gerenciar usuários secundários. Quando um dispositivo está
em execução no modo de proprietário do dispositivo, a restrição
DISALLOW_ADD_USERé definida automaticamente. Isso impede que os usuários criem usuários secundários não gerenciados. Além disso, os métodosCreateUser()ecreateAndInitializeUser()foram descontinuados. O novo métodoDevicePolicyManager.createAndManageUser()os substitui. - Os proprietários de dispositivos podem acessar os identificadores de dispositivos. Um proprietário do dispositivo pode acessar o
endereço MAC do Wi-Fi de um dispositivo usando
DevicePolicyManager.getWifiMacAddress(). Se o Wi-Fi nunca tiver sido ativado no dispositivo, esse método vai retornar um valor denull. - A configuração do Modo de Trabalho controla o acesso aos apps de trabalho. Quando o modo de trabalho está desativado, o inicializador do sistema indica que os apps de trabalho estão indisponíveis, deixando-os esmaecidos. Ativar o modo de trabalho novamente restaura o comportamento normal.
- Ao instalar um arquivo PKCS #12 que contém uma cadeia de certificados do cliente e
a chave privada correspondente na interface de configurações, o certificado de CA na
cadeia não é mais instalado no armazenamento de credenciais confiáveis. Isso não
afeta o resultado de
KeyChain.getCertificateChain()quando os apps tentam recuperar a cadeia de certificados do cliente mais tarde. Se necessário, o certificado de CA precisa ser instalado no armazenamento de credenciais confiáveis usando a interface de configurações separadamente, com um formato codificado em DER em uma extensão de arquivo .crt ou .cer. - A partir do Android 7.0, o registro e o armazenamento de impressões digitais são gerenciados por usuário. Se o controlador de política de dispositivo (DPC, na sigla em inglês) de um proprietário de perfil for direcionado ao nível 23 (ou anterior) da API em um dispositivo com o Android 7.0 (nível 24 da API), o usuário ainda poderá definir a impressão digital no dispositivo, mas os aplicativos de trabalho não poderão acessá-la. Quando o DPC tem como destino o nível desejado da API 24 ou mais recente, o usuário pode definir uma impressão digital especificamente para o perfil de trabalho em Configurações > Segurança > Segurança do perfil de trabalho.
- Um novo status de criptografia
ENCRYPTION_STATUS_ACTIVE_PER_USERé retornado porDevicePolicyManager.getStorageEncryptionStatus()para indicar que a criptografia está ativa e que a chave de criptografia está vinculada ao usuário. O novo status só será retornado se o DPC for direcionado ao nível desejado da API 24 ou mais recente. Para apps destinados a níveis da API anteriores,ENCRYPTION_STATUS_ACTIVEé retornado, mesmo que a chave de criptografia seja específica para o usuário ou perfil. - No Android 7.0, vários métodos que normalmente afetariam todo o
dispositivo se comportam de maneira diferente se o dispositivo tiver um perfil de trabalho instalado com um
desafio de trabalho separado. Em vez de afetar todo o dispositivo, esses
métodos se aplicam apenas ao perfil de trabalho. A lista completa desses métodos está
na documentação de
DevicePolicyManager.getParentProfileInstance(). Por exemplo,DevicePolicyManager.lockNow()bloqueia apenas o perfil de trabalho, em vez de bloquear todo o dispositivo. Para cada um desses métodos, é possível acessar o comportamento antigo chamando o método na instância pai doDevicePolicyManager. Para acessar esse pai, chameDevicePolicyManager.getParentProfileInstance(). Por exemplo, se você chamar o métodolockNow()da instância pai, todo o dispositivo será bloqueado.
Retenção de anotações
O Android 7.0 corrige um bug em que a visibilidade das anotações era ignorada. Esse problema permitiu que o ambiente de execução acessasse anotações que não deveria. Essas anotações incluíam:
VISIBILITY_BUILD: destinado a ser visível apenas no momento da criação.VISIBILITY_SYSTEM: destinado a ser visível no ambiente de execução, mas apenas para o sistema subjacente.
Se o app depende desse comportamento, adicione uma política de retenção às anotações
que precisam
estar disponíveis no momento da execução. Para isso, use @Retention(RetentionPolicy.RUNTIME).
Mudanças na configuração padrão de TLS/SSL
O Android 7.0 faz as seguintes mudanças na configuração padrão de TLS/SSL usada por apps para tráfego HTTPS e outros tráfegos TLS/SSL:
- Os pacotes de criptografia RC4 agora estão desativados.
- Os conjuntos de criptografia CHACHA20-POLY1305 agora estão ativados.
A desativação do RC4 por padrão pode causar falhas na conectividade HTTPS ou TLS/SSL quando o servidor não negocia pacotes de criptografia modernos. A correção preferencial é melhorar a configuração do servidor para ativar pacotes de criptografia e protocolos mais fortes e modernos. O ideal é que o TLSv1.2 e o AES-GCM estejam ativados, e os conjuntos de criptografia de Forward Secrecy (ECDHE) estejam ativados e sejam preferenciais.
Uma alternativa é modificar o app para usar um SSLSocketFactory personalizado para se comunicar com o servidor. A
fábrica precisa ser projetada para criar instâncias SSLSocket
que tenham alguns dos pacotes de criptografia exigidos pelo servidor
ativados, além dos pacotes de criptografia padrão.
Observação: essas mudanças não se aplicam ao WebView.
Apps destinados ao Android 7.0
Essas mudanças de comportamento se aplicam exclusivamente a apps destinados ao
Android 7.0 (nível 24 da API) ou versões mais recentes. Os apps que são compilados para o Android 7.0
ou que definem targetSdkVersion como Android 7.0 ou versões mais recentes precisam ser modificados
para oferecer suporte a esses comportamentos de forma adequada, quando aplicável.
Mudanças na serialização
O Android 7.0 (nível 24 da API) corrigiu um bug no cálculo do serialVersionUID padrão, que não correspondia à especificação.
As classes que implementam Serializable
e não especificam um campo serialVersionUID explícito podem
ter uma mudança no serialVersionUID padrão, o que causaria uma exceção
ao tentar desserializar instâncias da classe que foram
serializadas em uma versão anterior ou por um app destinado a uma versão
anterior. A mensagem de erro será semelhante a esta:
local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567
Para corrigir esses problemas, é necessário adicionar um campo serialVersionUID a
qualquer classe afetada com o valor de stream classdesc
serialVersionUID da mensagem de erro, por exemplo, 1234
nesse caso. Essa mudança segue todas as recomendações de boas práticas para
escrever código de serialização e funciona em todas as versões do Android.
O bug específico que foi corrigido estava relacionado à presença de métodos inicializadores
estáticos, ou seja, <clinit>. De acordo com a
especificação, a presença ou ausência de um método inicializador estático na
classe afeta o serialVersionUID padrão calculado para essa classe.
Antes da correção de bug, o cálculo também verificava a superclasse em busca de um
inicializador estático se uma classe não tivesse um.
Para esclarecer, essa mudança não afeta apps que segmentam os níveis 23 ou
anteriores do nível desejado da API, classes que têm um campo serialVersionUID ou classes
que têm um método inicializador estático.
Outros pontos importantes
- Quando um app é executado no Android 7.0, mas tem como destino um nível da API anterior, e o usuário muda o tamanho de exibição, o processo do app é encerrado. O app
precisa ser capaz de lidar com esse cenário de maneira adequada. Caso contrário, ele vai falhar
quando o usuário o restaurar em "Recentes".
Teste o app para garantir que esse comportamento não ocorra. Para isso, cause uma falha idêntica ao encerrar o app manualmente usando o DDMS.
Os apps destinados ao Android 7.0 (nível 24 da API) e versões mais recentes não são encerrados automaticamente em mudanças de densidade. No entanto, eles ainda podem responder mal a mudanças de configuração.
- Os apps no Android 7.0 precisam processar as mudanças de configuração sem problemas e não podem falhar nas inicializações seguintes. Para verificar o comportamento do app, mude o tamanho da fonte (Configurações > Tela > Tamanho da fonte) e restaure o app em "Recentes".
-
Devido a um bug em versões anteriores do Android, o sistema não sinalizava a gravação
em um soquete TCP na linha de execução principal como uma violação do modo estrito. O Android 7.0 corrige esse bug.
Os apps que apresentam esse comportamento agora geram uma
android.os.NetworkOnMainThreadException. Em geral, realizar operações de rede na linha de execução principal não é uma boa ideia porque essas operações costumam ter uma alta latência que causa ANRs e instabilidade. -
A família de métodos
Debug.startMethodTracing()agora armazena a saída por padrão no diretório específico do pacote no armazenamento compartilhado, em vez de no nível superior do cartão SD. Isso significa que os apps não precisam mais solicitar a permissãoWRITE_EXTERNAL_STORAGEpara usar essas APIs. -
Muitas APIs de plataforma agora começaram a verificar se há payloads grandes sendo enviados
em transações
Binder, e o sistema agora gera novamenteTransactionTooLargeExceptionscomoRuntimeExceptions, em vez de registrar ou suprimir silenciosamente. Um exemplo comum é armazenar muitos dados emActivity.onSaveInstanceState(), o que faz com queActivityThread.StopInfogere umaRuntimeExceptionquando o app é destinado ao Android 7.0. -
Se um app postar tarefas
Runnableem umViewe oViewnão estiver anexado a uma janela, o sistema vai colocar a tarefaRunnablena fila com oView. A tarefaRunnablenão será executada até que oViewseja anexado a uma janela. Esse comportamento corrige os seguintes bugs:- Se um app postar em um
Viewde uma linha de execução diferente da linha de execução de interface da janela pretendida, oRunnablepoderá ser executado na linha de execução errada. - Se a tarefa
Runnabletiver sido postada de uma linha de execução que não seja uma linha de execução de looper, o app poderá expor a tarefaRunnable.
- Se um app postar em um
-
Se um app no Android 7.0 com a permissão
DELETE_PACKAGEStentar excluir um pacote, mas outro app tiver instalado esse pacote, o sistema vai exigir a confirmação do usuário. Nesse cenário, os apps devem esperarSTATUS_PENDING_USER_ACTIONcomo o status de retorno ao invocarPackageInstaller.uninstall(). - O provedor JCA chamado Crypto foi descontinuado porque o único algoritmo dele, SHA1PRNG, é criptograficamente fraco. Os apps não podem mais usar SHA1PRNG para derivar chaves (de forma não segura), porque esse provedor não está mais disponível. Para mais informações, consulte a postagem do blog Provedor de segurança "Crypto" descontinuado no Android N.