Per offrire agli utenti un maggiore controllo sui file e limitarne il disordine, Android 10 ha introdotto un nuovo paradigma di archiviazione per le app chiamato archiviazione mirata. L'archiviazione con ambito cambia il modo in cui le app archiviano i file e accedono ai file nella memoria esterna di un dispositivo. Per eseguire la migrazione dell'app in modo da supportare l'archiviazione con ambito, segui le best practice per i casi d'uso di archiviazione più comuni descritte in questa guida. I casi d'uso sono organizzati in due categorie: gestione di file multimediali e gestione di file non multimediali.
Per scoprire di più su come archiviare e accedere ai file su Android, consulta le guide di formazione sullo spazio di archiviazione.
Gestire i file multimediali
Questa sezione descrive alcuni dei casi d'uso comuni per la gestione di file multimediali (file video, immagine e audio) e spiega l'approccio generale che può essere utilizzato dalla tua app. La seguente tabella riassume ciascuno di questi casi d'uso e fornisce link a ciascuna sezione che contiene ulteriori dettagli.
Caso d'uso | Riepilogo |
---|---|
Mostrare tutti i file immagine o video | Usa lo stesso approccio per tutte le versioni di Android. |
Mostrare immagini o video da una determinata cartella | Usa lo stesso approccio per tutte le versioni di Android. |
Accedere alle informazioni sulla posizione dalle foto | Scegli un solo approccio se la tua app utilizza l'archiviazione mirata. Utilizza un approccio diverso se la tua app disattiva l'archiviazione mirata. |
Definire la posizione di archiviazione per i nuovi download | Scegli un solo approccio se la tua app utilizza l'archiviazione mirata. Utilizza un approccio diverso se la tua app disattiva l'archiviazione mirata. |
Esportare i file multimediali degli utenti su un dispositivo | Usa lo stesso approccio per tutte le versioni di Android. |
Modifica o elimina più file multimediali in una singola operazione | Usa un unico approccio per Android 11. Per Android 10, disattiva lo spazio di archiviazione con ambito e utilizza l'approccio per Android 9 e versioni precedenti. |
Importa una singola immagine già esistente | Usa lo stesso approccio per tutte le versioni di Android. |
Acquisire una singola immagine | Usa lo stesso approccio per tutte le versioni di Android. |
Condividere file multimediali con altre app | Usa lo stesso approccio per tutte le versioni di Android. |
Condividere file multimediali con un'app specifica | Usa lo stesso approccio per tutte le versioni di Android. |
Accedere ai file da codice o librerie che utilizzano percorsi di file diretti | Usa un unico approccio per Android 11. Per Android 10, disattiva lo spazio di archiviazione con ambito e utilizza l'approccio per Android 9 e versioni precedenti. |
Mostra i file immagine o video di più cartelle
Esegui una query su una raccolta multimediale
utilizzando l'API query()
. Per filtrare o ordinare i file multimediali, regola i parametri projection
, selection
, selectionArgs
e sortOrder
.
Mostra immagini o video da una determinata cartella
Usa questo approccio:
- Segui le best practice descritte in Richiedere le autorizzazioni app,
richiedi l'autorizzazione
READ_EXTERNAL_STORAGE
. - Recupera i file multimediali in base al valore di
MediaColumns.DATA
, che contiene il percorso del file system assoluto dell'elemento multimediale su disco.
Nota: quando accedi a un file multimediale esistente, puoi utilizzare il valore della colonna DATA
nella logica. Il motivo è che questo valore ha un percorso file valido.
Tuttavia, non dare per scontato che il file sia sempre disponibile. Preparati a gestire eventuali errori di I/O basati su file che potrebbero verificarsi.
Per creare o aggiornare un file multimediale, invece, non utilizzare la
colonna DATA
. Utilizza invece le colonne DISPLAY_NAME
e RELATIVE_PATH
.
Accedere alle informazioni sulla posizione dalle foto
Se la tua app utilizza l'archiviazione mirata, segui i passaggi nella sezione Informazioni sulla posizione nelle foto della guida allo spazio di archiviazione per contenuti multimediali.
Definisci la posizione di archiviazione per i nuovi download
Se l'app utilizza lo spazio di archiviazione limitato, presta attenzione alla posizione in cui scegli di archiviare i file multimediali scaricati.
Se altre app richiedono l'accesso ai file, valuta la possibilità di utilizzare raccolte multimediali ben definite per i download o le raccolte di documenti.
Su Android 11 e versioni successive, i file all'interno della directory esterna specifica dell'app non sono accessibili ad altre app, anche se usi DownloadManager
per recuperarli.
Esportare i file multimediali dell'utente su un dispositivo
Definisci una posizione predefinita appropriata in cui archiviare i file multimediali dell'utente:
- Consenti agli utenti di scegliere se rendere i loro file multimediali leggibili o meno da altre app, utilizzando lo spazio di archiviazione specifico dell'app o lo spazio di archiviazione condiviso.
- Consenti agli utenti di esportare file da directory specifiche dell'app a una posizione più accessibile in genere. Utilizza le raccolte di immagini, video e audio di MediaStore per esportare file multimediali nella galleria del dispositivo.
Modifica o eliminazione di più file multimediali in un'unica operazione
Incorpora la logica basata sulle versioni di Android su cui viene eseguita l'app.
In esecuzione su Android 11
Usa questo approccio:
- Crea un intent in attesa per la richiesta di scrittura o eliminazione della tua app utilizzando
MediaStore.createWriteRequest()
oMediaStore.createTrashRequest()
, quindi chiedi all'utente l'autorizzazione per modificare un insieme di file richiamando quell'intent. Valuta la risposta dell'utente:
- Se l'autorizzazione è stata concessa, procedi con l'operazione di modifica o eliminazione.
- Se l'autorizzazione non è stata concessa, spiega all'utente perché la funzionalità nell'app richiede l'autorizzazione.
Scopri di più su come gestire gruppi di file multimediali utilizzando questi metodi disponibili su Android 11 e versioni successive.
In esecuzione su Android 10
Se la tua app ha come target Android 10 (livello API 29), disattiva l'archiviazione con ambito e continua a utilizzare l'approccio per Android 9 e versioni precedenti per eseguire questa operazione.
Android 9 o versioni precedenti
Usa questo approccio:
- Segui le best practice descritte in Richiedere le autorizzazioni app,
richiedi l'autorizzazione
WRITE_EXTERNAL_STORAGE
. - Utilizza l'API
MediaStore
per modificare o eliminare i file multimediali.
Importa una singola immagine già esistente
Se vuoi importare una singola immagine già esistente (ad esempio, da utilizzare come foto per il profilo di un utente), l'app può utilizzare la propria UI per l'operazione oppure il selettore di sistema.
Presenta la tua interfaccia utente
Usa questo approccio:
- Segui le best practice descritte in Richiedere le autorizzazioni app,
richiedi l'autorizzazione
READ_EXTERNAL_STORAGE
. - Utilizza l'API
query()
per eseguire una query su una raccolta di contenuti multimediali. - Visualizza i risultati nell'interfaccia utente personalizzata della tua app.
Utilizzare il selettore di sistema
Utilizza l'intent ACTION_GET_CONTENT
, che chiede all'utente di scegliere un'immagine da importare.
Se vuoi filtrare i tipi di immagini che il selettore di sistema presenta all'utente tra cui scegliere, puoi utilizzare setType()
o EXTRA_MIME_TYPES
.
Acquisisci una singola immagine
Quando vuoi acquisire una singola immagine da utilizzare nella tua app (ad esempio da usare come foto del profilo di un utente), usa l'intent ACTION_IMAGE_CAPTURE
per chiedere all'utente di scattare una foto con la fotocamera del dispositivo. Il sistema
memorizza la foto acquisita nella
tabella MediaStore.Images
.
Condividere file multimediali con altre app
Utilizza il metodo insert()
per aggiungere record direttamente al MediaStore. Per ulteriori informazioni, consulta la sezione Aggiungere un elemento della guida all'archiviazione multimediale.
Condividere file multimediali con un'app specifica
Utilizza il componente FileProvider
di Android, come descritto nella guida Configurazione della condivisione
file.
Accedere ai file da codice o librerie che utilizzano percorsi di file diretti
Incorpora la logica basata sulle versioni di Android su cui viene eseguita l'app.
In esecuzione su Android 11
Usa questo approccio:
- Segui le best practice descritte in Richiedere le autorizzazioni app,
richiedi l'autorizzazione
READ_EXTERNAL_STORAGE
. - Accedi ai file utilizzando percorsi diretti.
Per ulteriori informazioni, consulta la sezione su come aprire i file multimediali utilizzando i percorsi file diretti.
In esecuzione su Android 10
Se la tua app ha come target Android 10 (livello API 29), disattiva l'archiviazione con ambito e continua a utilizzare l'approccio per Android 9 e versioni precedenti per eseguire questa operazione.
Android 9 o versioni precedenti
Usa questo approccio:
- Segui le best practice descritte in Richiedere le autorizzazioni app,
richiedi l'autorizzazione
WRITE_EXTERNAL_STORAGE
. - Accedi ai file utilizzando percorsi diretti.
Gestire i file non multimediali
Questa sezione descrive alcuni casi d'uso comuni per la gestione di file non multimediali e spiega l'approccio generale che può essere utilizzato dalla tua app. La seguente tabella riassume ciascuno di questi casi d'uso e rimanda alle singole sezioni che contengono ulteriori dettagli.
Caso d'uso | Riepilogo |
---|---|
Aprire un file di documento | Usa lo stesso approccio per tutte le versioni di Android. |
Scrittura su file su volumi di archiviazione secondari | Usa un unico approccio per Android 11. Utilizza un approccio diverso per le versioni precedenti di Android. |
Eseguire la migrazione dei file esistenti da una posizione di archiviazione legacy | Quando possibile, esegui la migrazione dei file nello spazio di archiviazione limitato. Se necessario, disattiva l'archiviazione con ambito per Android 10. |
Condividere contenuti con altre app | Usa lo stesso approccio per tutte le versioni di Android. |
Memorizzare nella cache i file non multimediali | Usa lo stesso approccio per tutte le versioni di Android. |
Esportare file non multimediali su un dispositivo | Scegli un solo approccio se la tua app utilizza l'archiviazione mirata. Utilizza un approccio diverso se la tua app disattiva l'archiviazione mirata. |
Aprire un file di documento
Utilizza l'intent ACTION_OPEN_DOCUMENT
per chiedere all'utente di scegliere un file da aprire utilizzando il selettore di sistema. Se vuoi
filtrare i tipi di file che il selettore di sistema presenterà all'utente tra cui scegliere, puoi utilizzare
setType()
o EXTRA_MIME_TYPES
.
Ad esempio, potresti trovare tutti i file PDF, ODT e TXT utilizzando il seguente codice:
Kotlin
startActivityForResult( Intent(Intent.ACTION_OPEN_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "*/*" putExtra(Intent.EXTRA_MIME_TYPES, arrayOf( "application/pdf", // .pdf "application/vnd.oasis.opendocument.text", // .odt "text/plain" // .txt )) }, REQUEST_CODE )
Java
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] { "application/pdf", // .pdf "application/vnd.oasis.opendocument.text", // .odt "text/plain" // .txt }); startActivityForResult(intent, REQUEST_CODE);
Scrittura in file su volumi di archiviazione secondari
I volumi di archiviazione secondari includono le schede SD. Puoi accedere alle informazioni su un dato volume di archiviazione utilizzando la classe StorageVolume
.
Incorpora la logica basata sulla versione di Android su cui viene eseguita l'app.
In esecuzione su Android 11
Usa questo approccio:
- Utilizza il modello di archiviazione con ambito.
- Scegli come target Android 10 (livello API 29) o versioni precedenti.
- Dichiara l'autorizzazione
WRITE_EXTERNAL_STORAGE
. - Esegui uno dei seguenti tipi di accesso:
- Accesso ai file mediante l'API
MediaStore
. - Accesso diretto al percorso file utilizzando API come
File
ofopen()
.
- Accesso ai file mediante l'API
In esecuzione su versioni precedenti
Utilizza Storage Access Framework, che consente agli utenti di selezionare la posizione su un volume di archiviazione secondario in cui la tua app può scrivere il file.
Eseguire la migrazione dei file esistenti da una posizione di archiviazione legacy
Una directory è considerata una posizione di archiviazione legacy se non si tratta di una directory specifica dell'app o di una directory condivisa pubblica. Se la tua app crea o consuma file in una posizione di archiviazione legacy, ti consigliamo di eseguire la migrazione dei file dell'app in posizioni accessibili con spazio di archiviazione con ambito e di apportare eventuali modifiche necessarie all'app affinché funzionino con i file nello spazio di archiviazione con ambito.
Mantieni l'accesso alla posizione di archiviazione legacy per la migrazione dei dati
L'app deve mantenere l'accesso alla posizione di archiviazione legacy per poter eseguire la migrazione dei file dell'app in posizioni accessibili con l'ambito dello spazio di archiviazione. L'approccio da utilizzare dipende dal livello API target della tua app.
Se la tua app ha come target Android 11
Imposta il flag
preserveLegacyExternalStorage
sutrue
per conservare il modello di archiviazione legacy in modo che la tua app possa eseguire la migrazione dei dati degli utenti quando eseguono l'upgrade alla nuova versione della tua app destinata ad Android 11.Continua a disattivare l'archiviazione con ambito in modo che la tua app possa continuare ad accedere ai file nella posizione di archiviazione legacy sui dispositivi Android 10.
Se la tua app ha come target Android 10
Disattiva l'archiviazione con ambito per mantenere più facilmente il comportamento della tua app nelle diverse versioni di Android.
Esegui la migrazione dei dati dell'app
Quando la tua app è pronta per la migrazione, utilizza il seguente approccio:
- Scegli come target Android 10 o versioni precedenti.
- Disattiva l'archiviazione con ambito in modo che la tua app abbia accesso ai file di cui devi eseguire la migrazione.
-
Esegui il deployment del codice che utilizza l'API
File
per spostare i file dalla posizione attuale in/sdcard/
a una posizione accessibile con spazio di archiviazione limitato:- Sposta tutti i file dell'app privata nella directory restituita dal metodo
getExternalFilesDir()
. - Sposta tutti i file non multimediali condivisi in una sottodirectory della directory
Downloads/
dedicata all'app.
- Sposta tutti i file dell'app privata nella directory restituita dal metodo
- Rimuovi le directory di archiviazione legacy dell'app dalla directory
/sdcard/
.
Dopo che gli utenti installano la nuova versione dell'app, completano il processo di migrazione dei dati sui propri dispositivi. Puoi monitorare il processo di migrazione nella tua base utenti creando un evento di analisi.
Dopo che gli utenti hanno eseguito la migrazione dei loro dati, pubblica un altro aggiornamento dell'app, dove scegli come target Android 11.
Condividere contenuti con altre app
Per condividere i file della tua app con un'altra app, utilizza
FileProvider
. Per le app che devono condividere file tra loro, consigliamo di utilizzare un fornitore di contenuti per ciascuna app e poi di sincronizzare i dati man mano che le app vengono aggiunte alla raccolta.
Memorizza nella cache i file non multimediali
L'approccio da utilizzare dipende dal tipo di file che devono essere memorizzati nella cache.
- File di piccole dimensioni o file che contengono informazioni sensibili: usa
Context#getCacheDir()
. - File di grandi dimensioni o file che non contengono informazioni sensibili: utilizza
Context#getExternalCacheDir()
.
Esportare file non multimediali su un dispositivo
Definisci una posizione predefinita appropriata per l'archiviazione dei file non multimediali. Consenti agli utenti di esportare file da directory specifiche dell'app a una posizione più accessibile in genere. Utilizza i download di MediaStore o le raccolte di documenti per esportare file non multimediali sul dispositivo.
Disattivare temporaneamente l'archiviazione con ambito
Prima che l'app sia completamente compatibile con l'archiviazione con ambito, puoi disattivarla temporaneamente sia nei tuoi test sia nella tua app di produzione.
Disattiva nei test
Su Android 10 (livello API 29) e versioni successive, i test dell'app vengono eseguiti in una sandbox di archiviazione per impostazione predefinita. Questa sandbox impedisce all'app di accedere ai file all'esterno della directory specifica dell'app e delle directory condivise pubblicamente.
Se un test restituisce file per l'host, ad esempio screenshot, dati di debug, dati di copertura o metriche sulle prestazioni, puoi scrivere questi file nelle directory globali. A questo scopo, aggiungi il seguente flag al cablaggio pertinente che
Richiama am instrument
:
-e no-isolated-storage 1
Questo flag influisce su tutti i comportamenti dello scenario di test strumentato e su tutto il codice di test richiamato. Di conseguenza, quando utilizzi questo flag non puoi convalidare la compatibilità dell'app con l'archiviazione con ambito. Per l'output di test, è preferibile scrivere in uno spazio di archiviazione con ambito app leggibile dalla shell. Puoi quindi eseguire il pull di
quella directory con ambito app. Per determinare da quale directory eseguire il pull, chiama getExternalMediaDirs()
.
Disattivare nell'app di produzione
Se la tua app ha come target Android 10 (livello API 29) o versioni precedenti, puoi disattivare temporaneamente
lo spazio di archiviazione limitato nell'app di produzione. Se invece scegli come target
Android 10, devi impostare il valore di
requestLegacyExternalStorage
su true
nel file manifest dell'app:
<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Per verificare il comportamento di un'app che ha come target Android 10 o versioni precedenti quando
utilizzi l'archiviazione limitata, puoi attivarne il comportamento impostando il valore
requestLegacyExternalStorage
su false
. Se stai eseguendo test su un dispositivo che esegue Android 11, puoi anche utilizzare i flag di compatibilità delle app per testare il comportamento della tua app con o senza spazio di archiviazione limitato.
Risorse aggiuntive
Per ulteriori informazioni sullo spazio di archiviazione di Android, consulta i seguenti materiali: