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
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 generaIllegalStateException
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 chiamareContext.startForegroundService()
anche mentre l'app è in background. Tuttavia, l'app deve chiamare il metodostartForeground()
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 metodorequestPinShortcut()
della classeShortcutManager
. - Ora l'intent
ACTION_CREATE_SHORTCUT
può creare scorciatoie app che gestisci utilizzando la classeShortcutManager
. Questo intent può anche creare scorciatoie in Avvio applicazioni legacy che non interagiscono conShortcutManager
. 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'intentACTION_CREATE_SHORTCUT
ora sono scorciatoie app a tutti gli effetti. Di conseguenza, le app ora possono aggiornarle utilizzando i metodi inShortcutManager
. - 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 unNullPointerException
, 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'elementoView
. 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'attributoandroid:defaultFocusHighlightEnabled
sufalse
nel file XML di layout contenenteView
oppure passalo infalse
asetDefaultFocusHighlightEnabled()
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
-
- Il metodo
getSaveFormData()
ora restituiscefalse
. In precedenza, questo metodo restituiva invecetrue
. - La chiamata a
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 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 oggettiView
. Se TalkBack continua a non riconoscere i gesti compiuti su questiView
oggetti, sostituisciperformAccessibilityAction()
. - I servizi di accessibilità sono ora a conoscenza di tutte le istanze
ClickableSpan
all'interno degli oggettiTextView
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 intestazioneContent-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
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 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:
- Ora il valore dell'impostazione legacy
INSTALL_NON_MARKET_APPS
è sempre 1. Per determinare se un'origine sconosciuta può installare app utilizzando il programma di installazione dei pacchetti, devi utilizzare il valore restituitocanRequestPackageInstalls()
. - 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 invece applicare la limitazione utenteDISALLOW_INSTALL_UNKNOWN_SOURCES
. -
Per i profili gestiti creati sui 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 di cui è stato eseguito l'upgrade ad Android 8.0, la limitazione utente diDISALLOW_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 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 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 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
.
-
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
- 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)
esomeMethod(TextView)
che ricevono il risultato di una chiamata afindViewById()
. - 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 oggettoWebView
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
enet.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 oggettoNetworkRequest
oNetworkCallback
. 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'autorizzazioneREAD_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'APILauncherApps
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 callbackonAudioFocusChange()
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'argomentostreamType
nel costruttoreAudioTrack
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:
- 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.
- 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.
- Se la sessione multimediale dell'app è stata rilasciata, il sistema invia l'evento del pulsante multimediale al
MediaButtonReceiver
dell'app, se presente. - 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 chiamareCollections.sort()
, perché ciò causerebbe un overflow dello stack a causa della ricorsione infinita. Se vuoi, invece, il comportamento predefinito nell'implementazioneList
, evita di eseguire l'override disort()
.Se una classe principale implementa
sort()
in modo inappropriato, di solito può sostituireList.sort()
con un'implementazione basata suList.toArray()
,Arrays.sort()
eListIterator.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 esempiosortCompat()
, 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 di unArrayList
e la chiamata disort()
su quest'ultima durante l'iterazione avrebbe generatoConcurrentModificationException
se l'ordinamento fosse stato effettuato chiamandoList.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.