Modifiche del 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 dovresti comprendere e tenere presenti nelle tue app.

La maggior parte di queste modifiche interessa tutte le app, indipendentemente dalla versione di Android scelta come target. Tuttavia, diverse modifiche interessano solo le app destinate ad Android 8.0. Per una maggiore 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.

Limiti di esecuzione in background

Come una delle modifiche introdotte da Android 8.0 (livello API 26) per migliorare la durata della batteria, quando l'app entra nello stato memorizzato nella cache senza componenti attivi, il sistema rilascia eventuali wakelock bloccati 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:

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

Per impostazione predefinita, queste limitazioni si applicano solo alle app destinate a 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:

  • Il metodo startService() ora genera IllegalStateException se un'app che ha come target Android 8.0 tenta di usare questo metodo 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 mentre l'app è in background. Tuttavia, l'app deve chiamare il metodo startForeground() di quel servizio entro cinque secondi dalla creazione del servizio.

Per maggiori 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 della posizione meno frequentemente quando vengono utilizzate su un dispositivo con Android 8.0. Questa modifica del comportamento interessa tutte le app che ricevono aggiornamenti della posizione, incluso Google Play Services.

Queste modifiche interessano le seguenti API:

  • Fused Location Provider (FLP)
  • Geofencing
  • Misurazioni GNSS
  • Gestione indirizzi
  • Gestione Wi-Fi

Per assicurarti che l'app venga eseguita come previsto, segui questi passaggi:

  • Esamina la logica della tua app e assicurati di utilizzare le API di geolocalizzazione più recenti.
  • Verifica che la tua app mostri il comportamento previsto per ogni caso d'uso.
  • Prendi in considerazione l'utilizzo del Fused Location Provider (FLP) o il geofencing per gestire i casi d'uso che dipendono dalla posizione attuale dell'utente.

Per ulteriori informazioni su queste modifiche, consulta Limiti di 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 privata implicita. Dovresti invece creare una scorciatoia dell'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 intent può anche creare scorciatoie in Avvio applicazioni legacy che non interagiscono con ShortcutManager. In precedenza, questo intent poteva creare solo scorciatoie Avvio app legacy.
  • Le scorciatoie create utilizzando requestPinShortcut() e quelle create in un'attività che gestisce l'intent ACTION_CREATE_SHORTCUT ora sono scorciatoie app a tutti gli effetti. Di conseguenza, le app ora possono aggiornarle utilizzando i metodi in ShortcutManager.
  • Le scorciatoie precedenti mantengono la funzionalità rispetto alle versioni precedenti di Android, ma devi convertirle manualmente in scorciatoie app nella tua app.

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

Impostazioni internazionali e internazionalizzazione

Android 7.0 (livello API 24) ha introdotto il concetto di poter specificare un'impostazione internazionale della categoria predefinita, ma alcune API hanno continuato a utilizzare il metodo Locale.getDefault() generico, senza argomenti, quando invece avrebbero dovuto utilizzare le impostazioni internazionali della categoria DISPLAY predefinite. 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 alle impostazioni internazionali e all'internazionalizzazione:

  • La chiamata di Currency.getDisplayName(null) genera un NullPointerException, corrispondente 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 analizzare le date e gli orari. Di conseguenza, l'analisi potrebbe risentirne negativamente se l'orologio di sistema era errato al momento dell'avvio o in altri casi più rari.

    Ora, nei casi comuni la logica di analisi utilizza l'ICU e l'attuale valore 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 dell'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 mostrare 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.

Immissione 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 rinascita 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, il che si è tradotto in un modello più affidabile e prevedibile per la navigazione basata su frecce e schede.

In particolare, abbiamo apportato le seguenti modifiche al comportamento di impostazione dello stato attivo degli elementi:

  • Se non hai definito alcun colore dello stato di messa a fuoco per un oggetto View (disegnato in primo piano o in background), il framework ora imposta un colore di evidenziazione predefinito per l'elemento View. Questo punto attivo è un disegno a onde basato 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 passalo in false a setDefaultFocusHighlightEnabled() nella logica dell'interfaccia utente della tua app.

  • Per verificare in che modo l'input da tastiera incide 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, il che rende più facile per gli utenti navigare 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 per Android offre il supporto integrato per la funzionalità di compilazione automatica, i seguenti metodi relativi agli oggetti WebView sono cambiati per le app installate sui 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 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. Potresti dover solo registrare il gestore di clic utilizzato dagli oggetti View. Se TalkBack continua a non riconoscere i gesti compiuti su questi View oggetti, sostituisci performAccessibilityAction().

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

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

Networking e connettività HTTP(S)

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

  • Le richieste OPTIONS senza corpo hanno un'intestazione Content-Length: 0. In precedenza non aveva 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 può essere basata solo su questi valori. Un URL passato 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, che costituisce un uso illegale degli URI. Questa soluzione alternativa riguardava la compatibilità con release libcore precedenti. Gli sviluppatori che usano l'API in modo errato potrebbero visualizzare il messaggio ADB: "URI example.com ha etichette vuote nel nome host. Questo formato non è valido 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 sicura.
  • La gestione delle connessioni HTTP(S) di tunneling è cambiata come segue:
    • Quando esegui 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 trovava solo nella riga CONNECT.
    • Il sistema non invia più intestazioni user agent e autorizzazione proxy da una richiesta con tunnel al server proxy.

      Il sistema non invia più un'intestazione di autorizzazione proxy su una Http(s)URLConnection con tunnel al proxy durante la configurazione del tunnel. Il sistema, invece, genera un'intestazione di autorizzazione proxy e la invia al proxy quando questo 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. 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 ha esito negativo.
    • DatagramSocket.connect() imposta una pendingSocketException in caso di errore interno. Prima di Android 8.0, una chiamata recv() successiva generava un'eccezione Socket anche se una chiamata send() sarebbe riuscita. Per coerenza, entrambe le chiamate ora generano un'eccezione Socket.
  • InetAddress.isReachable() tenta di utilizzare ICMP prima di ricorrere al protocollo TCP Echo.
    • Alcuni host che bloccano la porta 7 (TCP Echo), come google.com, ora possono diventare raggiungibili se accettano il protocollo ICMP Echo.
    • Per gli host davvero non raggiungibili, questa modifica significa che viene trascorso il doppio del tempo 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 fa ipotesi sul numero di byte ricevuti. Pertanto, 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 dei dati superiore al limite massimo precedente di circa 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 della stabilità e dell'affidabilità.
  • Un'interfaccia utente più leggibile.
  • Un unico menu consolidato di Preferenze Wi-Fi.
  • Sui dispositivi compatibili, attivazione automatica del Wi-Fi quando è disponibile 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 si stabilisce una connessione HTTPS a un server che implementa in modo errato la negoziazione della versione di protocollo TLS, HttpsURLConnection non tenta più di utilizzare la soluzione alternativa 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 di chiamate di sistema consentite è limitato alle chiamate bionica. Sebbene siano disponibili molte altre chiamate di sistema per la compatibilità con le versioni precedenti, ne sconsigliamo l'uso.
  • Gli oggetti WebView dell'app ora vengono eseguiti in modalità multiprocesso. I contenuti web vengono gestiti in un processo separato e isolato dal processo dell'app contenitore per una maggiore sicurezza.
  • Non puoi più presumere che gli APK risiedano in directory i cui nomi terminano con -1 o -2. Le app dovrebbero 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 fonti 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 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 un'aggiornamento 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 conservare 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 la chiave di firma dell'app, oltre che 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 vedranno più lo stesso ID Android (anche per lo stesso utente).
    • Il valore di ANDROID_ID non cambia al momento della disinstallazione o della reinstallazione del pacchetto, purché la chiave di firma sia la stessa (e l'app non è stata installata prima di un'aggiornamento OTA a 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 che vengono spediti con Google Play Services e con l'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à. 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 la Thread.UncaughtExceptionHandler predefinita, 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 l'analisi dello stack 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 Thread.UncaughtExceptionHandler personalizzate richiamino sempre il gestore predefinito. Le app che seguono questo consiglio non sono interessate dalla modifica in Android 8.0.

modifica della firma trovaViewById()

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

  • Ciò potrebbe far sì che il codice esistente ora abbia un tipo restituito ambiguo, ad esempio se sono presenti entrambi i valori someMethod(View) e someMethod(TextView) che ricevono il risultato di una chiamata a findViewById().
  • Quando utilizzi il linguaggio di origine Java 8, è necessaria una trasmissione esplicita a View quando il tipo restituito non è vincolato (ad esempio, assertNotNull(findViewById(...)).someViewMethod()).
  • Il tipo restituito deve essere aggiornato per gli override dei metodi findViewById() non finali (ad esempio, Activity.findViewById()).

Modifica delle statistiche sull'utilizzo del fornitore di contatti

Nelle versioni precedenti di Android, il componente Provider di contatti consente agli sviluppatori di ottenere dati sull'utilizzo per ogni contatto. Questi dati sull'utilizzo mostrano le 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 è 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 i valori esatti internamente, quindi questa modifica non influisce sull'API per il completamento automatico.

Questa modifica del comportamento interessa i 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 consentire alle app di 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 dell'esperienza utente relativa a provisioning, notifiche, schermata Recenti e VPN sempre attiva.

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

App destinate ad Android 8.0

Queste modifiche del comportamento si applicano esclusivamente alle app che hanno come target Android 8.0 (livello API 26) o versioni successive. Le app che vengono compilate in base ad Android 8.0 o impostano targetSdkVersion su Android 8.0 o versioni successive devono modificare le proprie 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ù usare i seguenti tipi di finestre per mostrare finestre di avviso sopra altre app e finestre di sistema:

Le app devono 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 a mente le seguenti caratteristiche del nuovo tipo di finestra:

  • Le finestre di avviso di un'app vengono sempre visualizzate sotto 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 dello 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 di modifica dei contenuti

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

Queste API ora richiedono la definizione di un ContentProvider valido per l'autorità in tutti gli URI. La definizione di un valore ContentProvider valido con autorizzazioni pertinenti ti aiuterà a difendere la tua app dalle modifiche ai contenuti di app dannose e a impedirti di far divulgare dati potenzialmente privati ad app dannose.

Visualizza obiettivo

Gli oggetti View cliccabili sono ora attivabili per impostazione predefinita. 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 passa in 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 di identificatore della build OPR. Alcune corrispondenze di pattern potrebbero far sì che la logica di rilevamento del browser possa identificare erroneamente 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 questo tipo di identificazione errata, utilizza una stringa diversa da OPR come corrispondenza di schema 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 dell'app disattiva il supporto del traffico di testo in chiaro, gli oggetti WebView dell'app non possono accedere ai siti web tramite HTTP. Ogni oggetto WebView deve utilizzare HTTPS.
  • L'impostazione di sistema Consenti origini sconosciute è stata rimossa; invece, l'autorizzazione Installa app sconosciute gestisce le installazioni di app sconosciute da origini sconosciute. Per saperne 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ù avere accesso agli account utente, a meno che l'autenticatore non possieda gli 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 verrà ritirato LOGIN_ACCOUNTS_CHANGED_ACTION. Le app dovrebbero usare invece addOnAccountsUpdatedListener() per ricevere aggiornamenti sugli account durante il runtime.

Per informazioni sulle nuove API e sui metodi aggiunti per l'accesso e la rilevabilità degli account, 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 sul networking come i server DNS, le app con l'autorizzazione ACCESS_NETWORK_STATE possono registrare un oggetto NetworkRequest o NetworkCallback. Queste classi sono disponibili su 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 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 si trova in un profilo di lavoro, l'API LauncherApps si comporta come se nessuna app fosse installata in altri profili all'interno dello stesso gruppo di profili. Come prima, i tentativi di accedere a profili non correlati causano la generazione di SecurityEccezioni.

Autorizzazioni

Prima di Android 8.0 (livello API 26), se un'app richiedeva un'autorizzazione in fase di runtime e l'autorizzazione veniva 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 successive richieste di autorizzazioni nel gruppo di autorizzazioni vengono concesse automaticamente.

Ad esempio, supponi che un'app elenca READ_EXTERNAL_STORAGE e 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 un livello precedente, il sistema concede anche WRITE_EXTERNAL_STORAGE allo stesso tempo, perché appartiene allo stesso gruppo di autorizzazioni STORAGE ed è anche registrato 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 seguito l'app richiede WRITE_EXTERNAL_STORAGE, il sistema concede immediatamente questo privilegio senza chiedere conferma all'utente.

Contenuti multimediali

  • Il framework può eseguire la attenuazione automatica dell'attenuazione automatica dell'audio in autonomia. In questo caso, quando un'altra applicazione richiede lo stato attivo su AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, l'applicazione attiva riduce il volume, ma di solito non riceve un callback onAudioFocusChange() e non perderà lo stato attivo dell'audio. Sono disponibili nuove API per eseguire l'override di questo comportamento per le applicazioni che devono essere messe in pausa anziché utilizzare la funzionalità Attenuazione automatica.
  • Quando l'utente risponde alla telefonata, gli stream multimediali attivi vengono disattivati per tutta 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 della 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 oggetto AudioTrack, se l'applicazione richiede un buffer audio sufficientemente grande, il framework proverà a utilizzare l'output del buffer profondo 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 più di recente l'audio 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 eventi relativi ai pulsanti multimediali.
    3. Se la sessione multimediale dell'app è stata rilasciata, il sistema invia l'evento del pulsante multimediale al MediaButtonReceiver dell'app, se presente.
    4. In 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ù se contengono segmenti di carico che possono essere scrivibili ed eseguibili. Alcune app potrebbero non funzionare più a causa di questa modifica se hanno librerie native con segmenti di carico errati. Questa è una misura che rafforza la sicurezza.

Per ulteriori informazioni, consulta Segmenti scrivibili ed eseguibili.

Le modifiche ai linker sono legate al livello API scelto come target da 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 al livello API in cui avviene la modifica del linker, logcat mostra un avviso.

Gestione della raccolta

In Android 8.0 (livello API 26), l'elemento Collections.sort() viene implementato sopra List.sort(). Il contrario era vero in Android 7.x (livelli API 24 e 25): l'implementazione predefinita di List.sort() chiamata Collections.sort().

Questa modifica consente a Collections.sort() di sfruttare le implementazioni ottimizzate di List.sort(), ma ha 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, il comportamento predefinito nell'implementazione List, evita di eseguire l'override di sort().

    Se una classe principale implementa sort() in modo inappropriato, di solito può 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 intendi utilizzare quest'ultima opzione solo per avere un metodo sort() disponibile a tutti i livelli 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 di elenchi 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() su quest'ultima durante l'iterazione avrebbe generato 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 valore ConcurrentModificationException.

Comportamento di caricamento delle classi

Android 8.0 (livello API 26) verifica che i caricatori di classi non violano 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()), 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 al descrittore previsto. Se il descrittore restituito non corrisponde, la piattaforma genera un errore NoClassDefFoundError e archivia nell'eccezione un messaggio dettagliato che indica 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 che più caricatori di classi provino a definire le classi utilizzando lo stesso oggetto DexFile. Se tenti di farlo, il runtime Android restituisce 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, incluso PathClassLoader o BaseDexClassLoader.

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

In Android, tutti i caricatori di classi sono considerati con supporto parallelo. Quando più thread corrono per caricare la stessa classe con lo stesso caricatore di classi, vince 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 queste eccezioni in silenzio.

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