Junto com novos recursos e funcionalidades, o Android 7.0 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.
Caso você já tenha publicado 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 com o objetivo de 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 certas intents implícitas.
Soneca
Introduzido no Android 6.0 (API de nível 23), o recurso Soneca melhora a duração da bateria, adiando atividades de CPU e rede quando o usuário deixa o dispositivo desconectado, parado e com a tela desligada. O Android 7.0 traz ainda mais melhorias ao Soneca aplicando um subconjunto de restrições de CPU e rede enquanto o dispositivo está desconectado com a tela desligada, mas não necessariamente com o celular no bolso, por exemplo, quando está viajando, por exemplo.
Quando um dispositivo está usando a energia da bateria e a tela está desligada por um determinado
período, o dispositivo entra no modo Soneca e aplica o primeiro subconjunto de restrições: ele
desativa o acesso do app à rede e adia trabalhos e sincronizações. Se o dispositivo ficar
parado por um determinado período após entrar no modo Soneca, o sistema vai aplicar o
restante das restrições do recurso Soneca aos alarmes PowerManager.WakeLock
,
AlarmManager
, às verificações de GPS e de Wi-Fi. Independentemente de
algumas ou todas as restrições do "Soneca" estarem sendo aplicadas, o sistema ativará o
dispositivo para breves janelas de manutenção, em que os aplicativos terão permissão
para acessar a rede e poderão executar todos os jobs/sincronizações adiados.
A ativação da tela ou do dispositivo encerra o 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 Soneca, introduzida no Android 6.0 (API de nível 23), conforme discutido em Otimizar para apps em espera e Soneca. Siga 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 recurso 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 transmissões implícitas iniciam apps registrados com frequência para ouvi-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 na conectividade, como a alternância
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 de CONNECTIVITY_ACTION
no
manifesto. Como muitos apps se registram para receber essa transmissão, uma única
troca de rede pode fazer com que todos ativem 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 a
Câmera. Quando um usuário tira uma foto com o app Câmera, esses apps são despertados
para processar a transmissão.
Para aliviar esses problemas, o Android 7.0 aplica as seguintes otimizações:
- Os apps destinados ao Android 7.0 (API de nível 24) e versões mais recentes não receberão
transmissões
CONNECTIVITY_ACTION
se declararem o broadcast receiver no manifesto. Os apps ainda receberão transmissõesCONNECTIVITY_ACTION
se registrarem oBroadcastReceiver
noContext.registerReceiver()
e esse contexto ainda for válido. - O sistema não envia mais transmissões
ACTION_NEW_PICTURE
ouACTION_NEW_VIDEO
. Essa otimização afeta todos os apps, não apenas aqueles destinados ao Android 7.0.
Caso seu app use qualquer uma dessas intents, remova as dependências
delas o mais rápido possível para segmentar corretamente os dispositivos Android 7.0.
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 as condições especificadas, como conexão com uma
rede ilimitada, são atendidas. Você pode até usar JobScheduler
para reagir a mudanças nos provedores de conteúdo.
Para saber mais sobre otimizações em segundo plano no Android 7.0 (API de nível 24) e como adaptar seu app, consulte Otimizações em segundo plano.
Alterações nas permissões
O Android 7.0 inclui alterações nas permissões que podem afetar seu aplicativo.
Alterações 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 alteração de permissão produz vários efeitos colaterais:
-
O proprietário não deve mais relaxar as permissões de arquivos particulares,
e uma tentativa de fazer isso usando
MODE_WORLD_READABLE
e/ouMODE_WORLD_WRITEABLE
acionará umaSecurityException
.Observação:no momento, essa restrição não foi totalmente aplicada. Os apps ainda podem modificar as permissões para o diretório privado usando APIs nativas ou a API
File
. No entanto, não recomendamos o relaxamento de permissões para o diretório privado. -
A transmissão de URIs
file://
para fora do domínio do pacote pode deixar o receptor com um caminho inacessível. Portanto, as tentativas de transmitir um URIfile://
acionam umaFileUriExposedException
. A maneira recomendada de compartilhar o conteúdo de um arquivo particular é usando oFileProvider
. -
O
DownloadManager
não consegue mais compartilhar arquivos armazenados de forma privada por nome de arquivo. Os aplicativos legados podem acabar em um caminho inacessível ao acessarCOLUMN_LOCAL_FILENAME
. Os apps destinados ao Android 7.0 ou versões mais recentes acionam umaSecurityException
ao tentar acessarCOLUMN_LOCAL_FILENAME
. Aplicativos legados que definem o local de download como um local público usandoDownloadManager.Request.setDestinationInExternalFilesDir()
ouDownloadManager.Request.setDestinationInExternalPublicDir()
ainda podem acessar o caminho emCOLUMN_LOCAL_FILENAME
. No entanto, esse método não é recomendado. A maneira preferencial de acessar um arquivo exposto peloDownloadManager
é usandoContentResolver.openFileDescriptor()
.
Compartilhamento de arquivos entre aplicativos
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 falhará
com uma exceção FileUriExposedException
.
Para compartilhar arquivos entre aplicativos, envie um URI content://
e conceda uma permissão de acesso temporária ao URI. 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 destinadas a melhorar a usabilidade da plataforma para usuários com visão baixa ou deficiente. Em geral, essas mudanças não exigem mudanças de código no app. No entanto, é importante analisar e testar esse recurso com seu app para avaliar possíveis impactos na experiência do usuário.
Zoom de tela
O Android 7.0 permite que os usuários definam o Tamanho da tela, 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 alterar o zoom da tela além da largura mínima de tela de sw320dp, que é a largura de um Nexus 4, um smartphone comum de tamanho médio.
Quando a densidade do dispositivo mudar, o sistema notificará os apps em execução das seguintes maneiras:
- Se um app for direcionado ao nível 23 da API ou anterior, o sistema encerrará automaticamente todos os processos em segundo plano. Isso significa que, se um usuário sair desse app para abrir a tela Configurações e mudar a configuração Tamanho da tela, o sistema encerrará o app da mesma maneira que faria em uma situação de pouca memória. Se o app tiver algum processo em primeiro plano, o sistema vai notificar esses processos sobre a mudança de configuração, conforme descrito em Como processar mudanças no momento da 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 ser alterada para oferecer suporte a esse recurso, desde que os apps sigam as práticas recomendadas do Android. Os itens específicos a serem verificados são:
- Teste seu app em um dispositivo com largura de tela
sw320dp
e verifique se ele tem o desempenho adequado. - Quando a configuração do dispositivo mudar, atualize todas as informações dependentes de densidade armazenadas
em cache, como bitmaps em cache ou recursos carregados da
rede. Verifique se há mudanças de configuração quando o app sair do estado pausado e retomar.
Observação:se você armazenar em cache dados dependentes de configuração, é recomendável incluir metadados relevantes, como o tamanho de tela ou a densidade de pixels adequado 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 redimensionadas de acordo com a densidade de tela. Em vez disso, especifique dimensões com unidades de pixel de densidade independente (
dp
).
Configurações de visão no assistente de configuração
O Android 7.0 inclui configurações de visão na tela de boas-vindas, onde os usuários podem definir as seguintes configurações de acessibilidade em um novo dispositivo: Gesto de ampliação, Tamanho da fonte, Tamanho da tela 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. Encontre as configurações em Configurações > Acessibilidade.
Aplicativos NDK vinculados a bibliotecas da plataforma
A partir do Android 7.0, o sistema impede que os apps se vinculem dinamicamente a bibliotecas não NDK, o que pode causar falhas no app. Essa mudança de comportamento visa criar uma experiência de app consistente em todas as atualizações da plataforma e dispositivos. Mesmo que seu código não esteja vinculado a bibliotecas privadas, é possível que uma biblioteca estática de terceiros no seu app esteja fazendo isso. Portanto, todos os desenvolvedores precisam verificar se os apps deles não apresentam falhas em dispositivos com o Android 7.0. Caso seu app use código nativo, use apenas APIs públicas do NDK.
Seu app pode estar tentando acessar APIs de plataforma privada de três maneiras:
- O aplicativo acessa bibliotecas privadas da plataforma diretamente. Atualize seu app para incluir a própria cópia dessas bibliotecas ou usar as APIs públicas do NDK.
- Seu app usa uma biblioteca de terceiros que acessa bibliotecas privadas da plataforma. Mesmo que você tenha certeza de que o app não acessa bibliotecas privadas diretamente, ainda é necessário testá-lo nesse cenário.
- O aplicativo referencia uma biblioteca não incluída no seu APK. Por
exemplo, isso pode acontecer se você tentou usar sua própria cópia do OpenSSL, mas
esqueceu de agrupá-la com o APK do seu 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 não incluídas no NDK porque elas podem mudar ou ser removidas entre diferentes versões do Android. A mudança de OpenSSL para 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 distintos de compatibilidade.
Para reduzir o impacto que essa restrição pode ter sobre os apps
lançados atualmente, um conjunto de bibliotecas que apresentam uso significativo, como
libandroid_runtime.so
, libcutils.so
,
libcrypto.so
e libssl.so
, está temporariamente
acessível no Android 7.0 (nível 24 da API) para apps direcionados ao nível 23 da API ou
anterior. Se o app carrega uma dessas bibliotecas, o Logcat gera um aviso e um aviso aparece no dispositivo de destino para notificar você. Se você vir esses
avisos, atualize seu app para incluir a própria cópia dessas
bibliotecas ou usar apenas as APIs NDK públicas. Versões futuras da plataforma Android podem restringir o uso de bibliotecas privadas e causar falhas no app.
Todos os apps geram um erro de tempo de execução ao chamar uma API que não é
pública nem temporariamente acessível. O resultado é que
System.loadLibrary
e dlopen(3)
retornam
NULL
e podem causar uma falha no app. Revise o
código do app para remover o uso de APIs de plataforma privada e faça testes completos nos apps
usando um dispositivo ou emulador com o Android 7.0 (nível 24 da API). Se você não
tem certeza se seu app usa bibliotecas privadas, verifique o logcat para identificar o erro de execução.
A tabela a seguir descreve o comportamento que você pode esperar de um
app dependendo do uso de bibliotecas nativas privadas e do nível desejado
da API (android:targetSdkVersion
).
Bibliotecas | Nível desejado da API | Acesso em tempo de execução via vinculador dinâmico | Comportamento do Android 7.0 (API de nível 24) | Comportamento da plataforma Android futura |
---|---|---|---|---|
Pública do NDK | Alguma | Acessibilidade | Funciona como o esperado | Funciona como o esperado |
Privado (bibliotecas privadas temporariamente acessíveis) | 23 ou inferior | Temporariamente acessível | Funciona como o esperado, mas você recebe um aviso do logcat. | Erro em tempo de execução |
Privado (bibliotecas privadas temporariamente acessíveis) | 24 ou superior | Restrito | Erro em tempo de execução | Erro em tempo de execução |
Privado (outro) | Alguma | Restrito | Erro em tempo de execução | Erro em tempo de execução |
Verificar se o aplicativo usa bibliotecas privadas
Para ajudar a identificar problemas ao carregar bibliotecas privadas, o logcat pode gerar um aviso ou erro de ambiente de execução. Por exemplo, se o app for direcionado ao nível de API 23 ou anterior e tentar acessar uma biblioteca privada em um dispositivo com o Android 7.0, você poderá receber um aviso semelhante ao seguinte:
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 farão o app falhar. No entanto, se o app for direcionado à API de nível 24 ou mais recente, o logcat vai gerar o seguinte erro de tempo de execução e seu 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
vinculadas dinamicamente a APIs de plataforma privadas. A ferramenta readelf do Android 7.0DK 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 privadas de plataforma, atualize-o para incluir a própria cópia dessas bibliotecas ou use as APIs públicas do NDK.
- Caso seu app use uma biblioteca de terceiros que acesse símbolos privados, entre em contato com o autor da biblioteca para atualizá-la.
- Certifique-se de agrupar todas as bibliotecas externas ao NDK ao APK.
- Use as funções JNI padrão em vez de
getJavaVM
egetJNIEnv
delibandroid_runtime.so
:AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or JavaVM::AttachCurrentThread from <jni.h>.
- Use
__system_property_get
em vez do símbolo particularproperty_get
delibcutils.so
. Para fazer isso, use__system_property_get
com o seguinte include:#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 solução melhor seria evitar o uso dessas propriedades juntas.
- Use uma versão local do símbolo
SSL_ctrl
delibcrypto.so
. Por exemplo, vinculelibcyrpto.a
estaticamente no arquivo.so
ou inclua uma versão vinculada dinamicamente delibcrypto.so
do BoringSSL/OpenSSL e empacote-a no APK.
Android for Work
O Android 7.0 contém alterações para apps destinados ao Android for Work, incluindo alterações na instalação de certificados, redefinição de senha, gerenciamento secundário de usuários e acesso a identificadores de dispositivos. Se você estiver criando apps para ambientes do Android for Work, analise essas mudanças e modifique o app conforme necessário.
- Você precisa instalar um instalador de certificado delegado antes que o DPC possa configurá-lo. Para apps de perfis e de proprietários de dispositivos destinados ao Android 7.0 (nível 24 da API),
é necessário instalar o instalador de certificado delegado antes que o controlador
de política de dispositivo (DPC, na sigla em inglês) 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 perfis. Os administradores de dispositivo 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 tem senha, PIN ou padrão. - Proprietários de dispositivo e perfil podem gerenciar contas mesmo com restrições
definidas. Proprietários de dispositivos e de perfis podem chamar as APIs de gerenciamento de contas,
mesmo que as restrições de usuário
DISALLOW_MODIFY_ACCOUNTS
estejam em vigor. - Os donos de dispositivo podem gerenciar usuários secundários com maior facilidade. Quando um dispositivo está
sendo executado no modo "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 e foram substituídos pelo novo métodoDevicePolicyManager.createAndManageUser()
. - Os proprietários de dispositivo podem acessar identificadores de dispositivo. O proprietário de um dispositivo pode acessar o
endereço MAC Wi-Fi de um dispositivo usando
DevicePolicyManager.getWifiMacAddress()
. Se o Wi-Fi nunca foi ativado no dispositivo, esse método retornará o valornull
. - A configuração modo de trabalho controla o acesso a aplicativos de trabalho. Quando o modo de trabalho está desativado, a tela de início do sistema esmaece para indicar que os apps de trabalho estão indisponíveis. Ativar o modo de trabalho novamente restaura o comportamento normal.
- Ao instalar um arquivo PKCS no 12 que contém uma cadeia de certificados do cliente e
a chave privada correspondente da 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 separadamente no armazenamento de credenciais confiáveis pela interface de configurações, com um formato codificado por DER em uma extensão de arquivo .crt ou .cer. - A partir do Android 7.0, o registro e o armazenamento de impressão digital são gerenciados por usuário. Se o cliente da política de dispositivos (DPC, na sigla em inglês) de um proprietário de perfil for direcionado ao nível 23 da API (ou anterior) em um dispositivo com 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 é direcionado ao nível 24 da API e versões mais recentes, o usuário pode definir a impressão digital especificamente para o perfil de trabalho acessando Configurações > Segurança > Segurança do perfil de trabalho.
- Um novo status
ENCRYPTION_STATUS_ACTIVE_PER_USER
é retornado porDevicePolicyManager.getStorageEncryptionStatus()
para indicar que a criptografia está ativa e a chave está vinculada ao usuário. O novo status só será retornado se o DPC visar trabalhar com API de nível 24 e posteriores. Para apps direcionados a níveis de API anteriores,ENCRYPTION_STATUS_ACTIVE
será 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 do
DevicePolicyManager.getParentProfileInstance()
. Por exemplo, oDevicePolicyManager.lockNow()
bloqueia apenas o perfil de trabalho, em vez de bloquear todo o dispositivo. Para cada um desses métodos, você pode receber o comportamento antigo chamando o método na instância pai deDevicePolicyManager
. Você pode receber esse pai chamandoDevicePolicyManager.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 resolve um problema em que a visibilidade das anotações foi ignorada. Esse problema permitiu que o ambiente de execução acessasse anotações que não deveria conseguir. Dentre essas anotações, estão:
VISIBILITY_BUILD
: deveria estar visível apenas no momento da criação.VISIBILITY_SYSTEM
: deveria estar visível durante a execução, mas apenas para o sistema.
Se seu app se baseou nesse 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 TLS/SSL padrão usada por apps para HTTPS e outros tipos de tráfego TLS/SSL:
- Os pacotes de criptografia RC4 agora estão desativados.
- Os conjuntos de criptografia CHACHA20-POLY1305 estão ativados.
Se o RC4 for desativado por padrão, poderá ocorrer falhas na conectividade HTTPS ou TLS/SSL quando o servidor não negocia conjuntos de criptografia modernos. A solução recomendada é melhorar a configuração do servidor para permitir pacotes e protocolos de criptografia mais fortes e modernos. O ideal é que TLSv1.2 e AES-GCM estejam ativados e que os pacotes de criptografia Forward Secrecy (ECDHE) estejam ativados e tenham preferência.
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 de SSLSocket
que tenham alguns dos conjuntos de criptografia exigidos pelo servidor ativados, além dos conjuntos 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 compilados no Android 7.0
ou definidos targetSdkVersion
como Android 7.0 ou mais recente precisam ser
modificados para oferecer suporte a esses comportamentos de forma adequada, quando aplicável.
Mudanças na serialização
O Android 7.0 (API de nível 24) corrigiu um bug no cálculo do serialVersionUID padrão, em que ele não correspondia à especificação.
As classes que implementam Serializable
e não especificam um campo serialVersionUID
explícito podem encontrar uma alteração no serialVersionUID padrão que causaria uma exceção ao tentar desserializar instâncias da classe que foram serializadas em uma versão anterior ou serializadas por um app direcionado 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, como 1234
nesse caso. Essa mudança segue todas as recomendações de práticas recomendadas para
escrever código de serialização e funcionará em todas as versões do Android.
O bug específico que foi corrigido estava relacionado à presença de métodos de
inicialização estáticos, ou seja, <clinit>
. De acordo com a especificação, a presença ou ausência de um método de inicialização estático na classe afeta o serialVersionUID padrão calculado para essa classe.
Antes da correção do bug, o cálculo também verificava se a superclasse tinha um inicializador estático, caso uma classe não tivesse um.
Para esclarecer, essa mudança não afeta os apps direcionados ao nível 23 da API ou
anteriores, classes que têm um campo serialVersionUID
ou
que têm um método inicializador estático.
Outros pontos importantes
- Quando um app está em execução no Android 7.0, mas é direcionado a um nível de API anterior
e o usuário muda o tamanho da tela, o processo do app é encerrado. O app
precisa ser capaz de lidar corretamente com esse cenário. Caso contrário, ele falhará
quando o usuário o restaurar em Recents.
Teste seu app para garantir que esse comportamento não ocorra. Isso pode ser feito causando uma falha idêntica ao encerrar o app manualmente pelo 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, ainda podem responder mal a mudanças de configuração.
- Os apps no Android 7.0 precisam processar corretamente as mudanças de configuração e não falhar em inicializações subsequentes. Você pode verificar o comportamento do app mudando o tamanho da fonte (Configurações > Exibição > Tamanho da fonte) e restaurando o app em "Recentes".
-
Devido a um bug em versões anteriores do Android, o sistema não sinaliza a gravação
em um soquete TCP na linha de execução principal como uma violação de modo estrito. O Android 7.0 corrige esse problema.
Apps que exibem esse comportamento agora geram uma
android.os.NetworkOnMainThreadException
. Geralmente, realizar operações de rede na linha de execução principal não é uma boa ideia, porque essas operações costumam ter uma latência alta que causa ANRs e instabilidade. -
A família de métodos
Debug.startMethodTracing()
agora armazena por padrão a saída 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_STORAGE
para usar essas APIs. -
Muitas APIs de plataforma agora começaram a verificar se grandes payloads estão sendo enviados
por meio de transações
Binder
, e o sistema agora geraTransactionTooLargeExceptions
novamente comoRuntimeExceptions
, em vez de registrá-los ou suprimir esses payloads silenciosamente. Um exemplo comum é armazenar muitos dados emActivity.onSaveInstanceState()
, o que faz com queActivityThread.StopInfo
gere umaRuntimeException
quando o app é direcionado ao Android 7.0. -
Se um app postar tarefas
Runnable
em umaView
e oView
não estiver anexado a uma janela, o sistema vai enfileirar a tarefaRunnable
com aView
. A tarefaRunnable
não será executada até que aView
seja anexada a uma janela. Esse comportamento corrige os seguintes bugs:- Se um app publicar em um
View
de uma linha de execução diferente da linha de execução de IU da janela pretendida, oRunnable
poderá ser executado na linha de execução errada. - Se a tarefa
Runnable
fosse postada a partir de uma linha de execução diferente de uma linha de execução de looper, o app poderia expor a tarefaRunnable
.
- Se um app publicar em um
-
Se um app no Android 7.0 com
permissão
DELETE_PACKAGES
tentar excluir um pacote instalado por outro app, o sistema vai solicitar a confirmação do usuário. Nesse cenário, os apps precisam esperarSTATUS_PENDING_USER_ACTION
como 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 o SHA1PRNG para (de forma não segura) derivar chaves, porque esse provedor não está mais disponível. Para saber mais, consulte a postagem do blog Provedor de segurança "Crypto" descontinuado no Android N.