Modifiche al comportamento di Android 7.0

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

Se hai già pubblicato un'app per Android, tieni presente che la tua app potrebbe essere interessata da queste modifiche nella piattaforma.

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 e 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 posticipando 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 di CPU e rete quando il dispositivo è scollegato con lo schermo spento, ma non necessariamente è fermo, ad esempio quando è in viaggio.

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

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

Quando un dispositivo è alimentato a batteria e lo schermo è spento per un determinato periodo di tempo, il dispositivo entra in modalità Sospensione e applica il primo sottoinsieme di limitazioni: interrompe l'accesso alla rete delle app e reinvia job e sincronizzazioni. Se il dispositivo rimane fermo per un determinato periodo di tempo dopo l'attivazione della modalità Sospensione, il sistema applica il resto delle limitazioni relative alla sospensione a PowerManager.WakeLock, sveglie 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 e possono eseguire job/sincronizzazioni differite.

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

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

Tieni presente che l'attivazione dello schermo o il collegamento del dispositivo comporta l'uscita dalla modalità Sospensione e la rimozione di queste limitazioni relative all'elaborazione. Il comportamento aggiuntivo non influisce su suggerimenti e best practice per adattare l'app alla versione precedente di Doze introdotta in Android 6.0 (livello API 23), come spiegato nella sezione Ottimizzazione per sospensione e standby delle app. Devi comunque seguire questi suggerimenti, 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.

Project Svelte: ottimizzazioni in background

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

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

Analogamente, nelle versioni precedenti di Android, le app potevano registrarsi per ricevere annunci ACTION_NEW_PICTURE e ACTION_NEW_VIDEO impliciti da altre app, ad esempio Fotocamera. Quando un utente scatta una foto con l'app Fotocamera, queste app si attivano 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 per poter scegliere correttamente come target i dispositivi Android 7.0. Il framework Android offre 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 apportati ai fornitori di contenuti.

Per saperne di più sulle ottimizzazioni in background in Android 7.0 (livello API 24) e su come adattare la tua app, consulta la pagina 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, l'accesso alla directory privata delle app destinate ad Android 7.0 o versioni successive è limitato (0700). Questa impostazione impedisce la perdita di metadati dei file privati, ad esempio le dimensioni o l'esistenza dei file. Questa modifica delle autorizzazioni ha diversi effetti collaterali:

Condivisione di file tra app

Per le app che hanno come target Android 7.0, il framework Android applica il criterio dell'API StrictMode che vieta l'esposizione degli URI file:// all'esterno dell'app. Se un intent contenente l'URI di un file lascia l'app, l'app non va a buon fine 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, vedi Condivisione dei file.

Accessibilità migliorata

Android 7.0 include modifiche volte a migliorare l'usabilità della piattaforma per gli utenti ipovedenti o con disabilità visiva. In genere queste modifiche non dovrebbero richiedere modifiche al codice nell'app, ma ti consigliamo di esaminare queste funzionalità e testarle con l'app per valutare il potenziale impatto sull'esperienza utente.

Zoom schermo

Android 7.0 consente agli utenti di impostare le Dimensioni del display in modo da ingrandire o ridurre tutti gli elementi sullo schermo, migliorando così l'accessibilità del dispositivo per gli utenti ipovedenti. Gli utenti non possono eseguire lo zoom dello 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 zoomate 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à del dispositivo cambia, il sistema avvisa le app in esecuzione nei seguenti modi:

  • Se un'app ha come target il livello API 23 o un livello 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 farebbe in una situazione di memoria insufficiente. Se nell'app sono presenti processi in primo piano, il sistema notifica a questi processi la 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 processi (in primo piano e in background) vengono avvisati della modifica della configurazione, come descritto in Gestione delle modifiche al runtime.

Per la maggior parte delle app non è necessario apportare modifiche per supportare questa funzionalità, a condizione che 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 in modo adeguato.
  • Quando la configurazione del dispositivo cambia, aggiorna le informazioni memorizzate nella cache che dipendono dalla densità, ad esempio le informazioni memorizzate nella cache o le risorse caricate dalla rete. Verifica la presenza di modifiche alla configurazione quando l'app viene ripristinata dallo stato in pausa.

    Nota: se memorizzi nella cache dati dipendenti dalla configurazione, è consigliabile includere i metadati pertinenti, come le dimensioni dello schermo o la densità in pixel appropriati. 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 vengono scalate in base alla densità dello schermo. Specifica invece le dimensioni con unità pixel indipendenti dalla densità (dp).

Impostazioni visive nella configurazione guidata

Android 7.0 include le impostazioni visive nella schermata di benvenuto, in cui gli utenti possono configurare le seguenti impostazioni di accessibilità su un nuovo dispositivo: Gesto di ingrandimento, Dimensione carattere, Dimensioni display e TalkBack. Questa modifica aumenta la visibilità dei 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 da Android 7.0, il sistema impedisce il collegamento dinamico delle app a librerie non NDK, causando possibili arresti anomali dell'app. Questo cambiamento di comportamento mira a creare un'esperienza coerente con le app negli aggiornamenti della piattaforma e su dispositivi diversi. Anche se il codice non rimanda alle librerie private, è possibile che una libreria statica di terze parti nella tua app lo faccia. Pertanto, tutti gli sviluppatori dovrebbero controllare che le loro app non abbiano un arresto anomalo sui dispositivi con Android 7.0. Se la tua app utilizza codice nativo, devi utilizzare solo API NDK pubbliche.

Sono tre i modi in cui la tua app potrebbe tentare di accedere alle API delle piattaforme private:

  • La tua app accede direttamente alle librerie di piattaforme private. Devi aggiornare l'app includendo la relativa copia di queste librerie o utilizzare le API NDK pubbliche.
  • La tua app utilizza una libreria di terze parti che accede alle librerie private delle piattaforme. Anche se hai la certezza che la tua app non acceda direttamente alle librerie private, devi comunque testare l'app per questo scenario.
  • La tua app fa riferimento a una libreria non inclusa nel relativo APK. Ad esempio, questo potrebbe accadere se hai provato a utilizzare la tua copia di OpenSSL ma hai dimenticato di raggrupparlo con l'APK della tua app. L'app potrebbe funzionare 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 con il tuo APK.

Le app non devono utilizzare librerie native non incluse nell'NDK perché potrebbero cambiare o essere rimosse tra versioni diverse 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 livelli diversi di compatibilità.

Per ridurre l'impatto che questa limitazione potrebbe avere sulle app attualmente rilasciate, un insieme di librerie che registrano un uso 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 versioni precedenti. 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. Di conseguenza, 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 delle piattaforme private e testare accuratamente le tue app utilizzando un dispositivo o un emulatore con Android 7.0 (livello API 24). Se non sai con certezza se la tua app utilizza 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 relativo livello API target (android:targetSdkVersion).

Librerie Livello API target Accesso al runtime tramite linker dinamico Comportamento di Android 7.0 (livello API 24) Comportamento futuro della piattaforma Android
NDK pubblico Qualsiasi Accessibili Funziona come previsto Funziona come previsto
Privata (librerie private accessibili temporaneamente) 23 o meno Temporaneamente accessibile Funziona come previsto, ma viene visualizzato un avviso logcat. Errore di runtime
Privata (librerie private accessibili temporaneamente) 24 o successiva Con limitazioni Errore di runtime Errore di runtime
Privato (altro) Qualsiasi Con limitazioni 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 di una piattaforma privata, ma non causano l'arresto anomalo dell'app. Tuttavia, se l'app ha come target il livello API 24 o versioni successive, logcat genera il seguente errore di runtime e la tua 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 della piattaforma privata. Lo strumento Readelf di Android 7.0DK consente di generare un elenco di tutte le librerie condivise collegate dinamicamente di 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 seguire 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 della piattaforma private, devi aggiornarla in modo da includere una copia personale di queste 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 libreria per aggiornare la libreria.
  • Assicurati di pacchettizzare tutte le librerie non NDK nel tuo APK.
  • Usa le funzioni JNI standard anziché getJavaVM e getJNIEnv da 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 completamente di utilizzare queste proprietà.

  • Utilizza una versione locale del simbolo SSL_ctrl di libcrypto.so. Ad esempio, dovresti collegare in modo statico libcyrpto.a nel file .so oppure includere una versione di libcrypto.so a collegamento 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 delle password, alla gestione utenti secondaria e all'accesso agli identificatori dei dispositivi. Se stai creando app per ambienti Android for Work, devi esaminare queste modifiche e modificare l'app di conseguenza.

  • Devi installare un programma di installazione del certificato 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 del certificato delegato prima che il controller dei criteri dei dispositivi (DPC) chiami DevicePolicyManager.setCertInstallerPackage(). Se il programma di installazione non è già installato, il sistema genera un messaggio IllegalArgumentException.
  • Le limitazioni della reimpostazione della password per gli amministratori dei dispositivi ora vengono applicate 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 ha password, PIN o sequenza.
  • I proprietari di dispositivi e profili possono gestire gli account anche se sono impostate delle limitazioni. I proprietari di dispositivi e profili possono chiamare l'API Account Management anche se sono in vigore le limitazioni utente di DISALLOW_MODIFY_ACCOUNTS.
  • I proprietari dei dispositivi possono gestire più facilmente gli utenti secondari. Quando un dispositivo è in esecuzione 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à Lavoro controlla l'accesso alle app di lavoro. Quando la modalità Lavoro non è attiva, Avvio app di sistema indica che le app di lavoro non sono disponibili rendendole selezionabili in grigio. Se abiliti di nuovo la modalità di lavoro, verrà ripristinato il comportamento normale.
  • Quando installi un file PKCS #12 contenente una catena di certificati client e la chiave privata corrispondente dall'interfaccia utente Impostazioni, il certificato CA nella catena non viene più installato nell'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 richiesto, il certificato CA deve essere installato separatamente nell'archiviazione delle credenziali attendibili tramite l'interfaccia utente delle 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 sono gestite in base all'utente. Se il client DPC (Device Policy Client) del proprietario di un 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 versioni successive, l'utente può impostare l'impronta digitale 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, a indicare 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 solitamente incidono sull'intero dispositivo si comportano in modo diverso se sul dispositivo è installato un profilo di lavoro con una verifica di lavoro separata. Anziché interessare l'intero dispositivo, questi metodi 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é bloccare l'intero dispositivo. Per ognuno di questi metodi, puoi ottenere il comportamento precedente chiamando il metodo sull'istanza padre di DevicePolicyManager; puoi ottenere questo metodo padre chiamando DevicePolicyManager.getParentProfileInstance(). Ad esempio, se chiami il metodo lockNow() dell'istanza padre, l'intero dispositivo viene 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 a cui non avrebbe dovuto essere. Queste annotazioni includevano:

  • VISIBILITY_BUILD: dovrebbero essere visibili solo al momento della creazione.
  • VISIBILITY_SYSTEM: deve essere visibile in fase di runtime, ma solo al sistema sottostante.

Se la tua app ha fatto affidamento su questo comportamento, aggiungi alle annotazioni un criterio di conservazione che deve essere disponibile in fase di runtime. Per farlo, devi utilizzare @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 abilitate.

La disattivazione di RC4 per impostazione predefinita potrebbe causare interruzioni nella 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ù solidi e moderni. Idealmente, TLSv1.2 e AES-GCM dovrebbero essere attivati e le suite di crittografia Forward Secrecy (ECDHE) dovrebbero essere abilitate e preferite.

Un'alternativa è modificare l'app per utilizzare un SSLSocketFactory personalizzato per comunicare con il server. Il dati di fabbrica dovrebbe essere progettato per creare istanze SSLSocket che dispongono di alcune delle suite di crittografia richieste dal server abilitate, oltre alle suite di crittografia predefinite.

Nota. Queste modifiche non riguardano WebView.

App destinate ad 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 vengono compilate in base ad Android 7.0 o impostano targetSdkVersion su Android 7.0 o versioni successive devono modificare le proprie 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 in cui non corrispondeva alla specifica.

Le classi che implementano Serializable e non specificano un campo serialVersionUID esplicito potrebbero vedere una modifica nel valore serialVersionUID predefinito, il che causerebbe un'eccezione quando si tenta di deserializzare le istanze della classe che sono state serializzate su una versione precedente o serializzate 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 prassi per la scrittura del codice di serie e funzionerà su tutte le versioni di Android.

Il bug specifico corretto riguardava la presenza di metodi di inizializzazione statici, ad esempio <clinit>. In base alla 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 superclasse per un inizializzatore statico, se una classe non ne aveva uno.

Per chiarire, questa modifica non interessa le app che hanno come target i livelli API 23 o precedenti, le classi che hanno un campo serialVersionUID o le classi con un metodo di inizializzazione statico.

Altri aspetti 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.

    Dovresti testare l'app per assicurarti che questo comportamento non si verifichi. Puoi farlo causando un arresto anomalo identico quando termini l'app manualmente tramite DCM.

    Le app che hanno come target Android 7.0 (livello API 24) e versioni successive non vengono terminate automaticamente in caso di 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 agli 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 segnalava la scrittura in un socket TCP nel thread principale come violazione in modalità rigida. 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é queste operazioni di solito hanno un'elevata latenza che causa errori ANR e jank.
  • La famiglia di metodi Debug.startMethodTracing() ora imposta l'archiviazione dell'output nella directory specifica del pacchetto nello spazio di archiviazione condiviso, anziché nel livello superiore della scheda SD. Ciò significa che le app non devono 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, anziché registrarli o sopprimerli in modalità silenziosa. Un esempio comune è l'archiviazione di troppi dati in Activity.onSaveInstanceState(), il che fa sì che ActivityThread.StopInfo restituisca un 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 accoda l'attività Runnable con l'elemento View; l'attività Runnable non viene eseguita finché la View non viene collegata a una finestra. Questo comportamento corregge i seguenti bug:
    • Se un'app ha pubblicato un'app in un View da un thread diverso dal thread di interfaccia utente della finestra prevista, l'elemento Runnable potrebbe essere eseguito sul thread sbagliato.
    • Se l'attività Runnable viene pubblicata da un thread diverso da un thread del looper, l'app potrebbe esporre l'attività Runnable.
  • Se un'app su Android 7.0 con autorizzazione DELETE_PACKAGES tenta di eliminare un pacchetto, ma il pacchetto è stato installato da un'altra app, il sistema richiede la conferma dell'utente. In questo scenario, le app devono aspettarsi STATUS_PENDING_USER_ACTION come stato di ritorno 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 ricavare le chiavi (in modo non sicuro), perché questo provider non è più disponibile. Per maggiori informazioni, consulta il post del blog Provider "Crypto" di sicurezza deprecato in Android N.