Per offrire agli utenti un maggiore controllo sui file e limitare il disordine, Android 10 ha introdotto un nuovo paradigma di archiviazione per le app chiamato spazio di archiviazione limitato. Lo spazio di archiviazione delimitato cambia il modo in cui le app archiviano e accedono ai file sullo spazio di archiviazione esterno di un dispositivo. Per aiutarti eseguire la migrazione dell'app per supportare l'archiviazione con ambito, segui le best practice per i casi d'uso dello spazio di archiviazione descritti in questa guida. I casi d'uso sono organizzati in due categorie: gestione di file multimediali e gestione non multimediali.
In molti casi, la tua app crea file a cui altre app non devono o non devono accedere. Il sistema fornisce posizioni di archiviazione specifiche per le app. .
Per scoprire di più su come archiviare e accedere ai file su Android, consulta le guide di formazione sull'archiviazione.
Gestire i file multimediali
Questa sezione descrive alcuni casi d'uso comuni per la gestione dei file multimediali (file video, immagine e audio) e spiega l'approccio generale che la tua app può utilizzare. La tabella seguente riassume ciascuno di questi casi d'uso e contiene i link alle sezioni con ulteriori dettagli.
Caso d'uso | Riepilogo |
---|---|
Mostrare tutti i file di immagini o video | Utilizza lo stesso approccio per tutte le versioni di Android. |
Mostrare immagini o video di un determinato tipo cartella | Utilizza lo stesso approccio per tutte le versioni di Android. |
Accedi alle informazioni sulla posizione da foto | Utilizza un approccio se la tua app utilizza lo spazio di archiviazione limitato. Utilizza un approccio diverso se la tua app disattiva l'archiviazione mirata. |
Definire la posizione di archiviazione dei nuovi download | Utilizza un approccio se la tua app utilizza lo spazio di archiviazione limitato. Utilizza un approccio diverso se la tua app disattiva l'archiviazione mirata. |
Esportare i file multimediali dell'utente su un dispositivo | Utilizza lo stesso approccio per tutte le versioni di Android. |
Modificare o eliminare più file multimediali in in una singola operazione | Utilizza un approccio per Android 11. Per Android 10, disattiva l'ambito spazio di archiviazione e usare invece l'approccio per Android 9 e versioni precedenti. |
Importare un'immagine singola già esistente | Utilizza lo stesso approccio per tutte le versioni di Android. |
Acquisire una singola immagine | Utilizza lo stesso approccio per tutte le versioni di Android. |
Condividere file multimediali con altre app | Utilizza lo stesso approccio per tutte le versioni di Android. |
Condividere file multimediali con un'app specifica | Utilizza lo stesso approccio per tutte le versioni di Android. |
Accedere ai file da codice o librerie che utilizzano percorsi di file diretti | Utilizza un approccio per Android 11. Per Android 10, disattiva lo spazio di archiviazione con ambito e utilizza l'approccio per Android 9 e versioni precedenti. |
Mostrare file di immagini o video da più cartelle
Esegui una query su una raccolta di contenuti multimediali
utilizzando l'API query()
. Per filtrare o ordinare i file multimediali, regola projection
, selection
,
selectionArgs
e sortOrder
.
Mostra immagini o video da una determinata cartella
Utilizza questo approccio:
- Seguendo le best practice descritte in Richiedi autorizzazioni app,
richiedi l'autorizzazione
READ_EXTERNAL_STORAGE
. - Recupera i file multimediali in base al valore di
MediaColumns.DATA
, che contiene il percorso di file system assoluto per l'elemento multimediale su disco.
Nota: quando accedi a un file multimediale esistente, puoi utilizzare il valore
di DATA
nella tua logica. Questo perché questo valore ha un percorso file valido.
Tuttavia, non dare per scontato che il file sia sempre disponibile. Preparati a gestirle
eventuali errori di I/O basati su file.
Per creare o aggiornare un file multimediale, invece, non utilizzare la classe
Colonna DATA
. Usa invece i DISPLAY_NAME
e
RELATIVE_PATH
colonne.
Accedere alle informazioni sulla posizione dalle foto
Se l'app utilizza l'archiviazione con ambito, segui i passaggi descritti in Informazioni sulla posizione nelle fotografie della guida all'archiviazione dei contenuti multimediali.
Definisci la posizione di archiviazione per i nuovi download
Se la tua app utilizza lo spazio archiviazione limitato, tieni presente la posizione in cui scegli di memorizzare i file multimediali scaricati.
Se altre app richiedono l'accesso ai file, valuta la possibilità di utilizzare collezioni di contenuti 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 per l'app non sono accessibili ad altre app, anche se utilizzi DownloadManager
per recuperarli.
Esportare i file multimediali utente su un dispositivo
Definisci una posizione predefinita adeguata in cui archiviare i contenuti multimediali dell'utente file:
- Consenti agli utenti di scegliere se rendere i file multimediali leggibili da altre app o meno, usando lo spazio di archiviazione specifico per le app o lo spazio di archiviazione condiviso.
- Consenti agli utenti di esportare file da directory specifiche delle app in una posizione più accessibile in generale. Utilizza le raccolte di immagini, video e audio di MediaStore per esportare i file multimediali in galleria del dispositivo.
Modificare o eliminare più file multimediali in un'unica operazione
Incorpora una logica basata sulle versioni di Android su cui viene eseguita l'app.
In esecuzione su Android 11
Utilizza questo approccio:
- Crea un intent in attesa per la richiesta di scrittura o eliminazione della tua app utilizzando
MediaStore.createWriteRequest()
oppureMediaStore.createTrashRequest()
e chiedi all'utente l'autorizzazione per modificare un insieme di file richiamando l'intento. 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à della tua app ne ha bisogno.
Scopri di più su come gestire gruppi di contenuti multimediali mediante questi file 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 lo spazio di archiviazione soggetto a limitazioni e continua a utilizzare l'approccio per Android 9 e versioni precedenti per eseguire questa operazione.
Con Android 9 o versioni precedenti
Utilizza questo approccio:
- Seguendo le best practice descritte in Richiedere le autorizzazioni app,
richiedi
WRITE_EXTERNAL_STORAGE
autorizzazione. - Utilizza l'API
MediaStore
per modificare o eliminare i file multimediali.
Importa una singola immagine già esistente
Quando vuoi importare una singola immagine già esistente (ad esempio, per utilizzare come foto per il profilo di un utente), la tua app può utilizzare la propria UI per operativa, oppure il selettore di sistema.
Presenta la tua interfaccia utente
Utilizza questo approccio:
- Seguendo le best practice descritte in Richiedere le autorizzazioni app,
richiedi
READ_EXTERNAL_STORAGE
autorizzazione. - Utilizza l'API
query()
per eseguire query su una raccolta multimediale. - Visualizza i risultati nell'interfaccia utente personalizzata della tua app.
Utilizza il selettore di sistema
Utilizza l'intent ACTION_GET_CONTENT
, che chiede all'utente di selezionare un'immagine da importare.
Se vuoi filtrare i tipi di immagini che il selettore di sistema presenta al
un utente tra cui scegliere, puoi usare
setType()
o EXTRA_MIME_TYPES
.
Acquisisci una singola immagine
Quando vuoi acquisire una singola immagine da utilizzare nella tua app (ad esempio come foto del profilo di un utente), utilizza l'intent ACTION_IMAGE_CAPTURE
per chiedere all'utente di scattare una foto utilizzando la fotocamera del dispositivo. Il sistema immagazzina la foto acquisita nella tabella MediaStore.Images
.
Condividere file multimediali con altre app
Utilizza la
insert()
per aggiungere record direttamente in MediaStore. Per ulteriori informazioni, vedi
nella sezione Aggiungi un elemento del
all'archiviazione dei contenuti multimediali.
Condividere file multimediali con un'app specifica
Usa il componente FileProvider
di Android, come descritto nella sezione File di configurazione
condivisione.
Accedere ai file da codice o librerie che utilizzano percorsi di file diretti
Incorpora la logica in base alle versioni di Android su cui viene eseguita la tua app.
In esecuzione su Android 11
Utilizza questo approccio:
- Seguendo le best practice descritte in Richiedere le autorizzazioni app,
richiedi
READ_EXTERNAL_STORAGE
autorizzazione. - Accedi ai file utilizzando percorsi diretti.
Per ulteriori informazioni, consulta la sezione su come aprire i file multimediali utilizzando percorsi di file diretti.
In esecuzione su Android 10
Se la tua app ha come target Android 10 (livello API 29), disattiva lo spazio di archiviazione soggetto a limitazioni e continua a utilizzare l'approccio per Android 9 e versioni precedenti per eseguire questa operazione.
In esecuzione su Android 9 o versioni precedenti
Utilizza questo approccio:
- Seguendo le best practice descritte in Richiedi autorizzazioni app,
richiedi l'autorizzazione
WRITE_EXTERNAL_STORAGE
. - Accedi ai file utilizzando percorsi diretti.
Gestire i file non multimediali
Questa sezione descrive alcuni dei casi d'uso comuni per la gestione di file non multimediali. e illustra l'approccio generale che la tua app può usare. La tabella seguente riassume ciascuno di questi casi d'uso e fornisce i link a ognuna delle sezioni che contenere ulteriori dettagli.
Caso d'uso | Riepilogo |
---|---|
Aprire il file di un documento | Utilizza lo stesso approccio per tutte le versioni di Android. |
Scrivere 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 di file esistenti da una versione precedente posizione di archiviazione | Se possibile, esegui la migrazione dei file all'archiviazione con ambito. Disattiva l'ambito per Android 10. |
Condividere contenuti con altre app | Utilizza lo stesso approccio per tutte le versioni di Android. |
Memorizzare nella cache i file non multimediali | Utilizza lo stesso approccio per tutte le versioni di Android. |
Esportare file non multimediali su un dispositivo | Utilizza un approccio se la tua app utilizza lo spazio di archiviazione limitato. Utilizza un approccio diverso se la tua app disattiva l'archiviazione mirata. |
Aprire un file di documento
Utilizza la ACTION_OPEN_DOCUMENT
per chiedere all'utente di scegliere un file da aprire usando il selettore di sistema. Se
vuoi filtrare i tipi di file che il selettore di sistema presenterà al
un 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:
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 )
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);
Scrivere in file su volumi di archiviazione secondari
I volumi di archiviazione secondari includono le schede SD. Puoi accedere alle informazioni su un determinato volume di archiviazione utilizzando la classe StorageVolume
.
Incorpora la logica in base alla versione di Android su cui viene eseguita la tua app.
In esecuzione su Android 11
Utilizza questo approccio:
- Utilizza il modello di spazio di archiviazione basato sugli ambiti.
- Scegli come target Android 10 (livello API 29) o versioni precedenti.
- Dichiara il
WRITE_EXTERNAL_STORAGE
autorizzazione. - Esegui uno dei seguenti tipi di accesso:
- Accesso ai file con l'API
MediaStore
. - Accesso diretto al percorso del file utilizzando API come
File
ofopen()
.
- Accesso ai file con l'API
In esecuzione su versioni precedenti
Utilizzare Storage Access Framework, che consente agli utenti di selezionare la posizione su un volume di archiviazione secondario in cui l'app può scrivere .
Eseguire la migrazione dei file esistenti da un percorso di archiviazione precedente
Una directory è considerata una posizione di archiviazione precedente se non è una directory specifica per l'app o una directory condivisa pubblica. Se la tua app crea o utilizza i file in una posizione di archiviazione precedente, ti consigliamo di eseguire la migrazione dell'app in posizioni accessibili con l'archiviazione con ambito e apportare le modifiche necessarie all'app per funzionare con i file nello spazio di archiviazione con ambito.
Mantenere l'accesso alla posizione di archiviazione precedente per la migrazione dei dati
L'app deve mantenere l'accesso alla posizione di archiviazione precedente per eseguire la migrazione dei file dell'app in posizioni accessibili con lo spazio di archiviazione limitato. La dipende dal livello API target della tua app.
Se la tua app ha come target Android 11
Imposta il parametro
preserveLegacyExternalStorage
flag atrue
per preservare lo spazio di archiviazione legacy modello in modo che che la tua app possa eseguire la migrazione dei dati di un utente quando esegue l'upgrade alla nuova versione di la tua app che ha come target Android 11.Continua a disattivare lo spazio di archiviazione delimitato in modo che la tua app possa continuare ad accedere ai file nella posizione di archiviazione precedente sui dispositivi Android 10.
Se la tua app ha come target Android 10
Disattiva l'archiviazione con ambito per semplificare la mantenere il comportamento dell'app nelle varie versioni di Android.
Esegui la migrazione dei dati dell'app
Quando la tua app è pronta per la migrazione, utilizza il seguente approccio:
- Target Android 10 o versioni precedenti.
- Disattiva lo spazio di archiviazione delimitato 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 loro posizione corrente in/sdcard/
a una posizione accessibile con lo spazio di archiviazione delimitato:- Sposta tutti i file privati dell'app nella directory restituita dal
getExternalFilesDir()
. - Sposta tutti i file non multimediali condivisi in una sottodirectory dedicata all'app di
nella directory
Downloads/
.
- Sposta tutti i file privati dell'app nella directory restituita dal
- Rimuovi le directory di archiviazione precedenti dell'app dalla directory
/sdcard/
.
Dopo che gli utenti installano la nuova versione della tua app, completano i dati processo di migrazione sui propri dispositivi. Puoi monitorare il processo di migrazione alla base utenti creando un evento di analisi.
Dopo che gli utenti hanno eseguito la migrazione dei propri dati, pubblica un altro aggiornamento dell'app, dove hai come target Android 11.
Condividere contenuti con altre app
Per condividere i file di un'app con un'altra app, usa un
FileProvider
. Per le app che devono essere tutte condivise
file tra loro, ti consigliamo di utilizzare una libreria di contenuti
provider per ogni app.
quindi sincronizzando i dati man mano che le app vengono aggiunte alla raccolta.
Memorizza nella cache file non multimediali
L'approccio da utilizzare dipende dal tipo di file necessario da memorizzare nella cache.
- File di piccole dimensioni o file che contengono informazioni sensibili: utilizza
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 adeguata per archiviare contenuti non multimediali . Consenti agli utenti di esportare file da directory specifiche dell'app in una posizione più accessibile a livello generale. Utilizza i download di MediaStore o le raccolte di documenti per esportare file non multimediali in del dispositivo.
Gestire file specifici per le app
Se la tua app crea file a cui altre app non devono accedere o non devono accedere, puoi archiviarli in località di archiviazione specifiche per l'app.
Directory della memoria interna
Il sistema impedisce ad altre app di accedere a queste posizioni. Su Android 10 (livello API 29) e versioni successive, queste posizioni sono criptate. Queste posizioni sono un buon posto per archiviare dati sensibili a cui solo la tua app può accedere.
Directory di archiviazione esterna
Se lo spazio di archiviazione interno non è sufficiente per archiviare i file specifici dell'app, valuta la possibilità di utilizzare lo spazio di archiviazione esterno. Sebbene sia possibile per un'altra app accedere a queste directory se dispone delle autorizzazioni appropriate, i file memorizzati in queste directory sono destinati all'uso solo da parte della tua app.
Su Android 4.4 (livello API 19) o versioni successive, la tua app non deve richiedere autorizzazioni relative allo spazio di archiviazione per accedere a directory specifiche dell'app all'interno dello spazio di archiviazione esterno.
Quando l'utente disinstalla l'app, i file salvati nello spazio di archiviazione specifico dell'app vengono rimosso, pertanto non dovresti usare questo spazio di archiviazione per salvare tutto ciò che l'utente si aspetta di conservare indipendentemente dalla tua app.
Disattiva temporaneamente l'archiviazione con ambito
Prima che la tua app sia completamente compatibile con lo spazio di archiviazione limitato, puoi disattivarla temporaneamente sia nei test sia nell'app di produzione.
Disattiva nei test
Su Android 10 (livello API 29) e versioni successive, i test della tua app vengono eseguiti in uno spazio di archiviazione la sandbox per impostazione predefinita. Questa sandbox impedisce all'app di accedere ai file al di fuori della directory specifica dell'app e delle directory condivise pubblicamente.
Se un test genera file per l'host, ad esempio screenshot, dati di debug, dati sulla copertura o metriche sul rendimento, puoi scrivere questi file nelle directory globali. Per farlo, aggiungi il seguente flag al harness pertinente che invoca am instrument
:
-e no-isolated-storage 1
Questo flag influisce su tutto il comportamento del caso di test strumentato e su tutto il codice di test invocato. Pertanto, quando utilizzi questo flag, non puoi convalidare la compatibilità della tua app con lo spazio di archiviazione limitato. Per l'output del test, è meglio scrivere nello spazio di archiviazione a livello di app leggibile dalla shell. Puoi quindi estrarre la directory basata sull'app. Per determinare da quale directory estrarre i dati, chiama
getExternalMediaDirs()
.
Disattiva nella tua 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 basato sugli ambiti nell'app di produzione. Tuttavia, se hai 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 testare il comportamento di un'app che ha come target Android 10 o versioni precedenti quando
utilizzando l'archiviazione con ambito, puoi attivare il comportamento impostando il valore
Da requestLegacyExternalStorage
a false
. Se stai eseguendo il test su un dispositivo che
esegue Android 11, puoi anche utilizzare la compatibilità app
per testare
comportamento dell'app, con o senza spazio di archiviazione con ambito.
Risorse aggiuntive
Per ulteriori informazioni sullo spazio di archiviazione di Android, visualizza i seguenti materiali: