Modifiche al comportamento di Android 8.0

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

La maggior parte di queste modifiche riguarda tutte le app, indipendentemente dalla versione di Android che scelgono come target. Tuttavia, diverse modifiche interessano solo le app destinate ad Android 8.0. Per massimizzarne la chiarezza, questa pagina è divisa in due sezioni: Modifiche per tutte le app e Modifiche per le app destinate ad Android 8.0.

Modifiche per tutte le app

Queste modifiche del comportamento si applicano a tutte le app quando vengono eseguite sulla piattaforma Android 8.0 (livello API 26), indipendentemente dal livello API target. Tutti gli sviluppatori sono tenuti a esaminare queste modifiche e modificare le proprie app per supportarle correttamente, ove applicabile all'app.

Limiti di esecuzione in background

Come una delle modifiche introdotte da Android 8.0 (livello API 26) per migliorare la durata della batteria, quando la tua app entra nello stato memorizzato nella cache senza componenti attivi, il sistema rilascia eventuali wakelock bloccati dall'app.

Inoltre, per migliorare le prestazioni dei dispositivi, il sistema limita determinati comportamenti delle app che non sono in esecuzione in primo piano. Nello specifico:

  • Per le app in esecuzione in background sono ora previsti limiti relativi alla libertà di accesso ai servizi in background.
  • Le app non possono utilizzare i propri manifest per registrarsi per la maggior parte delle trasmissioni implicite (ovvero le trasmissioni che non sono indirizzate specificatamente all'app).

Per impostazione predefinita, queste limitazioni si applicano solo alle app destinate alla versione O. Tuttavia, gli utenti possono attivare queste limitazioni per qualsiasi app dalla schermata Impostazioni, anche se l'app non ha scelto come target O.

Android 8.0 (livello API 26) include anche le seguenti modifiche relative a metodi specifici:

  • Il metodo startService() ora genera IllegalStateException se un'app che ha come target Android 8.0 tenta di usarlo in una situazione in cui non è consentito creare servizi in background.
  • Il nuovo metodo Context.startForegroundService() avvia un servizio in primo piano. Il sistema consente alle app di chiamare Context.startForegroundService() anche quando l'app è in background. Tuttavia, l'app deve chiamare il metodo startForeground() del servizio entro cinque secondi dalla creazione del servizio.

Per maggiori informazioni, consulta Limiti di esecuzione in background.

Limiti di geolocalizzazione in background su Android

Per preservare la batteria, l'esperienza utente e l'integrità del sistema, le app in background ricevono aggiornamenti della posizione meno frequentemente se utilizzate su un dispositivo con Android 8.0. Questa modifica del comportamento interessa tutte le app che ricevono aggiornamenti sulla posizione, incluso Google Play Services.

Queste modifiche interessano le seguenti API:

  • Fused Località Provider (FLP)
  • Geofencing
  • Misurazioni GNSS
  • Gestore località
  • Gestione Wi-Fi

Per assicurarti che l'app venga eseguita come previsto, completa i seguenti passaggi:

  • Esamina la logica della tua app e assicurati di utilizzare le API di località più recenti.
  • Verifica che la tua app mostri il comportamento che ti aspetti per ogni caso d'uso.
  • Valuta la possibilità di utilizzare il Fused Location Provider (FLP) o il geofencing per gestire i casi d'uso che dipendono dalla località attuale dell'utente.

Per ulteriori informazioni su queste modifiche, consulta Limiti per le località in background.

Scorciatoie applicazioni

Android 8.0 (livello API 26) include le seguenti modifiche alle scorciatoie app:

  • La trasmissione com.android.launcher.action.INSTALL_SHORTCUT non ha più alcun effetto sulla tua app perché ora è una trasmissione implicita privata. Devi invece creare una scorciatoia dell'app utilizzando il metodo requestPinShortcut() della classe ShortcutManager.
  • Ora l'intent ACTION_CREATE_SHORTCUT può creare scorciatoie app che puoi gestire utilizzando la classe ShortcutManager. Questo intent può anche creare scorciatoie Avvio app legacy che non interagiscono con ShortcutManager. In precedenza, questo intent poteva creare solo scorciatoie Avvio app precedenti.
  • Le scorciatoie create utilizzando requestPinShortcut() e quelle create in un'attività che gestisce l'intent ACTION_CREATE_SHORTCUT sono ora scorciatoie app complete. Di conseguenza, le app ora possono aggiornarle utilizzando i metodi in ShortcutManager.
  • Le scorciatoie precedenti mantengono la funzionalità delle versioni precedenti di Android, ma dovrai convertirle manualmente in scorciatoie app nella tua app.

Per ulteriori informazioni sulle modifiche alle scorciatoie app, consulta la guida alla funzionalità Blocco di scorciatoie e widget.

Impostazioni internazionali e internazionalizzazione

Android 7.0 (livello API 24) ha introdotto il concetto di poter specificare le impostazioni internazionali della categoria predefinite, ma alcune API hanno continuato a utilizzare il metodo Locale.getDefault() generico, senza argomenti, quando avrebbero dovuto invece usare le impostazioni internazionali predefinite della categoria DISPLAY. In Android 8.0 (livello API 26), i seguenti metodi ora utilizzano Locale.getDefault(Category.DISPLAY) anziché Locale.getDefault():

Locale.getDisplayScript(Locale) torna a Locale.getDefault() anche quando il valore displayScript specificato per l'argomento Locale non è disponibile.

Di seguito sono riportate ulteriori modifiche relative a impostazioni internazionali e internazionalizzazione:

  • La chiamata di Currency.getDisplayName(null) genera un NullPointerException, che corrisponde al comportamento documentato.
  • L'analisi del nome del fuso orario è stata modificata. In precedenza, i dispositivi Android utilizzavano il valore dell'orologio di sistema campionato al momento dell'avvio per memorizzare nella cache i nomi dei fusi orari utilizzati per l'analisi delle date e degli orari. Di conseguenza, se l'orologio di sistema era errato al momento dell'avvio o in altri casi più rari, l'analisi potrebbe risentirne.

    Ora, nei casi più comuni, la logica di analisi utilizza l'ICU e il valore attuale dell'orologio di sistema durante l'analisi dei nomi dei fusi orari. Questa modifica fornisce risultati più corretti, che potrebbero essere diversi dalle versioni precedenti di Android quando la tua app utilizza corsi come SimpleDateFormat.

  • Android 8.0 (livello API 26) aggiorna la versione delle ICU alla versione 58.

Finestre di avviso

Se un'app utilizza l'autorizzazione SYSTEM_ALERT_WINDOW e usa uno dei seguenti tipi di finestre per tentare di visualizzare le finestre di avviso sopra altre app e finestre di sistema:

...queste finestre vengono sempre visualizzate sotto le finestre che utilizzano il tipo di finestra TYPE_APPLICATION_OVERLAY. Se un'app ha come target Android 8.0 (livello API 26), utilizza il TYPE_APPLICATION_OVERLAY tipo di finestra per visualizzare le finestre di avviso.

Per ulteriori informazioni, consulta la sezione Tipi di finestre comuni per le finestre di avviso all'interno delle modifiche del comportamento per le app che hanno come target Android 8.0.

Input e navigazione

Con l'avvento delle app per Android su ChromeOS e altri fattori di forma di grandi dimensioni, come i tablet, stiamo assistendo a una ripresa dell'utilizzo della navigazione da tastiera all'interno delle app per Android. In Android 8.0 (livello API 26), abbiamo risolto i problemi utilizzando la tastiera come dispositivo di input di navigazione, ottenendo un modello più affidabile e prevedibile per la navigazione basata su frecce e schede.

In particolare, abbiamo apportato le seguenti modifiche al comportamento di messa a fuoco degli elementi:

  • Se non hai definito alcun colore dello stato di messa a fuoco per un oggetto View (disegnabile in primo piano o sullo sfondo), il framework ora imposta un colore di evidenziazione predefinito per l'elemento View. Questa evidenziazione di messa a fuoco è un'evidenza disegnata a onde basata sul tema dell'attività.

    Se non vuoi che un oggetto View utilizzi questa evidenziazione predefinita quando riceve lo stato attivo, imposta l'attributo android:defaultFocusHighlightEnabled su false nel file XML di layout contenente View oppure passa false a setDefaultFocusHighlightEnabled() nella logica dell'interfaccia utente della tua app.

  • Per verificare in che modo l'input della tastiera influisce sullo stato attivo degli elementi UI, puoi attivare l'opzione sviluppatore Disegno > Mostra limiti del layout. In Android 8.0, questa opzione mostra un'icona "X" sopra l'elemento attualmente attivo.

Inoltre, tutti gli elementi della barra degli strumenti in Android 8.0 sono automaticamente cluster di navigazione da tastiera, consentendo agli utenti di navigare più facilmente all'interno e all'esterno di ogni barra degli strumenti.

Per scoprire di più su come migliorare il supporto della navigazione da tastiera all'interno dell'app, leggi la guida Supporto della navigazione da tastiera.

Compilazione automatica dei moduli web

Ora che il framework di compilazione automatica di Android fornisce supporto integrato per la funzionalità di compilazione automatica, i seguenti metodi relativi agli oggetti WebView sono cambiati per le app installate su dispositivi con Android 8.0 (livello API 26):

WebSettings
WebViewDatabase
  • La chiamata a clearFormData() non ha più alcun effetto.
  • Il metodo hasFormData() ora restituisce false. In precedenza, questo metodo restituisceva true quando il modulo conteneva dati.

Accessibilità

Android 8.0 (livello API 26) include le seguenti modifiche all'accessibilità:

  • Il framework di accessibilità ora converte tutti i gesti di doppio tocco in azioni ACTION_CLICK. Questa modifica consente a TalkBack di comportarsi in modo più simile ad altri servizi di accessibilità.

    Se gli oggetti View dell'app utilizzano la gestione al tocco personalizzata, devi verificare che funzionino ancora con TalkBack. Potrebbe essere sufficiente registrare il gestore dei clic utilizzato dagli oggetti View. Se TalkBack continua a non riconoscere i gesti eseguiti su questi View oggetti, esegui l'override di performAccessibilityAction().

  • I servizi di accessibilità sono ora consapevoli di tutte le istanze ClickableSpan all'interno degli oggetti TextView della tua app.

Per scoprire di più su come rendere più accessibile la tua app, consulta la sezione Accessibilità.

Rete e connettività HTTP(S)

Android 8.0 (livello API 26) include le seguenti modifiche al comportamento della connettività di rete e HTTP(S):

  • Le richieste OPTIONS senza corpo hanno un'intestazione Content-Length: 0. In precedenza non avevano alcuna intestazione Content-Length.
  • HttpURLConnection normalizza gli URL contenenti percorsi vuoti aggiungendo una barra dopo il nome dell'host o dell'autorità. Ad esempio, converte http://example.com in http://example.com/.
  • Un selettore proxy personalizzato impostato tramite ProxySelector.setDefault() ha come target solo l'indirizzo (schema, host e porta) di un URL richiesto. Di conseguenza, la selezione del proxy potrebbe basarsi solo su questi valori. Un URL trasmesso a un selettore proxy personalizzato non include il percorso, i parametri di ricerca o i frammenti dell'URL richiesto.
  • Gli URI non possono contenere etichette vuote.

    In precedenza, la piattaforma supportava una soluzione alternativa per accettare etichette vuote nei nomi host, il che costituisce un uso non valido degli URI. Questa soluzione alternativa era per la compatibilità con le versioni precedenti di libcore. Gli sviluppatori che utilizzano l'API in modo errato potrebbero visualizzare il messaggio ADB: "URI example.com ha etichette vuote nel nome host. Il formato non è corretto e non sarà accettato nelle future release di Android." Android 8.0 rimuove questa soluzione alternativa; il sistema restituisce un valore null per gli URI non corretti.

  • L'implementazione di HttpsURLConnection su Android 8.0 non esegue la versione di riserva del protocollo TLS/SSL non sicuro.
  • La gestione delle connessioni HTTP(S) di tunneling è cambiata come segue:
    • Durante l'esecuzione del tunneling della connessione HTTPS tramite la connessione, il sistema inserisce correttamente il numero di porta (:443) nella riga Host quando invia queste informazioni a un server intermedio. In precedenza, il numero di porta si trovava solo nella riga CONNECT.
    • Il sistema non invia più intestazioni user agent e autorizzazione proxy da una richiesta sottoposta a tunneling al server proxy.

      Il sistema non invia più un'intestazione di autorizzazione proxy su una connessione Http(s)URL con tunnel al proxy durante la configurazione del tunnel. Il sistema genera invece un'intestazione di autorizzazione proxy e la invia al proxy quando il proxy invia HTTP 407 in risposta alla richiesta iniziale.

      Allo stesso modo, il sistema non copia più l'intestazione user agent dalla richiesta con tunnel alla richiesta proxy che configura il tunnel. ma genera un'intestazione user-agent per la richiesta.

  • Il metodo send(java.net.DatagramPacket) genera una SocketException se il metodo connect() eseguito in precedenza ha avuto esito negativo.
    • DatagramSocket.connect() imposta una pendingSocketException in caso di errore interno. Prima di Android 8.0, una chiamata recv() successiva generava un'eccezione SocketException anche se l'operazione avrebbe avuto esito positivo con una chiamata send(). Per coerenza, entrambe le chiamate ora restituiscono un'eccezione Socket.
  • InetAddress.isReachable() tenta l'ICMP prima di utilizzare il protocollo TCP Echo.
    • Alcuni host che bloccano la porta 7 (TCP Echo), come google.com, ora potrebbero diventare raggiungibili se accettano il protocollo ICMP Echo.
    • Per gli host veramente non raggiungibili, questa modifica implica il doppio del tempo trascorso prima che venga restituita la chiamata.

Bluetooth

Android 8.0 (livello API 26) apporta le seguenti modifiche alla lunghezza dei dati recuperati dal metodo ScanRecord.getBytes():

  • Il metodo getBytes() non formula ipotesi sul numero di byte ricevuti. Di conseguenza, le app non devono fare affidamento sul numero minimo o massimo di byte restituiti. Devono invece valutare la lunghezza dell'array risultante.
  • I dispositivi compatibili con Bluetooth 5 potrebbero restituire una lunghezza dati superiore al limite massimo precedente di ~60 byte.
  • Se un dispositivo remoto non fornisce una risposta di scansione, potrebbero essere restituiti anche meno di 60 byte.

Connettività senza interruzioni

Android 8.0 (livello API 26) apporta una serie di miglioramenti alle impostazioni Wi-Fi per semplificare la scelta della rete Wi-Fi che offre la migliore esperienza utente. Le modifiche specifiche includono:

  • Miglioramenti di stabilità e affidabilità.
  • Un'interfaccia utente più leggibile.
  • Un unico menu Preferenze Wi-Fi consolidato.
  • Sui dispositivi compatibili, attivazione automatica del Wi-Fi quando si trova una rete salvata di alta qualità nelle vicinanze.

Sicurezza

Android 8.0 include le seguenti modifiche relative alla sicurezza:

  • La piattaforma non supporta più SSLv3.
  • Quando viene stabilita una connessione HTTPS a un server che implementa in modo errato la negoziazione della versione di protocollo TLS, HttpsURLConnection non tenta più di utilizzare soluzioni alternative per tornare alle versioni precedenti del protocollo TLS e riprovare.
  • Android 8.0 (livello API 26) applica un filtro Secure Computing (SECCOMP) a tutte le app. L'elenco delle chiamate di sistema consentite è limitato alle chiamate esposte tramite bionica. Sebbene siano disponibili molte altre chiamate di sistema per la compatibilità con le versioni precedenti, sconsigliamo di utilizzarle.
  • Gli oggetti WebView dell'app ora vengono eseguiti in modalità multiprocesso. Per maggiore sicurezza, i contenuti web vengono gestiti in un processo separato e isolato da quello dell'app contenitore.
  • Non puoi più presumere che gli APK risiedano in directory i cui nomi terminano con -1 o -2. Le app devono usare sourceDir per ottenere la directory e non fare affidamento direttamente sul formato della directory.
  • Per informazioni sui miglioramenti della sicurezza relativi all'utilizzo delle librerie native, consulta Librerie native.

Inoltre, Android 8.0 (livello API 26) introduce le seguenti modifiche relative all'installazione di app sconosciute da origini sconosciute:

Per ulteriori dettagli sull'installazione di app sconosciute, consulta la guida Autorizzazioni di installazione delle app sconosciute.

Per ulteriori linee guida su come rendere più sicura la tua app, consulta Sicurezza per gli sviluppatori Android.

Privacy

Android 8.0 (livello API 26) apporta alla piattaforma le seguenti modifiche relative alla privacy.

  • La piattaforma ora gestisce gli identificatori in modo diverso.
    • Per le app installate prima di una OTA a una versione di Android 8.0 (livello API 26) (livello API 26), il valore di ANDROID_ID rimane lo stesso, a meno che non venga disinstallata e poi reinstallata dopo l'aggiornamento OTA. Per mantenere i valori durante le disinstallazioni dopo l'aggiornamento OTA, gli sviluppatori possono associare i valori vecchi e nuovi utilizzando il backup chiave/valore.
    • Per le app installate su un dispositivo con Android 8.0, il valore di ANDROID_ID è ora limitato all'ambito per chiave di firma dell'app e per utente. Il valore di ANDROID_ID è univoco per ogni combinazione di chiave di firma dell'app, utente e dispositivo. Di conseguenza, le app con chiavi di firma diverse in esecuzione sullo stesso dispositivo non vedono più lo stesso ID Android (anche per lo stesso utente).
    • Il valore di ANDROID_ID non cambia alla disinstallazione o alla reinstallazione del pacchetto, a condizione che la chiave di firma sia la stessa (e che l'app non sia stata installata a una versione di Android 8.0 prima di una OTA).
    • Il valore di ANDROID_ID non cambia anche se un aggiornamento di sistema causa la modifica della chiave di firma del pacchetto.
    • Sui dispositivi spediti con Google Play Services e l'ID pubblicità, devi utilizzare l' ID pubblicità. Un semplice sistema standard per monetizzare le app. L'ID pubblicità è un ID univoco reimpostabile dall'utente per la pubblicità. Viene fornito da Google Play Services.

      Gli altri produttori di dispositivi dovrebbero continuare a fornire ANDROID_ID.

  • L'esecuzione di query sulla proprietà di sistema net.hostname produce un risultato nullo.

Registrazione delle eccezioni non rilevate

Se un'app installa un Thread.UncaughtExceptionHandler che non chiama il Thread.UncaughtExceptionHandler predefinito, il sistema non termina l'app quando si verifica un'eccezione non rilevata. A partire da Android 8.0 (livello API 26), il sistema registra lo stacktrace delle eccezioni in questa situazione; nelle versioni precedenti della piattaforma, il sistema non avrebbe registrato l'analisi dello stack delle eccezioni.

Consigliamo che le implementazioni personalizzate di Thread.UncaughtExceptionHandler richiamino sempre il gestore predefinito; le app che seguono questo consiglio non sono interessate dalla modifica in Android 8.0.

modifica della firma di findViewById()

Tutte le istanze del metodo findViewById() ora restituiscono <T extends View> T anziché View. Questa modifica ha le seguenti implicazioni:

  • Di conseguenza, il codice esistente ora potrebbe avere un tipo restituito ambiguo, ad esempio se sono presenti entrambi someMethod(View) e someMethod(TextView) che ricevono il risultato di una chiamata a findViewById().
  • Quando utilizzi il linguaggio di origine Java 8, è necessario eseguire una trasmissione esplicita in View quando il tipo restituito non è vincolato (ad esempio, assertNotNull(findViewById(...)).someViewMethod()).
  • Il tipo restituito per gli override dei metodi findViewById() non finali (ad esempio Activity.findViewById()) dovrà essere aggiornato.

Modifica delle statistiche di utilizzo del provider di contatti

Nelle versioni precedenti di Android, il componente Provider di contatti consente agli sviluppatori di recuperare dati sull'utilizzo per ciascun contatto. Questi dati sull'utilizzo mostrano informazioni per ogni indirizzo email e ogni numero di telefono associato a un contatto, tra cui il numero di volte in cui il contatto è stato contattato e l'ultima volta che questo è stato contattato. Le app che richiedono l'autorizzazione READ_CONTACTS possono leggere questi dati.

Le app possono comunque leggere questi dati se richiedono l'autorizzazione READ_CONTACTS. In Android 8.0 (livello API 26) e versioni successive, le query per i dati sull'utilizzo restituiscono approssimazioni anziché valori esatti. Il sistema Android gestisce internamente i valori esatti, quindi questa modifica non influisce sull'API di completamento automatico.

Questa modifica del comportamento influisce sui seguenti parametri di query:

Gestione della raccolta

AbstractCollection.removeAll() e AbstractCollection.retainAll() ora generano sempre NullPointerException; in precedenza, NullPointerException non veniva generato quando la raccolta era vuota. Questa modifica rende il comportamento coerente con la documentazione.

Android Enterprise

Android 8.0 (livello API 26) modifica il comportamento di alcune API e funzionalità per le app aziendali, inclusi i controller dei criteri dei dispositivi (DPC). Le modifiche includono:

  • Nuovi comportamenti per aiutare le app a supportare i profili di lavoro sui dispositivi completamente gestiti.
  • Modifiche alla gestione degli aggiornamenti di sistema, alla verifica delle app e all'autenticazione per aumentare l'integrità del dispositivo e del sistema.
  • Miglioramenti all'esperienza utente per il provisioning, le notifiche, la schermata Recenti e la VPN sempre attiva.

Per visualizzare tutte le modifiche aziendali in Android 8.0 (livello API 26) e scoprire in che modo potrebbero influire sulla tua app, leggi l'articolo Android nella versione Enterprise.

App che hanno come target Android 8.0

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

Finestre di avviso

Le app che usano l'autorizzazione SYSTEM_ALERT_WINDOW non possono più utilizzare i seguenti tipi di finestre per mostrare finestre di avviso sopra altre app e finestre di sistema:

Le app devono invece utilizzare un nuovo tipo di finestra denominato TYPE_APPLICATION_OVERLAY.

Quando utilizzi il tipo di finestra TYPE_APPLICATION_OVERLAY per visualizzare le finestre di avviso per la tua app, tieni presente le seguenti caratteristiche del nuovo tipo di finestra:

  • Le finestre di avviso di un'app vengono sempre visualizzate sotto le finestre di sistema critiche, ad esempio la barra di stato e gli IME.
  • Il sistema può spostare o ridimensionare le finestre che utilizzano il tipo di finestra TYPE_APPLICATION_OVERLAY per migliorare la presentazione sullo schermo.
  • Aprendo l'area notifiche, gli utenti possono accedere a impostazioni che impediscono a un'app di visualizzare le finestre di avviso mostrate utilizzando il tipo di finestra TYPE_APPLICATION_OVERLAY.

Notifiche relative alle modifiche dei contenuti

Android 8.0 (livello API 26) cambia il comportamento di ContentResolver.notifyChange() e registerContentObserver(Uri, boolean, ContentObserver) per le app destinate ad Android 8.0.

Queste API ora richiedono la definizione di un ContentProvider valido per l'autorità in tutti gli URI. La definizione di un ContentProvider valido con autorizzazioni pertinenti contribuirà a difendere la tua app dalle modifiche ai contenuti di app dannose e ti impedirà di diffondere dati potenzialmente privati verso app dannose.

Visualizza stato attivo

Ora è possibile attivare per impostazione predefinita anche gli oggetti View cliccabili. Se vuoi che un oggetto View sia cliccabile ma non attivabile, imposta l'attributo android:focusable su false nel file XML di layout contenente View oppure trasmetti false a setFocusable() nella logica dell'interfaccia utente della tua app.

Corrispondenza user agent nel rilevamento del browser

Android 8.0 (livello API 26) e versioni successive includono la stringa dell'identificatore della build OPR. Alcune corrispondenze di pattern possono far sì che la logica di rilevamento del browser possa identificare in modo errato un browser non Opera come Opera. Un esempio di tale corrispondenza di schema potrebbe essere:

if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}

Per evitare problemi derivanti da tale errata identificazione, utilizza una stringa diversa da OPR come corrispondenza di schema per il browser Opera.

Sicurezza

Le modifiche seguenti influiscono sulla sicurezza in Android 8.0 (livello API 26):

  • Se la configurazione della sicurezza di rete della tua app disattiva il supporto del traffico in testo non crittografato, gli oggetti WebView dell'app non possono accedere ai siti web tramite HTTP. Ogni oggetto WebView deve utilizzare invece il protocollo HTTPS.
  • L'impostazione di sistema Consenti origini sconosciute è stata rimossa; al suo posto, l'autorizzazione Installa app sconosciute gestisce le installazioni di app sconosciute provenienti da fonti sconosciute. Per scoprire di più su questa nuova autorizzazione, consulta la guida Autorizzazioni di installazione di app sconosciute.

Per ulteriori linee guida su come rendere più sicura la tua app, consulta Sicurezza per gli sviluppatori Android.

Accesso all'account e rilevabilità

In Android 8.0 (livello API 26), le app non possono più accedere agli account utente, a meno che l'autenticatore non sia proprietario degli account o l'utente non conceda l'accesso. L'autorizzazione GET_ACCOUNTS non è più sufficiente. Per ottenere l'accesso a un account, le app devono usare AccountManager.newChooseAccountIntent() o un metodo specifico dell'autenticatore. Dopo aver ottenuto l'accesso agli account, un'app può chiamare AccountManager.getAccounts() per accedervi.

Android 8.0 viene ritirato LOGIN_ACCOUNTS_CHANGED_ACTION. Le app dovrebbero invece utilizzare addOnAccountsUpdatedListener() per ricevere aggiornamenti sugli account durante il runtime.

Per informazioni sulle nuove API e sui metodi aggiunti per l'accesso agli account e la rilevabilità, consulta Accesso e rilevabilità all'account nella sezione Nuove API di questo documento.

Privacy

Le modifiche che seguono influiscono sulla privacy in Android 8.0 (livello API 26).

  • Le proprietà di sistema net.dns1, net.dns2, net.dns3 e net.dns4 non sono più disponibili, una modifica che migliora la privacy sulla piattaforma.
  • Per ottenere informazioni di networking come i server DNS, le app con l'autorizzazione ACCESS_NETWORK_STATE possono registrare un oggetto NetworkRequest o NetworkCallback. Queste classi sono disponibili in Android 5.0 (livello API 21) e versioni successive.
  • La libreria Build.SERIAL è deprecata. Le app che devono conoscere il numero di serie hardware devono utilizzare invece il nuovo metodo Build.getSerial(), che richiede l'autorizzazione READ_PHONE_STATE.
  • L'API LauncherApps non consente più alle app del profilo di lavoro di ottenere informazioni sul profilo principale. Quando un utente utilizza un profilo di lavoro, l'API LauncherApps si comporta come se non fosse installata alcuna app in altri profili all'interno dello stesso gruppo di profili. Come in precedenza, i tentativi di accesso a profili non correlati causano le eccezioni SecurityExceptions.

Autorizzazioni

Prima di Android 8.0 (livello API 26), se un'app richiedeva un'autorizzazione in fase di runtime e l'autorizzazione è stata concessa, il sistema concedeva anche in modo errato all'app le restanti autorizzazioni che appartenevano allo stesso gruppo di autorizzazioni e che erano registrate nel manifest.

Per le app destinate ad Android 8.0, questo comportamento è stato corretto. All'app vengono concesse solo le autorizzazioni che ha richiesto esplicitamente. Tuttavia, una volta che l'utente concede un'autorizzazione all'app, tutte le richieste successive di autorizzazioni nel gruppo di autorizzazioni vengono concesse automaticamente.

Ad esempio, supponiamo che in un'app siano elencati sia READ_EXTERNAL_STORAGE sia WRITE_EXTERNAL_STORAGE nel file manifest. L'app richiede READ_EXTERNAL_STORAGE e l'utente la concede. Se l'app ha come target il livello API 25 o precedente, il sistema concede anche WRITE_EXTERNAL_STORAGE contemporaneamente, perché appartiene allo stesso gruppo di autorizzazioni STORAGE ed è anch'esso registrata nel manifest. Se l'app ha come target Android 8.0 (livello API 26), il sistema concede solo READ_EXTERNAL_STORAGE in quel momento; tuttavia, se in un secondo momento l'app richiede WRITE_EXTERNAL_STORAGE, il sistema concede immediatamente questo privilegio senza chiedere conferma all'utente.

Contenuti multimediali

  • Il framework è in grado di eseguire autonomamente l'attenuazione automatica dell'attenuazione automatica dell'audio. In questo caso, quando un'altra applicazione richiede lo stato attivo con AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, l'applicazione attiva riduce il volume, ma di solito non riceve un callback onAudioFocusChange() e non perde lo stato attivo sull'audio. Sono disponibili nuove API per eseguire l'override di questo comportamento per le applicazioni che devono essere messe in pausa anziché essere eseguite in modalità Attenuazione automatica.
  • Quando l'utente accetta una chiamata, gli stream multimediali attivi vengono disattivati per tutta la durata della chiamata.
  • Tutte le API relative all'audio dovrebbero usare AudioAttributes anziché i tipi di stream audio per descrivere il caso d'uso della riproduzione audio. Continua a utilizzare i tipi di stream audio solo per i controlli del volume. Altri utilizzi dei tipi di flussi funzionano ancora (ad esempio, l'argomento streamType per il costruttore AudioTrack deprecato), ma il sistema registra questo errore come errore.
  • Quando si utilizza un AudioTrack, se l'applicazione richiede un buffer audio sufficientemente grande, il framework proverà a utilizzare l'output del deep buffer, se disponibile.
  • In Android 8.0 (livello API 26) la gestione degli eventi del pulsante multimediale è diversa:
    1. La gestione dei pulsanti multimediali in un'attività della UI non è cambiata: le attività in primo piano hanno ancora la priorità nella gestione degli eventi dei pulsanti multimediali.
    2. Se l'attività in primo piano non gestisce l'evento del pulsante multimediale, il sistema lo indirizza all'app che ha riprodotto l'audio più di recente localmente. Lo stato attivo, i flag e lo stato di riproduzione di una sessione multimediale non vengono presi in considerazione per determinare quale app riceve gli eventi del pulsante multimediale.
    3. Se la sessione multimediale dell'app è stata rilasciata, il sistema invia l'evento del pulsante multimediale all'elemento MediaButtonReceiver dell'app, se presente.
    4. Per tutti gli altri casi, il sistema ignora l'evento del pulsante multimediale.

Librerie native

Nelle app che hanno come target Android 8.0 (livello API 26), le librerie native non vengono caricate più a lungo se contengono segmenti di caricamento sia scrivibili che eseguibili. A causa di questa modifica, alcune app potrebbero smettere di funzionare se hanno librerie native con segmenti di carico errati. Questa è una misura di rafforzamento della sicurezza.

Per ulteriori informazioni, consulta Segmenti eseguibili ed eseguibili.

Le modifiche apportate ai linker sono legate al livello API target di un'app. Se viene apportata una modifica al linker al livello API target, l'app non può caricare la libreria. Se scegli come target un livello API inferiore a quello in cui si verifica la modifica del linker, logcat mostra un avviso.

Gestione della raccolta

In Android 8.0 (livello API 26), Collections.sort() viene implementato nella parte superiore di List.sort(). Il contrario era vero in Android 7.x (livelli API 24 e 25): l'implementazione predefinita di List.sort() è stata denominata Collections.sort().

Questa modifica consente a Collections.sort() di sfruttare le implementazioni ottimizzate di List.sort(), ma prevede i seguenti vincoli:

  • Le implementazioni di List.sort() non devono chiamare Collections.sort(), perché ciò causerebbe un overflow dello stack a causa della ricorsione infinita. Se vuoi invece utilizzare il comportamento predefinito nell'implementazione di List, evita di eseguire l'override di sort().

    Se una classe principale implementa sort() in modo inappropriato, in genere è possibile sostituire List.sort() con un'implementazione basata su List.toArray(), Arrays.sort() e ListIterator.set(). Ecco alcuni esempi:

    @Override
    public void sort(Comparator<? super E> c) {
      Object[] elements = toArray();
      Arrays.sort(elements, c);
      ListIterator<E> iterator = (ListIterator<Object>) listIterator();
      for (Object element : elements) {
        iterator.next();
        iterator.set((E) element);
      }
    }
    

    Nella maggior parte dei casi, puoi anche eseguire l'override di List.sort() con un'implementazione che delega a implementazioni predefinite diverse a seconda del livello API. Ecco alcuni esempi:

    @Override
    public void sort(Comparator<? super E> comparator) {
      if (Build.VERSION.SDK_INT <= 25) {
        Collections.sort(this);
      } else {
        super.sort(comparator);
      }
    }
    

    Se scegli quest'ultima opzione solo perché vuoi che un metodo sort() sia disponibile a tutti i livelli dell'API, valuta la possibilità di assegnargli un nome univoco, ad esempio sortCompat(), anziché eseguire l'override di sort().

  • Collections.sort() ora viene conteggiato come una modifica strutturale nelle implementazioni dell'elenco che chiamano sort(). Ad esempio, nelle versioni della piattaforma precedenti ad Android 8.0 (livello API 26), l'iterazione di un ArrayList e la chiamata di sort() durante l'iterazione generava un ConcurrentModificationException se l'ordinamento fosse stato effettuato chiamando List.sort(). Collections.sort() non ha generato un'eccezione.

    Questa modifica rende il comportamento della piattaforma più coerente: entrambi gli approcci ora generano un ConcurrentModificationException.

Comportamento di caricamento delle classi

Android 8.0 (livello API 26) controlla che i caricatori di classi non violino le ipotesi del runtime durante il caricamento di nuove classi. Questi controlli vengono eseguiti indipendentemente dal fatto che si faccia riferimento alla classe in Java (da forName()), dal bytecode Dalvik o JNI. La piattaforma non intercetta le chiamate dirette da Java al metodo loadClass() né controlla i risultati di queste chiamate. Questo comportamento non dovrebbe influire sul funzionamento dei caricatori delle classi.

La piattaforma verifica che il descrittore della classe restituita dal caricatore di classi corrisponda a quello previsto. Se il descrittore restituito non corrisponde, la piattaforma genera un errore NoClassDefFoundError e memorizza nell'eccezione un messaggio dettagliato che segnala la discrepanza.

La piattaforma verifica inoltre che i descrittori delle classi richieste siano validi. Questo controllo rileva le chiamate JNI che caricano indirettamente classi come GetFieldID(), passando descrittori non validi a quelle classi. Ad esempio, un campo con la firma java/lang/String non è stato trovato perché la firma non è valida. Deve essere Ljava/lang/String;.

È diversa da una chiamata JNI a FindClass() in cui java/lang/String è un nome completo valido.

Android 8.0 (livello API 26) non supporta la presenza di più caricatori di classi che tentano di definire le classi utilizzando lo stesso oggetto DexFile. Un tentativo in tal senso fa sì che il runtime Android restituisca un errore InternalError con il messaggio "Tentativo di registrare il file dex <filename> con più caricatori di classi".

L'API DexFile è ora deprecata e ti consigliamo vivamente di utilizzare uno dei classloader della piattaforma, tra cui PathClassLoader o BaseDexClassLoader.

Nota: puoi creare più caricatori di classi che fanno riferimento allo stesso APK o contenitore di file JAR dal file system. Questa operazione di solito non comporta un sovraccarico di memoria: se vengono archiviati file DEX nel container anziché compressi, la piattaforma può eseguire un'operazione mmap anziché estrarli direttamente. Tuttavia, se la piattaforma deve estrarre il file DEX dal container, il riferimento a un file DEX in questo modo potrebbe consumare molta memoria.

In Android, tutti i caricatori di classi sono considerati compatibili con la modalità parallela. Quando più thread competono per caricare la stessa classe con lo stesso caricatore di classi, viene vinto il primo thread a completare l'operazione e il risultato viene utilizzato per gli altri thread. Questo comportamento si verifica indipendentemente dal fatto che il caricatore di classi abbia restituito la stessa classe, restituito una classe diversa o generato un'eccezione. La piattaforma ignora automaticamente queste eccezioni.

Attenzione: nelle versioni della piattaforma precedenti ad Android 8.0 (livello API 26), violare questi presupposti può portare alla definizione più volte della stessa classe, danneggiamento dell'heap dovuto alla confusione delle classi e altri effetti indesiderati.