Modifiche del comportamento di Android 8.0

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

La maggior parte di queste modifiche interessa tutte le app, indipendentemente dalla versione di Android di destinazione. Tuttavia, diverse modifiche interessano solo le app che hanno come target Android 8.0. Per una maggiore chiarezza, questa pagina è divisa in due sezioni: Modifiche per tutte le app e Modifiche per le app che hanno come target Android 8.0.

Modifiche per tutte le app

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

Limiti di esecuzione in background

Una delle modifiche introdotte da Android 8.0 (livello API 26) per migliorare la durata della batteria è che, quando l'app entra nello stato in cache, senza componenti attivi, il sistema rilascia tutti i wakelock detenuti dall'app.

Inoltre, per migliorare le prestazioni del dispositivo, il sistema limita alcuni comportamenti delle app che non sono in esecuzione in primo piano. Nello specifico:

  • Ora le app eseguite in background hanno dei limiti sulla libertà di accesso ai servizi in background.
  • Le app non possono utilizzare i propri manifest per registrarsi alla maggior parte delle trasmissioni implicite (ovvero le trasmissioni che non hanno come target specifico l'app).

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

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

  • Ora il metodo startService() genera un IllegalStateException se un'app che ha come target Android 8.0 tenta di utilizzarlo 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 ulteriori informazioni, consulta Limiti di esecuzione in background.

Limiti di geolocalizzazione in background di Android

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

Queste modifiche interessano le seguenti API:

  • Fused Location Provider (FLP)
  • Geofencing
  • Misurazioni GNSS
  • Gestore della posizione
  • Gestore Wi-Fi

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

  • Esamina la logica dell'app e assicurati di utilizzare le API di geolocalizzazione più recenti.
  • Verifica che la tua app presenti il comportamento previsto per ogni caso d'uso.
  • Valuta la possibilità di utilizzare il Fornitore di posizione combinato (FLP) o il geofencing per gestire i casi d'uso che dipendono dalla posizione attuale dell'utente.

Per ulteriori informazioni su queste modifiche, vedi Limiti per la posizione in background.

Scorciatoie app

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 privata implicita. Dovresti invece creare una scorciatoia per l'app utilizzando il metodo requestPinShortcut() della classe ShortcutManager.
  • Ora l'intent ACTION_CREATE_SHORTCUT può creare scorciatoie app che gestisci utilizzando la classe ShortcutManager. Questo intento può anche creare scorciatoie del programma di avvio precedenti che non interagiscono con ShortcutManager. In precedenza, questa intenzione poteva creare solo scorciatoie del programma di avvio precedente.
  • Le scorciatoie create utilizzando requestPinShortcut() e quelle create in un'attività che gestisce l'intent ACTION_CREATE_SHORTCUT ora sono scorciatoie per app a tutti gli effetti. Di conseguenza, ora le app possono aggiornarli utilizzando i metodi in ShortcutManager.
  • Le scorciatoie precedenti conservano le funzionalità delle versioni precedenti di Android, ma devi convertirle in scorciatoie app manualmente nell'app.

Per scoprire di più sulle modifiche alle scorciatoie delle app, consulta la guida alle funzionalità sulla bloccatura di scorciatoie e widget.

Impostazioni internazionali e localizzazione

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

Anche Locale.getDisplayScript(Locale) viene eseguito il fallback su Locale.getDefault() quando il valore displayScript specificato per l'argomento Locale non è disponibile.

Di seguito sono riportate ulteriori modifiche relative alle impostazioni internazionali e all'internazionalizzazione:

  • La chiamata a Currency.getDisplayName(null) genera un NullPointerException, corrispondente al comportamento documentato.
  • L'analisi del nome del fuso orario è cambiata. 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, l'analisi potrebbe essere influenzata negativamente se l'orologio di sistema non è corretto al momento dell'avvio o in altri casi più rari.

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

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

Finestre di avviso

Se un'app utilizza l'autorizzazione SYSTEM_ALERT_WINDOW e 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 quelle 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 nelle modifiche al comportamento per le app destinate ad Android 8.0.

Input e navigazione

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

In particolare, abbiamo apportato le seguenti modifiche al comportamento dell'elemento attivo:

  • Se non hai definito colori dello stato di messa a fuoco per un oggetto View (elemento visibile in primo piano o sfondo), ora il framework imposta un colore di evidenziazione della messa a fuoco predefinito per View.View L'elemento in evidenza è un elemento disegnabile a onde basato sul tema dell'attività.

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

  • Per verificare in che modo l'input da tastiera influisce sull'attenzione degli elementi dell'interfaccia utente, puoi attivare l'opzione di sviluppatore Disegno > Mostra limiti del layout. In Android 8.0, questa opzione mostra un'icona "X" sull'elemento attualmente attivo.

Inoltre, tutti gli elementi della barra degli strumenti in Android 8.0 sono automaticamente cluster di navigazione con tastiera, che consentono agli utenti di entrare e uscire più facilmente da una barra degli strumenti.

Per ulteriori informazioni su come migliorare il supporto della navigazione da tastiera all'interno dell'app, leggi la guida Supporto della navigazione con tastiera.

Compilazione automatica dei moduli web

Ora che il framework di compilazione automatica di Android offre supporto integrato per la funzionalità di compilazione automatica, i seguenti metodi relativi agli oggetti WebView sono stati modificati 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 restituiva 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 del doppio tocco in azioni ACTION_CLICK. Questa modifica consente a TalkBack di comportarsi più come gli altri servizi di accessibilità.

    Se gli oggetti View della tua app utilizzano il trattamento personalizzato dei tocchi, devi verificare che funzionino ancora con TalkBack. Potresti dover solo registrare il gestore dei clic utilizzato dagli oggetti View. Se TalkBack continua a non riconoscere i gesti eseguiti su questi View oggetti, sostituisci performAccessibilityAction().

  • I servizi di accessibilità ora sono a conoscenza di tutte le istanze di ClickableSpan all'interno degli oggetti TextView dell'app.

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

Connettività di rete e 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 era presente l'intestazione Content-Length.
  • HttpURLConnection normalizza gli URL contenenti percorsi vuoti aggiungendo una barra dopo il nome dell'autorità o dell'host. 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 essere basata solo su questi valori. Un URL passato a un selettore di proxy personalizzato non include il percorso, i parametri di query 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, un uso illegale degli URI. Questa soluzione alternativa era per la compatibilità con le versioni precedenti di libcore. Gli sviluppatori che utilizzano l'API in modo errato vedrebbero il messaggio ADB: "URI example.com ha etichette vuote nel nome host. Il file non è valido e non verrà accettato nelle future release di Android." Android 8.0 rimuove questa soluzione alternativa; il sistema restituisce un valore nullo in caso di URI non corretti.

  • L'implementazione di HttpsURLConnection di Android 8.0 non esegue il fallback alla versione non sicura del protocollo TLS/SSL.
  • La gestione delle connessioni HTTP(S) in tunnel è cambiata nel seguente modo:
    • Durante il 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 verificava solo nella riga CONNECT.
    • Il sistema non invia più le intestazioni user-agent e proxy-authorization da una richiesta in tunnel al server proxy.

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

      Analogamente, il sistema non copia più l'intestazione dello user agent dalla richiesta con tunnel alla richiesta proxy che configura il tunnel. La libreria genera invece un'intestazione user-agent per quella richiesta.

  • Il metodo send(java.net.DatagramPacket) genera un'eccezione SocketException se il metodo connect() eseguito in precedenza non è riuscito.
    • DatagramSocket.connect() imposta un pendingSocketException in caso di errore interno. Prima di Android 8.0, una successiva chiamata recv() generava una SocketException anche se una chiamata send() avrebbe avuto esito positivo. Per coerenza, per entrambe le chiamate viene generata una SocketEccezioni.
  • InetAddress.isReachable() tenta ICMP prima di passare al protocollo TCP Echo.
    • Alcuni host che bloccano la porta 7 (TCP Echo), come google.com, ora potrebbero essere raggiungibili se accettano il protocollo ICMP Echo.
    • Per gli host realmente non raggiungibili, questa modifica comporta un tempo di attesa doppio prima del ritorno della 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 fa supposizioni sul numero di byte ricevuti. Pertanto, le app non devono fare affidamento su alcun numero minimo o massimo di byte restituiti. Dovrebbe invece valutare la lunghezza dell'array risultante.
  • I dispositivi compatibili con Bluetooth 5 potrebbero restituire una lunghezza dei dati superiore al valore massimo precedente di circa 60 byte.
  • Se un dispositivo remoto non fornisce una risposta alla ricerca, possono essere restituiti anche meno di 60 byte.

Connettività perfetta

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 alla stabilità e all'affidabilità.
  • Un'interfaccia utente più leggibile e intuitiva.
  • Un unico menu consolidato delle preferenze Wi-Fi.
  • Sui dispositivi compatibili, attivazione automatica del Wi-Fi quando nelle vicinanze c'è una rete salvata di alta qualità.

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 erroneamente la negoziazione della versione del protocollo TLS, HttpsURLConnection non tenta più la soluzione alternativa di eseguire il fallback alle versioni precedenti del protocollo TLS e riprovare.
  • Android 8.0 (livello API 26) applica un filtro di calcolo sicuro (SECCOMP) a tutte le app. L'elenco delle chiamate di sistema consentite è limitato a quelle esposte tramite bionic. Anche se sono disponibili diverse altre chiamate di sistema per la compatibilità con le versioni precedenti, ne sconsigliamo l'utilizzo.
  • Gli oggetti WebView della tua app ora vengono eseguiti in modalità multiprocesso. I contenuti web vengono gestiti in un processo separato e isolato dal processo dell'app contenente per una maggiore sicurezza.
  • Non puoi più presumere che gli APK si trovino in directory i cui nomi terminano con -1 o -2. Le app devono utilizzare sourceDir per recuperare la directory e non fare affidamento direttamente sul formato della directory.
  • Per informazioni sui miglioramenti alla 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 di app sconosciute.

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

Privacy

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

  • Ora la piattaforma gestisce gli identificatori in modo diverso.
    • Per le app installate prima di un aggiornamento OTA su una versione di Android 8.0 (livello API 26), il valore di ANDROID_ID rimane invariato, a meno che non vengano disinstallate e reinstallate dopo l'OTA. Per preservare i valori durante le disinstallazioni dopo l'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 è definito 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 al momento della disinstallazione o reinstallazione del pacchetto, purché la chiave di firma sia la stessa (e l'app non sia stata installata prima di una OTA su una versione di Android 8.0).
    • Il valore di ANDROID_ID non cambia anche se un aggiornamento di sistema causa la modifica della chiave di firma del pacchetto.
    • Sui dispositivi forniti con Google Play Services e ID pubblicità, devi utilizzare l'ID pubblicità. L'ID pubblicità, un semplice sistema standard per monetizzare le app, è un ID univoco reimpostabile dall'utente per la pubblicità. È fornito da Google Play Services.

      Altri produttori di dispositivi dovrebbero continuare a fornire ANDROID_ID.

  • La 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 richiama il Thread.UncaughtExceptionHandler predefinito, il sistema non arresta l'app quando si verifica un'eccezione non rilevata. A partire da Android 8.0 (livello API 26), il sistema registra la traccia dello stack dell'eccezione in questa situazione. Nelle versioni precedenti della piattaforma, il sistema non avrebbe registrato la traccia dello stack dell'eccezione.

Consigliamo di fare in modo che le implementazioni personalizzate di Thread.UncaughtExceptionHandler vengano sempre richiamate al 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 potrebbe ora avere un tipo restituito ambiguo, ad esempio se sono presenti sia someMethod(View) sia someMethod(TextView) che porta il risultato di una chiamata a findViewById().
  • Quando si utilizza il linguaggio di origine Java 8, è necessario un trasferimento esplicito a View quando il tipo di ritorno non è vincolato (ad esempio, assertNotNull(findViewById(...)).someViewMethod()).
  • Le sostituzioni dei metodi findViewById() non finali (ad esempio Activity.findViewById()) richiedono l'aggiornamento del tipo di ritorno.

Modifica delle statistiche di utilizzo del fornitore di contatti

Nelle versioni precedenti di Android, il componente Provider di contatti consente agli sviluppatori di ottenere i dati di utilizzo per ogni contatto. Questi dati sull'utilizzo mostrano le informazioni per ogni indirizzo email e ogni numero di telefono associato a un contatto, inclusi il numero di volte in cui il contatto e l'ultima volta che è 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 mantiene i valori esatti internamente, quindi questa modifica non influisce sull'API di completamento automatico.

Questa modifica del comportamento interessa i seguenti parametri di query:

Gestione della raccolta

AbstractCollection.removeAll() e AbstractCollection.retainAll() ora generano sempre un NullPointerException; in precedenza, il valore 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 provisioning, notifiche, schermata Recenti e VPN sempre attiva.

Per vedere tutte le modifiche aziendali in Android 8.0 (livello API 26) e scoprire come potrebbero influire sulla tua app, leggi Android in azienda.

App che hanno come target Android 8.0

Queste modifiche al comportamento si applicano esclusivamente alle app che hanno come target Android 8.0 (livello API 26) o versioni successive. Le app compilate per Android 8.0 o che impostano targetSdkVersion su Android 8.0 o versioni successive devono modificare le proprie app per supportare correttamente questi comportamenti, se applicabili all'app.

Finestre di avviso

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

Le app devono invece utilizzare un nuovo tipo di finestra chiamato 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, come 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 alle impostazioni per impedire a un'app di visualizzare le finestre di avviso mostrate utilizzando il tipo di finestra TYPE_APPLICATION_OVERLAY.

Notifiche relative alle modifiche ai contenuti

Android 8.0 (livello API 26) cambia il comportamento di ContentResolver.notifyChange() e registerContentObserver(Uri, boolean, ContentObserver) per le app che hanno come target Android 8.0.

Ora queste API richiedono che per l'autorità in tutti gli URI sia definito un valore ContentProvider valido. La definizione di un ContentProvider valido con autorizzazioni pertinenti aiuterà a difendere la tua app dalle modifiche ai contenuti da parte di app dannose e a evitare la fuga di dati potenzialmente privati a app dannose.

Visualizza focus

Ora gli oggetti View cliccabili sono attivabili anche per impostazione predefinita. Se vuoi che un oggetto View sia cliccabile, ma non sia possibile impostarne il focus, imposta l'attributo android:focusable su false nel file XML del layout contenente View oppure passa false a setFocusable() nella logica dell'interfaccia utente dell'app.

Corrispondenza user agent nel rilevamento del browser

Android 8.0 (livello API 26) e versioni successive includono la stringa di identificazione della build OPR. Alcune corrispondenze di pattern possono causare un'errata identificazione di un browser non Opera come Opera da parte della logica di rilevamento del browser. Un esempio di questa corrispondenza di pattern 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 una siffatta identificazione errata, utilizza una stringa diversa daOPR come corrispondenza pattern per il browser Opera.

Sicurezza

Le seguenti modifiche 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 di testo non criptato, gli oggetti WebView della tua app non possono accedere ai siti web tramite HTTP. Ogni WebView oggetto deve utilizzare HTTPS.
  • L'impostazione di sistema Consenti origini sconosciute è stata rimossa. Al suo posto, l'autorizzazione Installa app sconosciute gestisce le installazioni di app sconosciute da origini sconosciute. Per scoprire di più su questa nuova autorizzazione, consulta la guida sulle 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 visibilità

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 utilizzare AccountManager.newChooseAccountIntent() o un metodo specifico per l'autenticatore. Dopo aver ottenuto l'accesso agli account, un'app può chiamare AccountManager.getAccounts() per accedervi.

Android 8.0 ritira 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 nuovi metodi aggiunti per l'accesso all'account e la rilevabilità, consulta Accesso all'account e rilevabilità nella sezione Nuove API di questo documento.

Privacy

Le seguenti modifiche riguardano la privacy in Android 8.0 (livello API 26).

  • Le proprietà di sistema net.dns1, net.dns2, net.dns3 e net.dns4 non sono più disponibile, una modifica che migliora la privacy sulla piattaforma.
  • Per ottenere informazioni di rete 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.
  • Il file Build.SERIAL è deprecato. Le app che devono conoscere il numero di serie dell'hardware devono invece utilizzare 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 è in un profilo di lavoro, l'API LauncherApps si comporta come se non fosse stata installata alcuna app in altri profili dello stesso gruppo di profili. Come in precedenza, i tentativi di accesso a profili non correlati causano SecurityEccezioni.

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 erroneamente all'app le altre autorizzazioni che appartenevano allo stesso gruppo di autorizzazioni e che sono state registrate nel file manifest.

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

Ad esempio, supponiamo che un'app elencasse sia READ_EXTERNAL_STORAGE sia WRITE_EXTERNAL_STORAGE nel file manifest. L'app richiede READ_EXTERNAL_STORAGE e l'utente lo concede. Se l'app ha come target il livello API 25 o versioni precedenti, il sistema concede anche WRITE_EXTERNAL_STORAGE contemporaneamente, perché appartiene allo stesso gruppo di autorizzazioni STORAGE ed è anche registrato nel file 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 può eseguire attenuazione automatica dell'audio autonomamente. In questo caso, quando un'altra applicazione richiede il controllo con AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, l'applicazione che ha il controllo riduce il volume, ma in genere non riceve un callback onAudioFocusChange() e non perde il controllo audio. Sono disponibili nuove API per eseguire l'override di questo comportamento per le applicazioni che devono essere messe in pausa anziché abbassate.
  • Quando l'utente risponde a una chiamata, gli stream multimediali attivi vengono disattivati per la durata della chiamata.
  • Tutte le API relative all'audio devono utilizzare AudioAttributes anziché i tipi di stream audio per descrivere il caso d'uso di riproduzione audio. Continua a utilizzare i tipi di stream audio solo per i controlli del volume. Altri utilizzi dei tipi di flusso continuano a funzionare (ad esempio, l'argomento streamType nel costruttore AudioTrack deprecato), ma il sistema registra questo errore come errore.
  • Quando utilizzi un AudioTrack, se l'applicazione richiede un buffer audio sufficientemente grande, il framework tenterà di utilizzare l'output del buffer avanzato, se disponibile.
  • In Android 8.0 (livello API 26) la gestione degli eventi relativi ai pulsanti multimediali è diversa:
    1. La gestione dei pulsanti multimediali in un'attività dell'interfaccia utente 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 instrada l'evento all'app che ha riprodotto l'audio più di recente in locale. Lo stato attivo, gli indicatori e lo stato di riproduzione di una sessione multimediale non vengono presi in considerazione per determinare quale app riceve gli eventi dei pulsanti multimediali.
    3. Se la sessione multimediale dell'app è stata rilasciata, il sistema invia l'evento relativo al pulsante multimediale all'elemento MediaButtonReceiver dell'app, se presente.
    4. In tutti gli altri casi, il sistema ignora l'evento del pulsante multimediale.

Librerie native

Nelle app destinate ad Android 8.0 (livello API 26), le librerie native non vengono più caricate se contengono un segmento di caricamento sia scrivibile sia eseguibile. Alcune app potrebbero non funzionare più a causa di questa modifica se hanno librerie native con segmenti di caricamento errati. Si tratta di una misura di rafforzamento della sicurezza.

Per ulteriori informazioni, consulta Segmenti scrivibili ed eseguibili.

Le modifiche del linker sono legate al livello API scelto come target di un'app. Se c'è una modifica del linker a livello di API di destinazione, 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), l'Collections.sort() è implementata su List.sort(). Il contrario era vero in Android 7.x (livelli API 24 e 25): l'implementazione predefinita di List.sort() era chiamata Collections.sort().

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

  • Le implementazioni di List.sort() non devono chiamare Collections.sort(), perché così facendo comporterebbe un overflow dello stack dovuto a ricorsi infiniti. Se invece vuoi il comportamento predefinito nell'implementazione di List, devi evitare di eseguire l'override di sort().

    Se una classe principale implementa sort() in modo improprio, in genere è sufficiente sostituire List.sort() con un'implementazione basata su List.toArray(), Arrays.sort() e ListIterator.set(). Ad esempio:

    @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 diverse implementazioni predefinite a seconda del livello API. Ad esempio:

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

    Se scegli la seconda opzione solo perché vuoi avere un metodo sort() disponibile su tutti i livelli dell'API, ti consigliamo di assegnargli un nome univoco, come sortCompat(), anziché eseguire l'override di sort().

  • Collections.sort() ora viene conteggiato come una modifica strutturale nelle implementazioni di elenchi che chiamano sort(). Ad esempio, nelle versioni della piattaforma precedenti ad Android 8.0 (livello API 26), l'iterazione su ArrayList e la chiamata a sort() durante l'iterazione avrebbe generato un ConcurrentModificationException se l'ordinamento fosse stato eseguito 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 della classe

Android 8.0 (livello API 26) verifica 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 alla classe sia fatto riferimento da Java (da forName()), dal bytecode di Dalvik o da JNI. La piattaforma non intercetta le chiamate dirette da Java al metodoloadClass() e non controlla i risultati di queste chiamate. Questo comportamento non dovrebbe influire sul funzionamento dei caricatori di classi di buon comportamento.

La piattaforma controlla che il descrittore della classe restituito dal caricatore di classi sia uguale al descrittore 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 controlla anche 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 queste classi. Ad esempio, un campo con firmajava/lang/String non viene trovato perché la firma non è valida; dovrebbe essere Ljava/lang/String;.

Questo è diverso da una chiamata JNI a FindClass() dove java/lang/String è un nome completo valido.

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

L'API DexFile è stata ritirata e ti consigliamo vivamente di utilizzare uno dei class loader della piattaforma, tra cui PathClassLoader o BaseDexClassLoader.

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

In Android, tutti i caricatori di classi sono considerati compatibili con il parallelismo. Quando più thread competono per caricare la stessa classe con lo stesso caricatore di classi, vince il primo thread che completa 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, una classe diversa o abbia generato un'eccezione. La piattaforma ignora automaticamente queste eccezioni.

Attenzione: nelle versioni della piattaforma inferiori ad Android 8.0 (livello API 26), la violazione di queste ipotesi può portare alla definizione della stessa classe più volte, alla corruzione dell'heap a causa della confusione tra classi e ad altri effetti indesiderati.