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
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 unIllegalStateException
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 chiamareContext.startForegroundService()
anche quando l'app è in background. Tuttavia, l'app deve chiamare il metodostartForeground()
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 metodorequestPinShortcut()
della classeShortcutManager
. - Ora l'intent
ACTION_CREATE_SHORTCUT
può creare scorciatoie app che gestisci utilizzando la classeShortcutManager
. Questo intento può anche creare scorciatoie del programma di avvio precedenti che non interagiscono conShortcutManager
. 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'intentACTION_CREATE_SHORTCUT
ora sono scorciatoie per app a tutti gli effetti. Di conseguenza, ora le app possono aggiornarli utilizzando i metodi inShortcutManager
. - 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 unNullPointerException
, 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 perView
.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'attributoandroid:defaultFocusHighlightEnabled
sufalse
nel file XML del layout contenente ilView
oppure passafalse
asetDefaultFocusHighlightEnabled()
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
-
- Il metodo
getSaveFormData()
ora restituiscefalse
. In precedenza, questo metodo restituivatrue
. - La chiamata
setSaveFormData()
non ha più alcun effetto.
- Il metodo
WebViewDatabase
-
- La chiamata a
clearFormData()
non ha più alcun effetto. - Il
metodo
hasFormData()
ora restituiscefalse
. In precedenza, questo metodo restituivatrue
quando il modulo conteneva dati.
- La chiamata a
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 oggettiView
. Se TalkBack continua a non riconoscere i gesti eseguiti su questiView
oggetti, sostituisciperformAccessibilityAction()
. - I servizi di accessibilità ora sono a conoscenza di tutte le istanze di
ClickableSpan
all'interno degli oggettiTextView
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'intestazioneContent-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
inhttp://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:
- Il valore dell'impostazione precedente
INSTALL_NON_MARKET_APPS
ora è sempre 1. Per determinare se un'origine sconosciuta può installare app utilizzando il file di installazione del pacchetto, devi utilizzare il valore restituito dicanRequestPackageInstalls()
. - Se provi a modificare il valore di
INSTALL_NON_MARKET_APPS
utilizzandosetSecureSetting()
, viene generato unUnsupportedOperationException
. Per impedire agli utenti di installare app sconosciute utilizzando origini sconosciute, devi applicare la limitazioneDISALLOW_INSTALL_UNKNOWN_SOURCES
per gli utenti. -
Per i profili gestiti creati su dispositivi con Android 8.0 (livello API 26) viene attivata automaticamente la limitazione utente
DISALLOW_INSTALL_UNKNOWN_SOURCES
. Per i profili gestiti esistenti sui dispositivi su cui è stato eseguito l'upgrade ad Android 8.0, la limitazione dell'utenteDISALLOW_INSTALL_UNKNOWN_SOURCES
viene attivata automaticamente, a meno che il proprietario del profilo non abbia disattivato esplicitamente questa limitazione (prima dell'upgrade) impostandoINSTALL_NON_MARKET_APPS
su 1.
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 diANDROID_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
.
-
Per le app installate prima di un aggiornamento OTA su una versione di Android 8.0 (livello API 26), il valore di
- 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)
siasomeMethod(TextView)
che porta il risultato di una chiamata afindViewById()
. - 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 esempioActivity.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. OgniWebView
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
enet.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 oggettoNetworkRequest
oNetworkCallback
. 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'autorizzazioneREAD_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'APILauncherApps
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 callbackonAudioFocusChange()
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'argomentostreamType
nel costruttoreAudioTrack
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:
- 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.
- 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.
- Se la sessione multimediale dell'app è stata rilasciata,
il sistema invia l'evento relativo al pulsante multimediale all'elemento
MediaButtonReceiver
dell'app, se presente. - 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 chiamareCollections.sort()
, perché così facendo comporterebbe un overflow dello stack dovuto a ricorsi infiniti. Se invece vuoi il comportamento predefinito nell'implementazione diList
, devi evitare di eseguire l'override disort()
.Se una classe principale implementa
sort()
in modo improprio, in genere è sufficiente sostituireList.sort()
con un'implementazione basata suList.toArray()
,Arrays.sort()
eListIterator.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, comesortCompat()
, anziché eseguire l'override disort()
.-
Collections.sort()
ora viene conteggiato come una modifica strutturale nelle implementazioni di elenchi che chiamanosort()
. Ad esempio, nelle versioni della piattaforma precedenti ad Android 8.0 (livello API 26), l'iterazione suArrayList
e la chiamata asort()
durante l'iterazione avrebbe generato unConcurrentModificationException
se l'ordinamento fosse stato eseguito chiamandoList.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.