In vielen Fällen erstellt Ihre App Dateien, auf die andere Apps nicht zugreifen müssen oder sollten. Das System bietet die folgenden Speicherorte für solche app-spezifischen Dateien:
Verzeichnisse im internen Speicher:Diese Verzeichnisse umfassen sowohl einen dedizierten Speicherort für nichtflüchtige Dateien als auch einen weiteren Speicherort für Cache-Daten. Das System verhindert, dass andere Apps auf diese Speicherorte zugreifen. Unter Android 10 (API-Level 29) und höher sind diese Speicherorte verschlüsselt. Diese Eigenschaften machen diese Speicherorte zu einem guten Ort für vertrauliche Daten, auf die nur Ihre App selbst zugreifen kann.
Verzeichnisse im externen Speicher:Diese Verzeichnisse umfassen sowohl einen dedizierten Speicherort für nichtflüchtige Dateien als auch einen weiteren Speicherort für Cache-Daten. Obwohl eine andere App auf diese Verzeichnisse zugreifen kann , wenn sie die entsprechenden Berechtigungen hat, sind die in diesen Verzeichnissen gespeicherten Dateien nur für die Verwendung durch Ihre App vorgesehen. Wenn Sie speziell Dateien erstellen möchten , auf die andere Apps zugreifen können sollen, sollte Ihre App diese Dateien in dem freigegebenen Speicherbereich des externen Speichers speichern.
Wenn der Nutzer Ihre App deinstalliert, werden die in app-spezifischem Speicher gespeicherten Dateien entfernt. Aus diesem Grund sollten Sie diesen Speicher nicht verwenden, um etwas zu speichern, das unabhängig von Ihrer App bestehen bleiben soll. Wenn Ihre App beispielsweise Nutzern das Aufnehmen von Fotos ermöglicht, erwarten sie, dass sie auch nach der Deinstallation Ihrer App auf diese Fotos zugreifen können. Daher sollten Sie stattdessen freigegebenen Speicher verwenden, um diese Arten von Dateien in der entsprechenden Mediensammlungzu speichern.
In den folgenden Abschnitten wird beschrieben, wie Sie Dateien in app-spezifischen Verzeichnissen speichern und darauf zugreifen.
Zugriff über den internen Speicher
Für jede App stellt das System Verzeichnisse im internen Speicher bereit, in denen eine App ihre Dateien organisieren kann. Ein Verzeichnis ist für die nichtflüchtigen Dateien Ihrer App vorgesehen und ein anderes enthält die Cache-Dateien Ihrer App. Ihre App benötigt keine Systemberechtigungen, um Dateien in diesen Verzeichnissen zu lesen und zu schreiben.
Andere Apps können nicht auf Dateien zugreifen, die im internen Speicher gespeichert sind. Daher ist der interne Speicher ein guter Ort für App-Daten, auf die andere Apps nicht zugreifen sollten.
Beachten Sie jedoch, dass diese Verzeichnisse in der Regel klein sind. Bevor Ihre App app-spezifische Dateien in den internen Speicher schreibt, sollte sie den kostenlosen Speicherplatz auf dem Gerät abfragen.
Auf nichtflüchtige Dateien zugreifen
Die normalen, nichtflüchtigen Dateien Ihrer App befinden sich in einem Verzeichnis, auf das Sie mit der filesDir
Eigenschaft eines Kontextobjekts zugreifen können. Das Framework bietet mehrere Methoden, mit denen Sie auf Dateien in diesem Verzeichnis zugreifen und sie dort speichern können.
Auf Dateien zugreifen und sie speichern
Sie können die File API verwenden, um auf Dateien zuzugreifen und sie zu speichern.
Um die Leistung Ihrer App aufrechtzuerhalten, sollten Sie dieselbe Datei nicht mehrmals öffnen und schließen.
Das folgende Code-Snippet zeigt, wie Sie die File API verwenden:
Kotlin
val file = File(context.filesDir, filename)
Java
File file = new File(context.getFilesDir(), filename);
Datei mit einem Stream speichern
Alternativ zur Verwendung der File API können Sie
openFileOutput()
aufrufen, um einen FileOutputStream abzurufen, der
in eine Datei im Verzeichnis filesDir schreibt.
Das folgende Code-Snippet zeigt, wie Sie Text in eine Datei schreiben:
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()); }
Wenn Sie anderen Apps Zugriff auf Dateien gewähren möchten, die in diesem Verzeichnis im internen Speicher gespeichert sind, verwenden Sie einen FileProvider mit dem FLAG_GRANT_READ_URI_PERMISSION Attribut.
Auf eine Datei mit einem Stream zugreifen
Verwenden Sie
openFileInput(), um eine Datei als Stream zu lesen:
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(); }
Liste der Dateien ansehen
Sie können ein Array mit den Namen aller Dateien im filesDir
Verzeichnis abrufen, indem Sie
fileList() aufrufen, wie in
folgendem Code-Snippet gezeigt:
Kotlin
var files: Array<String> = context.fileList()
Java
Array<String> files = context.fileList();
Unterverzeichnisse erstellen
Sie können auch Unterverzeichnisse erstellen oder ein inneres Verzeichnis öffnen, indem Sie
getDir() in Kotlin-basiertem
Code aufrufen oder in Java-basiertem Code das Stammverzeichnis und einen neuen Verzeichnisnamen an einen File
Konstruktor übergeben:
Kotlin
context.getDir(dirName, Context.MODE_PRIVATE)
Java
File directory = context.getFilesDir(); File file = new File(directory, filename);
Cache-Dateien erstellen
Wenn Sie vertrauliche Daten nur vorübergehend speichern müssen, sollten Sie das dafür vorgesehene Cache-Verzeichnis der App im internen Speicher verwenden, um die Daten zu speichern. Wie bei allen app-spezifischen Speichern werden die in diesem Verzeichnis gespeicherten Dateien entfernt, wenn der Nutzer Ihre App deinstalliert. Die Dateien in diesem Verzeichnis werden jedoch möglicherweise früher entfernt.
Rufen Sie
File.createTempFile() auf, um eine Cache-Datei zu erstellen:
Kotlin
File.createTempFile(filename, null, context.cacheDir)
Java
File.createTempFile(filename, null, context.getCacheDir());
Ihre App greift mit der
cacheDir Eigenschaft eines
Kontextobjekts und der File API auf eine Datei in diesem Verzeichnis zu:
Kotlin
val cacheFile = File(context.cacheDir, filename)
Java
File cacheFile = new File(context.getCacheDir(), filename);
Cache-Dateien entfernen
Obwohl Android manchmal selbst Cache-Dateien löscht, sollten Sie sich nicht darauf verlassen, dass das System diese Dateien für Sie bereinigt. Sie sollten die Cache-Dateien Ihrer App immer im internen Speicher verwalten.
Verwenden Sie eine der folgenden Methoden, um eine Datei aus dem Cache-Verzeichnis im internen Speicher zu entfernen:
Die
delete()Methode für einFileObjekt das die Datei darstellt:Kotlin
cacheFile.delete()
Java
cacheFile.delete();
Die
deleteFile()Methode des App-Kontexts, wobei Sie den Namen der Datei übergeben:Kotlin
context.deleteFile(cacheFileName)
Java
context.deleteFile(cacheFileName);
Zugriff über den externen Speicher
Wenn der interne Speicher nicht genügend Platz für app-spezifische Dateien bietet, sollten Sie stattdessen den externen Speicher verwenden. Das System bietet Verzeichnisse im externen Speicher, in denen eine App Dateien organisieren kann, die für den Nutzer nur innerhalb Ihrer App von Nutzen sind. Ein Verzeichnis ist für die nichtflüchtigen Dateien Ihrer App vorgesehen und ein anderes enthält die Cache- Dateien Ihrer App.
Unter Android 4.4 (API-Level 19) oder höher muss Ihre App keine speicherbezogenen Berechtigungen anfordern, um auf app-spezifische Verzeichnisse im externen Speicher zuzugreifen. Die in diesen Verzeichnissen gespeicherten Dateien werden entfernt, wenn Ihre App deinstalliert wird.
Auf Geräten mit Android 9 (API-Level 28) oder niedriger kann Ihre App auf die app-spezifischen Dateien anderer Apps zugreifen, sofern Ihre App die entsprechenden Speicherberechtigungen hat. Um Nutzern mehr Kontrolle über ihre Dateien zu geben und die Dateiverwaltung zu vereinfachen, erhalten Apps, die auf Android 10 (API-Level 29) und höher ausgerichtet sind, standardmäßig eingeschränkten Zugriff auf den externen Speicher (begrenzter Speicher). Wenn der begrenzte Speicher aktiviert ist, können Apps nicht auf die app-spezifischen Verzeichnisse anderer Apps zugreifen.
Verfügbarkeit des Speichers prüfen
Da sich der externe Speicher auf einem physischen Volume befindet, das der Nutzer möglicherweise entfernen kann, prüfen Sie, ob das Volume zugänglich ist, bevor Sie versuchen, app-spezifische Daten aus dem externen Speicher zu lesen oder app-spezifische Daten in den externen Speicher zu schreiben.
Sie können den Status des Volumes abfragen, indem Sie
Environment.getExternalStorageState() aufrufen.
Wenn der zurückgegebene Status
MEDIA_MOUNTED ist, dann
können Sie app-spezifische Dateien im externen Speicher lesen und schreiben. Wenn der Status
MEDIA_MOUNTED_READ_ONLY,
ist, können Sie diese Dateien nur lesen.
Die folgenden Methoden sind beispielsweise nützlich, um die Speicherverfügbarkeit zu ermitteln:
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); }
Verwenden Sie auf Geräten ohne austauschbaren externen Speicher den folgenden Befehl, um ein virtuelles Volume zu aktivieren und die Logik für die Verfügbarkeit des externen Speichers zu testen:
adb shell sm set-virtual-disk true
Physischen Speicherort auswählen
Manchmal bietet ein Gerät, das eine Partition des internen Speichers als externen Speicher zuweist, auch einen SD-Kartensteckplatz. Das bedeutet, dass das Gerät mehrere physische Volumes hat, die externen Speicher enthalten können. Sie müssen also auswählen, welches Sie für den app-spezifischen Speicher verwenden möchten.
Rufen Sie
ContextCompat.getExternalFilesDirs() auf, um auf die verschiedenen Speicherorte zuzugreifen.
Wie im Code-Snippet gezeigt, wird das erste Element im zurückgegebenen Array als primäres externes Speichermedium betrachtet. Verwenden Sie dieses Volume, es sei denn, es ist voll oder nicht verfügbar.
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];
Auf nichtflüchtige Dateien zugreifen
Rufen Sie
getExternalFilesDir() auf, um auf app-spezifische Dateien im externen Speicher zuzugreifen.
Um die Leistung Ihrer App aufrechtzuerhalten, sollten Sie dieselbe Datei nicht mehrmals öffnen und schließen.
Das folgende Code-Snippet zeigt, wie Sie getExternalFilesDir() aufrufen:
Kotlin
val appSpecificExternalDir = File(context.getExternalFilesDir(null), filename)
Java
File appSpecificExternalDir = new File(context.getExternalFilesDir(null), filename);
Cache-Dateien erstellen
Wenn Sie dem Cache im externen Speicher eine app-spezifische Datei hinzufügen möchten, rufen Sie einen
Verweis auf den
externalCacheDir ab:
Kotlin
val externalCacheFile = File(context.externalCacheDir, filename)
Java
File externalCacheFile = new File(context.getExternalCacheDir(), filename);
Cache-Dateien entfernen
Verwenden Sie die
delete() Methode für ein File Objekt, das
die Datei darstellt, um eine Datei aus dem externen Cache-Verzeichnis zu entfernen:
Kotlin
externalCacheFile.delete()
Java
externalCacheFile.delete();
Medieninhalte
Wenn Ihre App mit Mediendateien arbeitet, die für den Nutzer nur innerhalb Ihrer App von Nutzen sind, sollten Sie sie in app-spezifischen Verzeichnissen im externen Speicher speichern, wie im folgenden Code-Snippet gezeigt:
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; }
Verwenden Sie unbedingt Verzeichnisnamen, die von API-Konstanten wie
DIRECTORY_PICTURES bereitgestellt werden.
Diese Verzeichnisnamen sorgen dafür, dass die Dateien vom System ordnungsgemäß behandelt werden.
Wenn keiner der vordefinierten Unterverzeichnis
namen zu Ihren Dateien passt, können Sie
stattdessen null an getExternalFilesDir() übergeben. Dadurch wird das app-spezifische Stammverzeichnis im externen Speicher zurückgegeben.
Freien Speicherplatz abfragen
Viele Nutzer haben nicht viel Speicherplatz auf ihren Geräten verfügbar. Ihre App sollte daher sparsam mit Speicherplatz umgehen.
Wenn Sie im Voraus wissen, wie viele Daten Sie speichern, können Sie mit
ermitteln, wie viel Speicherplatz das Gerät Ihrer App zur Verfügung stellen kann, indem Sie
getAllocatableBytes() aufrufen.
Der Rückgabewert von getAllocatableBytes() kann größer sein als der aktuelle kostenlose Speicherplatz auf dem Gerät. Das liegt daran, dass das System Dateien identifiziert hat, die aus den Cache-Verzeichnissen anderer Apps entfernt werden können.
Wenn genügend Speicherplatz zum Speichern der Daten Ihrer App vorhanden ist, rufen Sie
allocateBytes() auf.
Andernfalls kann Ihre App den Nutzer auffordern, einige
Dateien vom Gerät zu entfernen oder alle Cache-
Dateien vom Gerät zu entfernen.
Das folgende Code-Snippet zeigt ein Beispiel dafür, wie Ihre App den freien Speicherplatz auf dem Gerät abfragen kann:
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); }
Aktivität zur Speicherverwaltung erstellen
Ihre App kann eine benutzerdefinierte Aktivität deklarieren und erstellen, mit der der Nutzer die Daten verwalten kann, die Ihre App auf dem Gerät des Nutzers gespeichert hat. Sie
deklarieren diese benutzerdefinierte Aktivität zur Speicherverwaltung mit dem
android:manageSpaceActivity
Attribut in der Manifestdatei. Dateimanager-Apps können diese Aktivität auch dann aufrufen
, wenn Ihre App die Aktivität nicht exportiert, d. h. wenn für Ihre Aktivität
android:exported auf
false gesetzt ist.
Nutzer auffordern, einige Gerätedateien zu entfernen
Wenn Sie den Nutzer auffordern möchten, Dateien auf dem Gerät auszuwählen, die entfernt werden sollen, rufen Sie eine Intent
auf, die die
ACTION_MANAGE_STORAGE
Aktion enthält. Diese Intent zeigt dem Nutzer eine Aufforderung an. Bei Bedarf kann in dieser Aufforderung der auf dem Gerät verfügbare kostenlose Speicherplatz angezeigt werden. Verwenden Sie das Ergebnis der folgenden Berechnung, um diese nutzerfreundlichen Informationen anzuzeigen:
StorageStatsManager.getFreeBytes() / StorageStatsManager.getTotalBytes()
Nutzer auffordern, alle Cache-Dateien zu entfernen
Alternativ können Sie den Nutzer auffordern, die Cache-Dateien von allen Apps auf dem Gerät zu löschen. Rufen Sie dazu eine Intent auf, die die
ACTION_CLEAR_APP_CACHE
Intent-Aktion enthält.
ACTION_CLEAR_APP_CACHE
Zusätzliche Ressourcen
Weitere Informationen zum Speichern von Dateien im Speicher des Geräts finden Sie in den folgenden Ressourcen.