In molti casi, l'app crea file a cui le altre app non devono accedere oppure non devono accedere. Il sistema fornisce le seguenti posizioni per l'archiviazione File specifici per le app:
Directory della memoria interna: queste directory includono una directory una posizione per l'archiviazione di file permanenti e un'altra posizione per l'archiviazione di memorizzazione nella cache. Il sistema impedisce ad altre app di accedere a queste posizioni. Su Android 10 (livello API 29) e versioni successive, queste posizioni sono criptate. Questi caratteristiche rendono queste località un buon posto per archiviare dati sensibili che a cui può accedere soltanto l'app.
Directory di archiviazione esterna:queste directory includono una sezione una posizione per l'archiviazione di file permanenti e un'altra posizione per l'archiviazione di memorizzazione nella cache. Sebbene sia possibile che un'altra app acceda a queste directory Se l'app dispone delle autorizzazioni appropriate, i file archiviati in queste directory sono destinate esclusivamente all'uso da parte della tua app. Se intendi creare file a cui le altre app dovrebbero essere in grado di accedere, la tua app deve archiviare questi file La parte dello spazio di archiviazione condiviso dello spazio di archiviazione esterno .
Quando l'utente disinstalla l'app, i file salvati nello spazio di archiviazione specifico dell'app vengono rimosso. A causa di questo comportamento, non devi usare questo spazio di archiviazione per salvare tutto ciò che l'utente si aspetta di conservare indipendentemente dalla tua app. Per Ad esempio, se la tua app consente agli utenti di scattare foto, l'utente si aspetta che potrà accedere a quelle foto anche dopo aver disinstallato la tua app. Dovresti quindi utilizzare lo spazio di archiviazione condiviso per salvare questi tipi di file nei raccolta di contenuti multimediali.
Le seguenti sezioni descrivono come archiviare e accedere ai file all'interno specifiche dell'app.
Accesso dalla memoria interna
Per ogni app, il sistema fornisce directory all'interno della memoria interna in cui app può organizzare i propri file. Una directory è progettata per permanenti e un altro contenente i file YAML dell'app memorizzati nella cache. La tua app non richiede alcun sistema le autorizzazioni di lettura e scrittura sui file in queste directory.
Le altre app non possono accedere ai file memorizzati nella memoria interna. Ciò rende nella memoria interna è un buon posto per i dati delle app a cui altre app non dovrebbero accedere.
Tieni presente, tuttavia, che queste directory tendono a essere piccole. Prima di scrivere specifici di un'app nella memoria interna, l'app dovrebbe eseguire query spazio di archiviazione sul dispositivo.
Accedi ai file permanenti
I file permanenti comuni della tua app si trovano in una directory che puoi
l'accesso utilizzando la filesDir
di un oggetto di contesto. Il framework offre diversi metodi per aiutarti
accedere ai file e archiviarli in questa directory.
Accedere ai file e archiviarli
Puoi utilizzare l'API File
per accedere ai file e archiviarli.
Per mantenere le prestazioni della tua app, non aprire e chiudere lo stesso più volte.
Il seguente snippet di codice mostra come utilizzare l'API File
:
Kotlin
val file = File(context.filesDir, filename)
Java
File file = new File(context.getFilesDir(), filename);
Archiviare un file utilizzando uno stream
In alternativa all'utilizzo dell'API File
, puoi chiamare
openFileOutput()
per ottenere una FileOutputStream
che scrive
in un file nella directory filesDir
.
Il seguente snippet di codice mostra come scrivere del testo in un file:
Kotlin
val filename = "myfile" val fileContents = "Hello world!" context.openFileOutput(filename, Context.MODE_PRIVATE).use { it.write(fileContents.toByteArray()) }
Java
String filename = "myfile"; String fileContents = "Hello world!"; try (FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE)) { fos.write(fileContents.toByteArray()); }
Per consentire ad altre app di accedere ai file archiviati in
questa directory all'interno della memoria interna, utilizza
FileProvider
con
FLAG_GRANT_READ_URI_PERMISSION
.
Accedere a un file utilizzando uno stream
Per leggere un file come flusso, utilizza
openFileInput()
:
Kotlin
context.openFileInput(filename).bufferedReader().useLines { lines -> lines.fold("") { some, text -> "$some\n$text" } }
Java
FileInputStream fis = context.openFileInput(filename); InputStreamReader inputStreamReader = new InputStreamReader(fis, StandardCharsets.UTF_8); StringBuilder stringBuilder = new StringBuilder(); try (BufferedReader reader = new BufferedReader(inputStreamReader)) { String line = reader.readLine(); while (line != null) { stringBuilder.append(line).append('\n'); line = reader.readLine(); } } catch (IOException e) { // Error occurred when opening raw file for reading. } finally { String contents = stringBuilder.toString(); }
Visualizza l'elenco dei file
Puoi ottenere un array contenente i nomi di tutti i file all'interno dell'filesDir
della directory chiamando
fileList()
, come mostrato in
il seguente snippet di codice:
Kotlin
var files: Array<String> = context.fileList()
Java
Array<String> files = context.fileList();
Crea directory nidificate
Puoi anche creare directory nidificate o aprire una directory interna chiamando
getDir()
in modello basato su Kotlin
o passando la directory root e un nuovo nome alla directory in un File
nel codice basato su Java:
Kotlin
context.getDir(dirName, Context.MODE_PRIVATE)
Java
File directory = context.getFilesDir(); File file = new File(directory, filename);
Crea file cache
Se hai bisogno di archiviare i dati sensibili solo temporaneamente, devi utilizzare la designata nella directory della cache nella memoria interna per salvare i dati. Così come per tutta l'archiviazione specifica delle app, i file archiviati in questa directory vengono rimossa quando l'utente disinstalla l'app, anche se i file in questa directory potrebbe essere rimosso prima.
.Per creare un file memorizzato nella cache, chiama
File.createTempFile()
:
Kotlin
File.createTempFile(filename, null, context.cacheDir)
Java
File.createTempFile(filename, null, context.getCacheDir());
L'app accede a un file in questa directory utilizzando
cacheDir
di un
e l'API File
:
Kotlin
val cacheFile = File(context.cacheDir, filename)
Java
File cacheFile = new File(context.getCacheDir(), filename);
Rimuovi file della cache
Anche se a volte Android elimina i file della cache autonomamente, non devi fare affidamento sul sistema per ripulire questi file. Devi sempre mantenere cache dell'app all'interno della memoria interna.
Per rimuovere un file dalla directory della cache all'interno della memoria interna, utilizza una delle utilizza i seguenti metodi:
Il metodo
delete()
su un oggettoFile
che rappresenta il file:Kotlin
cacheFile.delete()
Java
cacheFile.delete();
La
deleteFile()
del contesto dell'app, passando il nome del file:Kotlin
context.deleteFile(cacheFileName)
Java
context.deleteFile(cacheFileName);
Accesso da memoria esterna
Se la memoria interna non offre spazio sufficiente per archiviare file specifici dell'app, prendi in considerazione l'utilizzo di un'unità di archiviazione esterna. Il sistema fornisce directory all'interno unità di archiviazione esterna in cui un'app può organizzare i file che forniscono valore all'utente solo all'interno dell'app. Una directory è progettata per i pod e un altro contiene la cache dell'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 di archiviazione. I file archiviati in queste directory vengono rimossi quando l'app viene disinstallata.
Sui dispositivi con Android 9 (livello API 28) o versioni precedenti, la tua app può accedere al file specifici dell'app che appartengono ad altre app, a condizione che l'app presenti le autorizzazioni appropriate per lo spazio di archiviazione. Per dare agli utenti un maggiore controllo sui loro file per limitare il disordine dei file, vengono visualizzate le app destinate ad Android 10 (livello API 29) e versioni successive l'accesso con ambito a un'unità di archiviazione esterna o spazio di archiviazione, per impostazione predefinita. Con ambito Aver attivato, le app non possono accedere alle directory specifiche dell'app che appartengono ad altre app.
Verifica che lo spazio di archiviazione sia disponibile
Poiché l'archiviazione esterna si trova su un volume fisico che l'utente potrebbe rimuovere, verificare che il volume sia accessibile prima di provare a leggere o scrivere dati specifici dell'app in una memoria esterna.
Puoi eseguire query sullo stato del volume richiamando
Environment.getExternalStorageState()
Se lo stato restituito è
MEDIA_MOUNTED
, poi
puoi leggere e scrivere file specifici delle app all'interno della memoria esterna. Se si tratta
MEDIA_MOUNTED_READ_ONLY
,
puoi solo leggere questi file.
Ad esempio, i seguenti metodi sono utili per determinare lo spazio di archiviazione disponibilità:
Kotlin
// Checks if a volume containing external storage is available // for read and write. fun isExternalStorageWritable(): Boolean { return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED } // Checks if a volume containing external storage is available to at least read. fun isExternalStorageReadable(): Boolean { return Environment.getExternalStorageState() in setOf(Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED_READ_ONLY) }
Java
// Checks if a volume containing external storage is available // for read and write. private boolean isExternalStorageWritable() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } // Checks if a volume containing external storage is available to at least read. private boolean isExternalStorageReadable() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) || Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY); }
Sui dispositivi senza memoria esterna rimovibile, usa il seguente comando per abilita un volume virtuale per testare la logica di disponibilità dello spazio di archiviazione esterno:
adb shell sm set-virtual-disk true
Seleziona una posizione di archiviazione fisica
A volte, un dispositivo che alloca una partizione della sua memoria interna come l'unità di archiviazione esterna fornisce anche uno slot per scheda SD. Ciò significa che il dispositivo più volumi fisici che potrebbero contenere unità di archiviazione esterna, quindi scegli quale usare per lo spazio di archiviazione specifico della tua app.
Per accedere alle diverse sedi, chiama
ContextCompat.getExternalFilesDirs()
Come mostrato nello snippet di codice, il primo elemento nell'array restituito è
è considerato il volume
di archiviazione esterna principale. Usa questo volume a meno che non sia pieno
o non disponibile.
Kotlin
val externalStorageVolumes: Array<out File> = ContextCompat.getExternalFilesDirs(applicationContext, null) val primaryExternalStorage = externalStorageVolumes[0]
Java
File[] externalStorageVolumes = ContextCompat.getExternalFilesDirs(getApplicationContext(), null); File primaryExternalStorage = externalStorageVolumes[0];
Accedi ai file permanenti
Per accedere ai file specifici delle app dallo spazio di archiviazione esterno, chiama
getExternalFilesDir()
Per mantenere le prestazioni della tua app, non aprire e chiudere lo stesso più volte.
Il seguente snippet di codice mostra come chiamare getExternalFilesDir()
:
Kotlin
val appSpecificExternalDir = File(context.getExternalFilesDir(null), filename)
Java
File appSpecificExternalDir = new File(context.getExternalFilesDir(null), filename);
Crea file cache
Per aggiungere un file specifico per un'app alla cache all'interno della memoria esterna, scarica un
riferimento ai
externalCacheDir
:
Kotlin
val externalCacheFile = File(context.externalCacheDir, filename)
Java
File externalCacheFile = new File(context.getExternalCacheDir(), filename);
Rimuovi file della cache
Per rimuovere un file dalla directory della cache esterna, utilizza la
delete()
su un oggetto File
che
rappresenta il file:
Kotlin
externalCacheFile.delete()
Java
externalCacheFile.delete();
Contenuti multimediali
Se la tua app funziona con file multimediali che forniscono valore all'utente solo all'interno dell'app, è meglio memorizzarli in directory specifiche dell'app all'interno come mostrato nello snippet di codice riportato di seguito:
Kotlin
fun getAppSpecificAlbumStorageDir(context: Context, albumName: String): File? { // Get the pictures directory that's inside the app-specific directory on // external storage. val file = File(context.getExternalFilesDir( Environment.DIRECTORY_PICTURES), albumName) if (!file?.mkdirs()) { Log.e(LOG_TAG, "Directory not created") } return file }
Java
@Nullable File getAppSpecificAlbumStorageDir(Context context, String albumName) { // Get the pictures directory that's inside the app-specific directory on // external storage. File file = new File(context.getExternalFilesDir( Environment.DIRECTORY_PICTURES), albumName); if (file == null || !file.mkdirs()) { Log.e(LOG_TAG, "Directory not created"); } return file; }
È importante utilizzare i nomi delle directory forniti da costanti API, come
DIRECTORY_PICTURES
Questi nomi di directory assicurano che i file vengano trattati correttamente dal sistema.
Se nessuna delle sottodirectory predefinite
personalizzati adatti ai tuoi file, puoi
passa null
in getExternalFilesDir()
. Questo restituisce la radice
alla directory specifica dell'app
nella memoria esterna.
Esegui query sullo spazio libero
Molti utenti non hanno molto spazio di archiviazione a disposizione sui propri dispositivi, quindi la tua app dovrebbero consumare lo spazio in modo ponderato.
Se conosci in anticipo quanti dati stai memorizzando, puoi scoprire come
la quantità di spazio che il dispositivo può fornire alla tua app chiamando
getAllocatableBytes()
Il valore restituito di getAllocatableBytes()
potrebbe essere maggiore dell'attuale valore
di spazio libero sul dispositivo. Questo perché il sistema ha identificato
file che può rimuovere da altre app della cache.
Se lo spazio è sufficiente per salvare i dati dell'app, chiama
allocateBytes()
Altrimenti, l'app può chiedere all'utente di rimuovere alcuni
file dal dispositivo o rimuovi tutta la cache
dal dispositivo.
Il seguente snippet di codice mostra un esempio di come la tua app può eseguire query sullo spazio libero sul dispositivo:
Kotlin
// App needs 10 MB within internal storage. const val NUM_BYTES_NEEDED_FOR_MY_APP = 1024 * 1024 * 10L; val storageManager = applicationContext.getSystemService<StorageManager>()!! val appSpecificInternalDirUuid: UUID = storageManager.getUuidForPath(filesDir) val availableBytes: Long = storageManager.getAllocatableBytes(appSpecificInternalDirUuid) if (availableBytes >= NUM_BYTES_NEEDED_FOR_MY_APP) { storageManager.allocateBytes( appSpecificInternalDirUuid, NUM_BYTES_NEEDED_FOR_MY_APP) } else { val storageIntent = Intent().apply { // To request that the user remove all app cache files instead, set // "action" to ACTION_CLEAR_APP_CACHE. action = ACTION_MANAGE_STORAGE } }
Java
// App needs 10 MB within internal storage. private static final long NUM_BYTES_NEEDED_FOR_MY_APP = 1024 * 1024 * 10L; StorageManager storageManager = getApplicationContext().getSystemService(StorageManager.class); UUID appSpecificInternalDirUuid = storageManager.getUuidForPath(getFilesDir()); long availableBytes = storageManager.getAllocatableBytes(appSpecificInternalDirUuid); if (availableBytes >= NUM_BYTES_NEEDED_FOR_MY_APP) { storageManager.allocateBytes( appSpecificInternalDirUuid, NUM_BYTES_NEEDED_FOR_MY_APP); } else { // To request that the user remove all app cache files instead, set // "action" to ACTION_CLEAR_APP_CACHE. Intent storageIntent = new Intent(); storageIntent.setAction(ACTION_MANAGE_STORAGE); }
Creare un'attività di gestione dello spazio di archiviazione
La tua app può dichiarare e creare un'attività personalizzata che, una volta avviata, consente
all'utente di gestire i dati che la tua app ha archiviato sul suo dispositivo. Tu
dichiara l'opzione "Gestisci spazio" personalizzata attività utilizzando
android:manageSpaceActivity
nel file manifest. Le app di gestione di file possono richiamare questo messaggio
attività
anche quando l'app non esporta l'attività. ovvero quando la tua attività imposta
Da android:exported
a
false
,
Chiedi all'utente di rimuovere alcuni file del dispositivo
Per richiedere all'utente di scegliere i file da rimuovere sul dispositivo, richiama un intent
che include
ACTION_MANAGE_STORAGE
un'azione. Questo intent mostra una richiesta all'utente. Se vuoi, questo prompt
mostrare la quantità di spazio libero disponibile sul dispositivo. Per mostrarlo
di facile utilizzo, utilizza il risultato del seguente calcolo:
StorageStatsManager.getFreeBytes() / StorageStatsManager.getTotalBytes()
Chiedi all'utente di rimuovere tutti i file della cache
In alternativa, puoi richiedere all'utente di cancellare i file della cache da tutti
di app installate sul dispositivo. A tale scopo, richiama un intent che includa la classe
ACTION_CLEAR_APP_CACHE
azione basata sull'intent.
Risorse aggiuntive
Per ulteriori informazioni sul salvataggio di file nello spazio di archiviazione del dispositivo, consulta la le seguenti risorse.