Modifiche al comportamento di Android 7.0

Oltre a nuove funzionalità, Android 7.0 include una serie di modifiche al comportamento del sistema e delle API. Questo documento evidenzia alcune delle modifiche principali che è necessario comprendere e tenere presenti nelle proprie app.

Se in precedenza hai pubblicato un'app per Android, tieni presente che queste modifiche nella piattaforma potrebbero essere interessate da queste modifiche.

Batteria e memoria

Android 7.0 include modifiche del comportamento del sistema volte a migliorare la durata della batteria dei dispositivi e a ridurre l'utilizzo della RAM. Queste modifiche possono influire sull'accesso dell'app alle risorse di sistema, nonché sul modo in cui l'app interagisce con altre app tramite determinati intent impliciti.

Sospensione

Introdotta in Android 6.0 (livello API 23), la funzionalità Doze migliora la durata della batteria rinviando le attività di CPU e rete quando un utente lascia il dispositivo scollegato, fermo e con lo schermo spento. Android 7.0 introduce ulteriori miglioramenti alla funzionalità Sospensione applicando un sottoinsieme di limitazioni relative a CPU e rete quando il dispositivo è scollegato con lo schermo spento, ma non necessariamente è in movimento, ad esempio quando l'utente è fermo.

Illustrazione di come la funzionalità Sospensione applica un primo livello di limitazioni relative alle attività di sistema per aumentare la durata della batteria

Figura 1. Illustrazione di come la funzionalità Sospensione applica un primo livello di limitazioni relative alle attività di sistema per aumentare la durata della batteria.

Quando il dispositivo è alimentato a batteria e lo schermo è spento per un determinato periodo di tempo, entra in modalità Sospensione e applica il primo sottoinsieme delle limitazioni: interrompe l'accesso alla rete delle app e rinvia i processi e le sincronizzazioni. Se il dispositivo rimane fermo per un determinato periodo di tempo dopo l'attivazione della modalità di sospensione, il sistema applica le restanti limitazioni relative alla sospensione a sveglie PowerManager.WakeLock, AlarmManager, GPS e ricerche di reti Wi-Fi. Indipendentemente dall'applicazione di alcune o tutte le limitazioni di sospensione, il sistema riattiva il dispositivo per brevi periodi di manutenzione, durante i quali alle applicazioni è consentito l'accesso alla rete ed è in grado di eseguire job/sincronizzazioni differite.

Illustrazione di come la funzionalità Sospensione applica un secondo livello di limitazioni relative all'attività di sistema dopo che il dispositivo è fermo per un determinato periodo di tempo

Figura 2. Illustrazione di come la funzionalità Sospensione applica un secondo livello di limitazioni relative all'attività di sistema dopo che il dispositivo è fermo per un determinato periodo di tempo.

Tieni presente che l'attivazione dello schermo o il collegamento al dispositivo comporta l'uscita dalla modalità Sospensione e la rimozione di queste limitazioni di elaborazione. Il comportamento aggiuntivo non influisce sui consigli e sulle best practice per adattare l'app alla versione precedente di Doze introdotta in Android 6.0 (livello API 23), come spiegato nella sezione Ottimizzare sospensione e standby delle app. Devi comunque seguire questi consigli, ad esempio utilizzare Firebase Cloud Messaging (FCM) per inviare e ricevere messaggi, e iniziare a pianificare gli aggiornamenti per soddisfare il comportamento di sospensione aggiuntivo.

Progetto Svelte: ottimizzazioni in background

Android 7.0 rimuove tre trasmissioni implicite per contribuire a ottimizzare l'utilizzo della memoria e il consumo energetico. Questa modifica è necessaria perché le trasmissioni implicite spesso avviano app registrate per ascoltarle in background. La rimozione di questi annunci può migliorare notevolmente le prestazioni del dispositivo e l'esperienza utente.

I dispositivi mobili subiscono frequenti cambiamenti di connettività, ad esempio durante il passaggio dalla rete Wi-Fi ai dati mobili. Attualmente, le app possono monitorare le variazioni di connettività registrando un ricevitore per la trasmissione CONNECTIVITY_ACTION implicita nel manifest. Poiché molte app si registrano per ricevere questa trasmissione, un singolo interruttore di rete può far sì che tutte si sveglino ed elaborino la trasmissione contemporaneamente.

Analogamente, nelle versioni precedenti di Android, le app potevano registrarsi per ricevere trasmissioni implicite ACTION_NEW_PICTURE e ACTION_NEW_VIDEO da altre app, come Fotocamera. Quando un utente scatta una foto con l'app Fotocamera, queste app si riattivano per elaborare la trasmissione.

Per risolvere questi problemi, Android 7.0 applica le seguenti ottimizzazioni:

Se la tua app utilizza uno di questi intent, devi rimuovere le dipendenze da questi intent il prima possibile in modo da poter scegliere correttamente i dispositivi Android 7.0 come target. Il framework Android fornisce diverse soluzioni per ridurre la necessità di queste trasmissioni implicite. Ad esempio, l'API JobScheduler fornisce un meccanismo solido per pianificare le operazioni di rete quando vengono soddisfatte condizioni specificate, come la connessione a una rete unmetered. Puoi anche utilizzare JobScheduler per reagire ai cambiamenti che interessano i fornitori di contenuti.

Per scoprire di più sulle ottimizzazioni in background in Android 7.0 (livello API 24) e su come adattare la tua app, consulta Ottimizzazioni in background.

Modifiche alle autorizzazioni

Android 7.0 include modifiche alle autorizzazioni che potrebbero interessare la tua app.

Modifiche alle autorizzazioni del file system

Per migliorare la sicurezza dei file privati, la directory privata delle app destinate ad Android 7.0 o versioni successive ha limitato l'accesso (0700). Questa impostazione impedisce la fuga di metadati dei file privati, ad esempio le dimensioni o l'esistenza dei file. Questa modifica delle autorizzazioni ha più effetti collaterali:

Condivisione di file tra app

Per le app destinate ad Android 7.0, il framework Android applica il criterio API StrictMode che vieta l'esposizione di URI file:// all'esterno dell'app. Se un intent contenente un URI di file esce dall'app, l'app non riesce con un'eccezione FileUriExposedException.

Per condividere file tra applicazioni, devi inviare un URI content:// e concedere un'autorizzazione di accesso temporanea all'URI. Il modo più semplice per concedere questa autorizzazione è utilizzare la classe FileProvider. Per ulteriori informazioni sulle autorizzazioni e sulla condivisione dei file, consulta la sezione Condivisione di file.

Accessibilità migliorata

Android 7.0 include modifiche volte a migliorare l'usabilità della piattaforma per gli utenti ipovedenti o con problemi di vista. In genere, queste modifiche non dovrebbero richiedere modifiche al codice nella tua app, ma dovresti esaminare queste funzionalità e testarle con la tua app per valutare il potenziale impatto sull'esperienza utente.

Zoom schermo

Android 7.0 consente agli utenti di impostare le Dimensioni del display che ingrandiscono o riducono tutti gli elementi sullo schermo, migliorando così l'accessibilità del dispositivo per gli utenti ipovedenti. Gli utenti non possono ingrandire lo schermo oltre la larghezza minima di sw320dp, ossia la larghezza di un Nexus 4, un comune telefono di medie dimensioni.

Schermo che mostra le dimensioni del display non con zoom del dispositivo su cui è in esecuzione un'immagine di sistema Android 7.0
Schermata che mostra l'effetto dell'aumento delle dimensioni di visualizzazione di un dispositivo con un'immagine di sistema Android 7.0

Figura 3. La schermata a destra mostra l'effetto dell'aumento delle dimensioni del display di un dispositivo con un'immagine di sistema Android 7.0.

Quando la densità dei dispositivi cambia, il sistema invia una notifica alle app in esecuzione nei seguenti modi:

  • Se un'app ha come target il livello API 23 o precedente, il sistema termina automaticamente tutti i processi in background. Ciò significa che se un utente esce da un'app di questo tipo per aprire la schermata Impostazioni e modifica l'impostazione Dimensioni visualizzazione, il sistema termina l'app come in una situazione di memoria insufficiente. Se l'app include processi in primo piano, il sistema invia una notifica a tali processi della modifica della configurazione come descritto in Gestione delle modifiche al runtime, come se l'orientamento del dispositivo fosse cambiato.
  • Se un'app ha come target Android 7.0, tutti i relativi processi (in primo piano e in background) vengono avvisati della modifica della configurazione, come descritto nella sezione Gestione delle modifiche al runtime.

Per la maggior parte delle app non è necessario apportare modifiche per supportare questa funzionalità, purché le app seguano le best practice di Android. Aspetti specifici da verificare:

  • Testa la tua app su un dispositivo con larghezza dello schermo sw320dp e assicurati che funzioni adeguatamente.
  • Quando la configurazione del dispositivo cambia, aggiorna tutte le informazioni memorizzate nella cache dipendenti dalla densità, ad esempio le bitmap memorizzate nella cache o le risorse caricate dalla rete. Verifica la presenza di modifiche alla configurazione quando l'app riprende dallo stato in pausa.

    Nota: se memorizzi nella cache dati dipendenti dalla configurazione, è consigliabile includere metadati pertinenti, ad esempio le dimensioni dello schermo o la densità in pixel appropriate per questi dati. Il salvataggio di questi metadati ti consente di decidere se aggiornare i dati memorizzati nella cache dopo una modifica alla configurazione.

  • Evita di specificare le dimensioni con unità px, poiché non si adattano alla densità dello schermo. Specifica invece le dimensioni con unità pixel indipendenti dalla densità (dp).

Impostazioni visive nella configurazione guidata

Android 7.0 include Impostazioni visive nella schermata di benvenuto, che consentono agli utenti di configurare le seguenti impostazioni di accessibilità su un nuovo dispositivo: Gesto di ingrandimento, Dimensioni carattere, Dimensioni display e TalkBack. Questa modifica aumenta la visibilità di bug relativi a diverse impostazioni dello schermo. Per valutare l'impatto di questa funzionalità, devi testare le tue app con queste impostazioni abilitate. Puoi trovare le impostazioni in Impostazioni > Accessibilità.

Collegamento delle app NDK alle librerie della piattaforma

A partire dalla versione 7.0 di Android, il sistema impedisce il collegamento dinamico delle app con librerie non NDK e questo potrebbe causare l'arresto anomalo dell'app. Questo cambiamento di comportamento mira a creare un'esperienza coerente con le app tra gli aggiornamenti della piattaforma e i diversi dispositivi. Anche se il codice potrebbe non essere collegato a librerie private, è possibile che l'operazione venga eseguita da una libreria statica di terze parti nella tua app. Pertanto, tutti gli sviluppatori dovrebbero verificare che le loro app non abbiano arresti anomali sui dispositivi con Android 7.0. Se la tua app utilizza codice nativo, dovresti utilizzare solo API NDK pubbliche.

La tua app potrebbe tentare di accedere alle API della piattaforma privata in tre modi:

  • La tua app accede direttamente alle librerie private della piattaforma. Devi aggiornare l'app in modo da includere la propria copia di queste librerie o utilizzare le API NDK pubbliche.
  • La tua app utilizza una libreria di terze parti che accede alle librerie private di piattaforme. Anche se hai la certezza che la tua app non acceda direttamente alle librerie private, devi comunque testare la tua app per questo scenario.
  • La tua app fa riferimento a una libreria non inclusa nel relativo APK. Ad esempio, questo può accadere se hai provato a utilizzare la tua copia di OpenSSL ma hai dimenticato di raggrupparla con l'APK della tua app. L'app potrebbe essere eseguita normalmente su versioni della piattaforma Android che includono libcrypto.so. Tuttavia, l'app potrebbe arrestarsi in modo anomalo nelle versioni successive di Android che non includono questa libreria (ad esempio Android 6.0 e versioni successive). Per risolvere il problema, assicurati di raggruppare tutte le librerie non NDK nell'APK.

Le app non devono utilizzare librerie native non incluse nell'NDK perché potrebbero cambiare o essere rimosse tra le diverse versioni di Android. Il passaggio da OpenSSL a BoringSSL è un esempio di questa modifica. Inoltre, poiché non esistono requisiti di compatibilità per le librerie di piattaforme non incluse nell'NDK, dispositivi diversi possono offrire diversi livelli di compatibilità.

Per ridurre l'impatto che questa limitazione potrebbe avere sulle app attualmente rilasciate, un insieme di librerie che vengono utilizzate in modo significativo, come libandroid_runtime.so, libcutils.so, libcrypto.so e libssl.so, sono temporaneamente accessibili su Android 7.0 (livello API 24) per le app che hanno come target il livello API 23 o precedente. Se la tua app carica una di queste librerie, logcat genera un avviso e sul dispositivo di destinazione viene visualizzato un avviso popup per avvisarti. Se vedi questi avvisi, devi aggiornare l'app in modo da includere la propria copia di queste librerie o utilizzare solo le API NDK pubbliche. Le release future della piattaforma Android potrebbero limitare completamente l'utilizzo delle librerie private e causare l'arresto anomalo della tua app.

Tutte le app generano un errore di runtime quando chiamano un'API che non è né pubblica né temporaneamente accessibile. Il risultato è che System.loadLibrary e dlopen(3) restituiscono entrambi NULL e potrebbero causare l'arresto anomalo dell'app. Controlla il codice dell'app per rimuovere l'utilizzo delle API della piattaforma privata e testare attentamente le tue app utilizzando un dispositivo o un emulatore con Android 7.0 (livello API 24). Se non hai la certezza che la tua app utilizzi librerie private, puoi controllare logcat per identificare l'errore di runtime.

La seguente tabella descrive il comportamento previsto di un'app in base all'utilizzo di librerie native private e al livello API target (android:targetSdkVersion).

Librerie Livello API target Accesso runtime tramite linker dinamico Comportamento di Android 7.0 (livello API 24) Comportamento futuro della piattaforma Android
NDK pubblico Qualsiasi Accessibile Funziona come previsto Funziona come previsto
Privata (librerie private accessibili temporaneamente) 23 o inferiore Temporaneamente accessibile Funziona come previsto, ma viene visualizzato un avviso logcat. Errore di runtime
Privata (librerie private accessibili temporaneamente) 24 o successiva Con restrizioni Errore di runtime Errore di runtime
Privato (altro) Qualsiasi Con restrizioni Errore di runtime Errore di runtime

Controllare se l'app utilizza librerie private

Per aiutarti a identificare i problemi di caricamento delle librerie private, logcat potrebbe generare un avviso o un errore di runtime. Ad esempio, se la tua app ha come target il livello API 23 o precedente e tenta di accedere a una libreria privata su un dispositivo con Android 7.0, potresti visualizzare un avviso simile al seguente:

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

Questi avvisi logcat indicano quale libreria sta tentando di accedere a un'API della piattaforma privata, ma non causeranno l'arresto anomalo dell'app. Se l'app ha come target il livello API 24 o successivo, tuttavia, logcat genera il seguente errore di runtime e l'app potrebbe arrestarsi in modo anomalo:

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)

Potresti anche vedere questi output logcat se la tua app utilizza librerie di terze parti che si collegano dinamicamente alle API private della piattaforma. Lo strumento di lettura in Android 7.0DK consente di generare un elenco di tutte le librerie condivise collegate dinamicamente per un determinato file .so eseguendo questo comando:

aarch64-linux-android-readelf -dW libMyLibrary.so

Aggiorna la tua app

Di seguito sono riportati alcuni passaggi che puoi svolgere per correggere questi tipi di errori e assicurarti che l'app non si arresti in modo anomalo negli aggiornamenti futuri della piattaforma:

  • Se la tua app utilizza librerie di piattaforme private, devi aggiornarla in modo da includere la propria copia di tali librerie o utilizzare le API NDK pubbliche.
  • Se la tua app utilizza una libreria di terze parti che accede a simboli privati, contatta l'autore della raccolta per aggiornare la raccolta.
  • Assicurati di pacchettizzare tutte le tue librerie non NDK con il tuo APK.
  • Utilizza le funzioni JNI standard anziché getJavaVM e getJNIEnv di libandroid_runtime.so:
    AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
    AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
    JavaVM::AttachCurrentThread from <jni.h>.
    
  • Usa __system_property_get anziché il simbolo privato property_get di libcutils.so. A questo scopo, usa __system_property_get con quanto segue:
    #include <sys/system_properties.h>
    

    Nota: la disponibilità e i contenuti delle proprietà di sistema non vengono testati tramite CTS. Una soluzione migliore sarebbe evitare di utilizzare tutte queste proprietà.

  • Utilizza una versione locale del simbolo SSL_ctrl di libcrypto.so. Ad esempio, devi collegare libcyrpto.a in modo statico nel file .so oppure includere una versione di libcrypto.so collegata in modo dinamico da BoringSSL/OpenSSL e pacchettizzarla nel tuo APK.

Android for Work

Android 7.0 contiene modifiche per le app destinate ad Android for Work, tra cui modifiche all'installazione dei certificati, alla reimpostazione della password, alla gestione utenti secondaria e all'accesso agli identificatori dei dispositivi. Se sviluppi app per ambienti Android for Work, dovresti rivedere queste modifiche e modificare la tua app di conseguenza.

  • Devi installare un programma di installazione dei certificati delegato prima che il DPC possa impostarlo. Per le app del profilo e del proprietario del dispositivo che hanno come target Android 7.0 (livello API 24), devi installare il programma di installazione dei certificati con delega prima che il controller dei criteri dei dispositivi (DPC) chiami DevicePolicyManager.setCertInstallerPackage(). Se il programma di installazione non è già installato, il sistema genera un IllegalArgumentException.
  • La reimpostazione delle limitazioni della password per gli amministratori dei dispositivi ora si applica ai proprietari del profilo. Gli amministratori dei dispositivi non possono più utilizzare DevicePolicyManager.resetPassword() per cancellare le password o modificare quelle già impostate. Gli amministratori dei dispositivi possono comunque impostare una password, ma solo se il dispositivo non dispone di password, PIN o sequenza.
  • I proprietari di dispositivi e profili possono gestire gli account anche se sono impostate delle limitazioni. I proprietari dei dispositivi e dei profili possono chiamare l'API Account Management anche se sono applicate limitazioni per gli utenti DISALLOW_MODIFY_ACCOUNTS.
  • I proprietari di dispositivi possono gestire più facilmente gli utenti secondari. Quando un dispositivo viene eseguito in modalità Proprietario del dispositivo, la limitazione DISALLOW_ADD_USER viene impostata automaticamente. Questo impedisce agli utenti di creare utenti secondari non gestiti. Inoltre, i metodi CreateUser() e createAndInitializeUser() sono deprecati e vengono sostituiti dal nuovo metodo DevicePolicyManager.createAndManageUser().
  • I proprietari dei dispositivi possono accedere agli identificatori dei dispositivi. Il proprietario di un dispositivo può accedere all'indirizzo MAC Wi-Fi di un dispositivo utilizzando DevicePolicyManager.getWifiMacAddress(). Se il Wi-Fi non è mai stato attivato sul dispositivo, questo metodo restituisce il valore null.
  • L'impostazione Modalità di lavoro controlla l'accesso alle app di lavoro. Quando la modalità di lavoro non è attiva, Avvio app di sistema indica che le app di lavoro non sono disponibili disattivandole. La riattivazione della modalità di lavoro ripristina il comportamento normale.
  • Quando installi un file PKCS #12 contenente una catena di certificati client e la chiave privata corrispondente dalla UI delle impostazioni, il certificato CA nella catena non viene più installato nello spazio di archiviazione delle credenziali attendibili. Ciò non influisce sul risultato di KeyChain.getCertificateChain() quando le app tentano di recuperare la catena di certificati client in un secondo momento. Se necessario, il certificato CA deve essere installato separatamente nell'archiviazione di credenziali attendibili tramite la UI Impostazioni, con un formato con codifica DER e un'estensione del file .crt o .cer.
  • A partire da Android 7.0, la registrazione e l'archiviazione delle impronte vengono gestite in base all'utente. Se il client DPC (Device Policy Client) di un proprietario del profilo ha come target il livello API 23 (o precedente) su un dispositivo con Android 7.0 (livello API 24), l'utente può comunque impostare l'impronta sul dispositivo, ma le applicazioni di lavoro non possono accedere all'impronta del dispositivo. Se il DPC ha come target il livello API 24 o superiore, l'utente può impostare l'impronta in modo specifico per il profilo di lavoro andando su Impostazioni > Sicurezza > Sicurezza del profilo di lavoro.
  • DevicePolicyManager.getStorageEncryptionStatus() restituisce un nuovo stato di crittografia, ENCRYPTION_STATUS_ACTIVE_PER_USER, che indica che la crittografia è attiva e che la chiave di crittografia è legata all'utente. Il nuovo stato viene restituito solo se il DPC ha come target il livello API 24 o superiore. Per le app che hanno come target livelli API precedenti, viene restituito ENCRYPTION_STATUS_ACTIVE anche se la chiave di crittografia è specifica per l'utente o il profilo.
  • In Android 7.0, diversi metodi che in genere influirebbero sull'intero dispositivo si comportano in modo diverso se sul dispositivo è installato un profilo di lavoro con una verifica di lavoro separata. Questi metodi non interessano l'intero dispositivo, ma si applicano solo al profilo di lavoro. L'elenco completo di questi metodi è disponibile nella documentazione di DevicePolicyManager.getParentProfileInstance(). Ad esempio, DevicePolicyManager.lockNow() blocca solo il profilo di lavoro, anziché l'intero dispositivo. Per ognuno di questi metodi, puoi ottenere il comportamento precedente chiamando il metodo sull'istanza padre di DevicePolicyManager; puoi ottenere questo comportamento padre chiamando DevicePolicyManager.getParentProfileInstance(). Ad esempio, se chiami il metodo lockNow() dell'istanza padre, l'intero dispositivo verrà bloccato.

Conservazione delle annotazioni

Android 7.0 corregge un bug per cui la visibilità delle annotazioni veniva ignorata. Questo problema ha consentito al runtime di accedere ad annotazioni che non avrebbe dovuto essere in grado di fare. Queste annotazioni includevano:

  • VISIBILITY_BUILD: dovrebbe essere visibile solo al momento della creazione.
  • VISIBILITY_SYSTEM: destinata a essere visibile in fase di runtime, ma solo al sistema sottostante.

Se la tua app si è affidata a questo comportamento, aggiungi un criterio di conservazione alle annotazioni che devono essere disponibili in fase di runtime. A tale scopo, utilizza @Retention(RetentionPolicy.RUNTIME).

Modifiche alla configurazione predefinita TLS/SSL

Android 7.0 apporta le seguenti modifiche alla configurazione TLS/SSL predefinita utilizzata dalle app per HTTPS e altro traffico TLS/SSL:

  • Le suite di crittografia RC4 sono ora disattivate.
  • Le suite di crittografia CHACHA20-POLY1305 sono ora attivate.

La disattivazione di RC4 per impostazione predefinita potrebbe causare interruzioni della connettività HTTPS o TLS/SSL quando il server non negozia suite di crittografia moderne. La soluzione preferita consiste nel migliorare la configurazione del server per abilitare suite di crittografia e protocolli più potenti e moderni. Idealmente, dovrebbero essere attivati TLSv1.2 e AES-GCM e dovrebbero essere attivate le suite di crittografia Forward Secrecy (ECDHE) e preferite.

In alternativa, puoi modificare l'app in modo da utilizzare un SSLSocketFactory personalizzato per comunicare con il server. La fabbrica dovrebbe essere progettata per creare istanze SSLSocket con alcune delle suite di crittografia richieste dal server abilitate, oltre alle suite di crittografia predefinite.

Nota. Queste modifiche non riguardano WebView.

App che hanno come target Android 7.0

Queste modifiche al comportamento si applicano esclusivamente alle app destinate ad Android 7.0 (livello API 24) o versioni successive. Le app che compilano su Android 7.0 o che impostano targetSdkVersion su Android 7.0 o versioni successive devono modificare le app per supportare correttamente questi comportamenti, ove applicabile all'app.

Modifiche alla serializzazione

Android 7.0 (livello API 24) ha corretto un bug nel calcolo del valore serialVersionUID predefinito per cui non corrispondeva alla specifica.

Le classi che implementano Serializable e non specificano un campo serialVersionUID esplicito potrebbero notare una modifica nel valore serialVersionUID predefinito, il che comporterebbe la generazione di un'eccezione quando si tenta di deserializzare le istanze della classe che sono state serializzate in una versione precedente o da un'app che ha come target una versione precedente. Il messaggio di errore sarà simile al seguente:

local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567

Per risolvere questi problemi è necessario aggiungere un campo serialVersionUID a qualsiasi classe interessata con il valore stream classdesc serialVersionUID dal messaggio di errore, ad esempio 1234 in questo caso. Questa modifica è conforme a tutti i suggerimenti di buone pratiche per la scrittura del codice di serializzazione e funzionerà su tutte le versioni di Android.

Il bug specifico corretto era correlato alla presenza di metodi di inizializzazione statici, ad esempio <clinit>. Secondo la specifica, la presenza o l'assenza di un metodo di inizializzazione statico nella classe influirà sul valore serialVersionUID predefinito calcolato per quella classe. Prima della correzione del bug, il calcolo controllava anche la super classe di un inizializzatore statico, se una classe non ne aveva uno.

Per chiarire, questa modifica non riguarda le app destinate ai livelli API 23 o precedenti, alle classi che hanno un campo serialVersionUID o alle classi che hanno un metodo di inizializzatore statico.

Altri punti importanti

  • Quando un'app è in esecuzione su Android 7.0, ma ha come target un livello API inferiore e l'utente cambia le dimensioni di visualizzazione, il processo dell'app viene interrotto. L'app deve essere in grado di gestire questo scenario correttamente. In caso contrario, si arresta in modo anomalo quando l'utente lo ripristina da Recenti.

    Devi testare l'app per assicurarti che questo comportamento non si verifichi. Per farlo, causa un arresto anomalo identico quando chiudi manualmente l'app tramite DCM.

    Le app che hanno come target Android 7.0 (livello API 24) e versioni successive non vengono terminate automaticamente con le variazioni della densità, ma potrebbero comunque rispondere male alle modifiche alla configurazione.

  • Le app su Android 7.0 dovrebbero essere in grado di gestire agevolmente le modifiche alla configurazione e non dovrebbero arrestarsi in modo anomalo negli avvii successivi. Puoi verificare il comportamento dell'app modificando le dimensioni dei caratteri (Impostazioni > Display > Dimensioni carattere), quindi ripristinando l'app da Recenti.
  • A causa di un bug nelle versioni precedenti di Android, il sistema non ha segnalato la scrittura su un socket TCP nel thread principale come violazione della modalità restrittiva. Android 7.0 corregge questo bug. Le app che mostrano questo comportamento ora generano un android.os.NetworkOnMainThreadException. In genere, eseguire operazioni di rete sul thread principale è una cattiva idea perché di solito hanno un'elevata latenza che causa errori ANR e jank.
  • Per impostazione predefinita, la famiglia di metodi Debug.startMethodTracing() memorizza l'output nella directory specifica del pacchetto nello spazio di archiviazione condiviso, anziché nel livello superiore della scheda SD. Ciò significa che le app non dovranno più richiedere l'autorizzazione WRITE_EXTERNAL_STORAGE per utilizzare queste API.
  • Molte API delle piattaforme hanno iniziato a controllare l'invio di payload di grandi dimensioni attraverso le transazioni Binder e il sistema ora restituisce TransactionTooLargeExceptions come RuntimeExceptions, invece di registrarli o ignorarli in modo invisibile. Un esempio comune è l'archiviazione di troppi dati in Activity.onSaveInstanceState(), per cui ActivityThread.StopInfo restituisce RuntimeException quando la tua app ha come target Android 7.0.
  • Se un'app pubblica Runnable attività in un View e l'elemento View non è collegato a una finestra, il sistema mette in coda l'attività Runnable con View; l'attività Runnable non viene eseguita finché la View non viene collegata a una finestra. Questo comportamento consente di correggere i seguenti bug:
    • Se un'app viene pubblicata in un View da un thread diverso dal thread dell'interfaccia utente della finestra prevista, la Runnable potrebbe essere eseguita nel thread sbagliato.
    • Se l'attività Runnable è stata pubblicata da un thread diverso da un thread del looper, l'app potrebbe esporre l'attività Runnable.
  • Se su Android 7.0 con autorizzazione DELETE_PACKAGES un'app prova a eliminare un pacchetto, ma quel pacchetto era installato da un'altra app, il sistema richiede la conferma dell'utente. In questo scenario, le app dovrebbero aspettarsi STATUS_PENDING_USER_ACTION come stato restituito quando richiamano PackageInstaller.uninstall().
  • Il provider JCA chiamato Crypto è deprecato perché il suo unico algoritmo, SHA1PRNG, è crittograficamente debole. Le app non possono più utilizzare SHA1PRNG per derivare le chiavi (in modo non sicuro), perché questo provider non è più disponibile. Per maggiori informazioni, consulta il blog post Il provider di sicurezza "Crypto" è deprecato in Android N.