Casi d'uso e best practice per lo spazio di archiviazione di Android

Per dare agli utenti un maggiore controllo sui propri file e limitare il disordine dei file, Android 10 ha introdotto un nuovo paradigma di archiviazione per le app archiviazione con ambito. Modifiche allo spazio di archiviazione con ambito il modo in cui le app archiviano e accedono ai file nella memoria esterna 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.

Per scoprire di più su come archiviare e accedere ai file su Android, consulta l'articolo relativo allo spazio di archiviazione guide alla formazione.

Gestire i file multimediali

Questa sezione descrive alcuni dei casi d'uso comuni per la gestione dei file multimediali. (video, immagini e file audio) e spiega l'approccio generale che il tuo che l'app può utilizzare. La tabella seguente riassume ciascuno di questi casi d'uso e i link a ciascuna sezione contenente ulteriori dettagli.

Caso d'uso Riepilogo
Mostra tutti i file immagine 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 Se la tua app utilizza l'archiviazione con ambito, scegli un solo approccio. Utilizza un altro se la tua app disattiva l'archiviazione con ambito.
Definire la posizione di archiviazione per i nuovi download Se la tua app utilizza l'archiviazione con ambito, scegli un solo approccio. Utilizza un altro se la tua app disattiva l'archiviazione con ambito.
Esportare i file multimediali degli utenti su un dispositivo Utilizza lo stesso approccio per tutte le versioni di Android.
Modificare o eliminare più file multimediali in in una singola operazione Usa un unico approccio per Android 11. Per Android 10, disattiva l'ambito spazio di archiviazione e usare invece l'approccio per Android 9 e versioni precedenti.
Importa una singola immagine già esistente esiste 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 usano percorsi di file diretti Usa un unico approccio per Android 11. Per Android 10, disattiva l'ambito spazio di archiviazione e usare invece l'approccio per Android 9 e versioni precedenti.

Mostra file di immagini o video da più cartelle

Eseguire query su una raccolta di contenuti multimediali utilizzando l'app query() tramite Google Cloud CLI o tramite l'API Compute Engine. Per filtrare o ordinare i file multimediali, regola projection, selection, selectionArgs e sortOrder.

Mostra immagini o video da una determinata cartella

Utilizza questo approccio:

  1. Seguendo le best practice descritte in Richiedere le autorizzazioni app, richiedi READ_EXTERNAL_STORAGE autorizzazione.
  2. 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. Il motivo è che 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.

Accedi 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 l'archiviazione con ambito, presta attenzione alla località in cui scegli di archiviare i file multimediali che scarichi.

Se altre app richiedono l'accesso ai file, valuta l'utilizzo di contenuti multimediali ben definiti raccolte per i download o le raccolte di documenti.

Su Android 11 e versioni successive, i file all'interno di file specifici dell'app esterna non sono accessibili ad altre app, anche se usi DownloadManager per recuperarli.

Esportare i file multimediali degli utenti su un dispositivo

Definisci una posizione predefinita adeguata in cui archiviare i contenuti multimediali dell'utente file:

di Gemini Advanced.

Modificare o eliminare più file multimediali in una singola operazione

Incorpora una logica basata sulle versioni di Android su cui viene eseguita l'app.

In esecuzione su Android 11

Utilizza questo approccio:

  1. Crea un intent in attesa per la richiesta di scrittura o eliminazione della tua app utilizzando MediaStore.createWriteRequest() oppure MediaStore.createTrashRequest() e chiedi all'utente l'autorizzazione per modificare un insieme di file richiamando l'intento.
  2. 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à in la tua app richiede l'autorizzazione.

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 l'ambito spazio di archiviazione e continuare a usare l'approccio ad Android 9 e inferiori per eseguire questa operazione.

Con Android 9 o versioni precedenti

Utilizza questo approccio:

  1. Seguendo le best practice descritte in Richiedere le autorizzazioni app, richiedi WRITE_EXTERNAL_STORAGE autorizzazione.
  2. 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:

  1. Seguendo le best practice descritte in Richiedere le autorizzazioni app, richiedi READ_EXTERNAL_STORAGE autorizzazione.
  2. Utilizza la query() API per eseguire query su una raccolta di contenuti multimediali.
  3. Visualizza i risultati nell'interfaccia utente personalizzata della tua app.

Utilizza il selettore di sistema

Utilizza la 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 al un 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, per come foto del profilo di un utente), utilizza l' ACTION_IMAGE_CAPTURE chiedere all'utente di scattare una foto utilizzando la fotocamera del dispositivo. Il sistema memorizza la foto acquisita 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.

Accedi ai file da codice o librerie che utilizzano percorsi di file diretti

Incorpora una logica basata sulle versioni di Android su cui viene eseguita l'app.

In esecuzione su Android 11

Utilizza questo approccio:

  1. Seguendo le best practice descritte in Richiedere le autorizzazioni app, richiedi READ_EXTERNAL_STORAGE autorizzazione.
  2. 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 l'ambito spazio di archiviazione e continuare a usare l'approccio ad Android 9 e inferiori per eseguire questa operazione.

Con Android 9 o versioni precedenti

Utilizza questo approccio:

  1. Seguendo le best practice descritte in Richiedere le autorizzazioni app, richiedi WRITE_EXTERNAL_STORAGE autorizzazione.
  2. 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.
Scrivi su file su volumi di archiviazione secondari Usa un unico approccio per Android 11. Usa un approccio diverso per tutte le versioni 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 persone 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 Se la tua app utilizza l'archiviazione con ambito, scegli un solo approccio. Utilizza un altro se la tua app disattiva l'archiviazione con ambito.

Apri il file di un 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:

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);

Scrivi su file su volumi di archiviazione secondari

I volumi di archiviazione secondari includono le schede SD. Puoi accedere alle informazioni su un un determinato volume di archiviazione StorageVolume.

Incorpora una logica basata sulla versione di Android su cui viene eseguita l'app.

In esecuzione su Android 11

Utilizza questo approccio:

  1. Utilizza il modello di archiviazione con ambito.
  2. Scegli come target Android 10 (livello API 29) o versioni precedenti.
  3. Dichiara il WRITE_EXTERNAL_STORAGE autorizzazione.
  4. Esegui uno dei seguenti tipi di accesso:
    • Accesso ai file con l'API MediaStore.
    • Accesso diretto al percorso file utilizzando API come File oppure fopen().

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 legacy se non è una una directory specifica di un'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

La tua app deve mantenere l'accesso alla posizione dello spazio di archiviazione precedente per: eseguire la migrazione dei file delle app in posizioni accessibili con l'archiviazione con ambito. La dipende dal livello API target della tua app.

Se la tua app ha come target Android 11
  1. Imposta il parametro preserveLegacyExternalStorage flag a true 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.

  2. Continua a disattivare l'archiviazione con ambito in modo da la tua app può continuare ad accedere ai tuoi file nella posizione di archiviazione precedente su 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:

  1. Scegli come target Android 10 o versioni precedenti.
  2. Disattiva l'archiviazione con ambito in modo da la tua app ha accesso ai file di cui devi eseguire la migrazione.
  3. Esegui il deployment del codice che utilizza l'API File per spostare i file dal posizione attuale in /sdcard/ a una posizione accessibile con l'archiviazione con ambito:

    1. Sposta tutti i file privati dell'app nella directory restituita dal getExternalFilesDir() .
    2. Sposta tutti i file non multimediali condivisi in una sottodirectory dedicata all'app di nella directory Downloads/.
  4. Rimuovi le directory di archiviazione legacy della tua app dal 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.

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 delle app in una posizione più accessibile in generale. Utilizza i download di MediaStore o le raccolte di documenti per esportare file non multimediali in del dispositivo.

Disattiva temporaneamente l'archiviazione con ambito

Prima che la tua app sia completamente compatibile con lo spazio di archiviazione con ambito, puoi attivare temporaneamente sia nei test che nella 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 sandbox per impostazione predefinita. Questa sandbox impedisce alla tua app di accedere ai file esterni della directory specifica dell'app e delle directory condivise pubblicamente.

Se un test produce file per l'host, ad esempio screenshot, dati di debug, di copertura o metriche sulle prestazioni; puoi scrivere questi file . A tale scopo, aggiungi la seguente flag al cablaggio pertinente richiama am instrument:

-e no-isolated-storage 1

Questo flag influisce su tutti il comportamento dello scenario di test instrumentato e interessa tutti di 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 è meglio utilizzare nello spazio di archiviazione con ambito app leggibile dalla shell. Puoi quindi eseguire il pull con ambito app. Per determinare da quale directory eseguire il pull, chiama getExternalMediaDirs()

Disattiva nella tua app di produzione

Se la tua app ha come target Android 10 (livello API 29) o versioni precedenti, puoi attivare temporaneamente spazio di archiviazione nell'app di produzione. Se scegli come target Tuttavia, per Android 10 devi impostare il valore. Da requestLegacyExternalStorage a 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:

Blog post