Auf App-spezifische Dateien zugreifen

Oft erstellt Ihre App Dateien, auf die andere Apps keinen Zugriff benötigen, oder nicht zugreifen darf. Das System stellt folgende Speicherorte zur Verfügung: app-spezifischen Dateien:

  • Interne Speicherverzeichnisse: Diese Verzeichnisse enthalten sowohl ein dediziertes Speicherort zum Speichern persistenter Dateien und weiterer Speicherort zum Speichern Daten im Cache zu speichern. Das System verhindert, dass andere Apps auf diese Standorte zugreifen. unter Android 10 (API-Level 29) und höher werden diese Standorte verschlüsselt. Diese Eigenschaften machen diese Standorte zu einem guten Ort für die Speicherung sensibler Daten, die auf die nur Ihre App selbst zugreifen kann.

  • Externe Speicherverzeichnisse: Diese Verzeichnisse enthalten sowohl ein dediziertes Speicherort zum Speichern persistenter Dateien und weiterer Speicherort zum Speichern Daten im Cache zu speichern. Es ist zwar möglich, dass eine andere App auf diese Verzeichnisse zugreifen kann, Wenn diese App die entsprechenden Berechtigungen hat, werden die in diesen Verzeichnissen gespeicherten Dateien nur für die Nutzung durch Ihre App bestimmt sind. Wenn Sie speziell Dateien erstellen möchten, auf die andere Apps zugreifen können sollen, sollte deine App diese Dateien in den Teil des freigegebenen Speichers des externen Speichers .

Wenn ein Nutzer deine App deinstalliert, werden die im App-spezifischen Speicher abgelegten Dateien entfernt. Deshalb sollten Sie diesen Speicher nicht verwenden, um alles, was der Nutzer erwartet, unabhängig von Ihrer App. Für Wenn Ihre App es Nutzenden ermöglicht, Fotos aufzunehmen, würde sie erwarten, dass kann er auch nach der Deinstallation deiner App auf diese Fotos zugreifen. Sie sollten sich also nutzen Sie stattdessen freigegebenen Speicher, um diese Dateitypen am entsprechenden Mediensammlung.

In den folgenden Abschnitten wird beschrieben, wie Sie Dateien in App-spezifischen Verzeichnissen.

Zugriff von internem Speicher

Für jede Anwendung stellt das System Verzeichnisse innerhalb des internen Speichers bereit, in denen ein App ihre Dateien organisieren kann. Ein Verzeichnis ist für die dauerhafte Dateien und eine andere enthält die im Cache gespeicherte Dateien. Deine App benötigt kein System Lese- und Schreibberechtigungen für Dateien in diesen Verzeichnissen.

Andere Apps können nicht auf Dateien im internen Speicher zugreifen. Dadurch wird internen Speicher ein guter Ort für App-Daten, auf die andere Apps nicht zugreifen sollten.

Denken Sie jedoch daran, dass diese Verzeichnisse in der Regel klein sind. Vor dem Schreiben App-spezifischen Dateien in den internen Speicher übertragen, sollte Ihre App den kostenlosen Speicherplatz auf dem Gerät.

Auf nichtflüchtige Dateien zugreifen

Die gewöhnlichen, persistenten Dateien Ihrer App befinden sich in einem Verzeichnis, das Sie Zugriff über die filesDir eines Kontextobjekts. Das Framework bietet mehrere Methoden, Dateien in diesem Verzeichnis öffnen und speichern.

Auf Dateien zugreifen und sie speichern

Mit der File API können Sie auf Dateien zugreifen und diese speichern.

Um die Leistung deiner App aufrechtzuerhalten, solltest du nicht die gleichen Elemente öffnen und schließen, zu wiederholen.

Das folgende Code-Snippet zeigt, wie die File API verwendet wird:

Kotlin

val file = File(context.filesDir, filename)

Java

File file = new File(context.getFilesDir(), filename);

Dateien mithilfe eines Streams speichern

Als Alternative zur Verwendung der File API können Sie auch openFileOutput() um ein FileOutputStream zu erhalten, in eine Datei im Verzeichnis filesDir.

Das folgende Code-Snippet zeigt, wie Text in eine Datei geschrieben wird:

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

So gestatten Sie anderen Apps den Zugriff auf Dateien, die in folgendem Verzeichnis gespeichert sind: dieses Verzeichnis innerhalb des internen Speichers, verwenden Sie FileProvider durch den FLAG_GRANT_READ_URI_PERMISSION .

Über einen Stream auf eine Datei zugreifen

Um eine Datei als Stream zu lesen, verwenden Sie 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();
}

Dateiliste ansehen

Sie können ein Array abrufen, das die Namen aller Dateien im filesDir enthält. durch Aufrufen von fileList(), wie in das folgende Code-Snippet:

Kotlin

var files: Array<String> = context.fileList()

Java

Array<String> files = context.fileList();

Verschachtelte Verzeichnisse erstellen

Sie können auch verschachtelte Verzeichnisse erstellen oder ein inneres Verzeichnis öffnen, indem Sie getDir() in Kotlin-basiert oder durch Übergabe des Stammverzeichnisses und eines neuen Verzeichnisnamens in File -Konstruktor in Java-basiertem Code:

Kotlin

context.getDir(dirName, Context.MODE_PRIVATE)

Java

File directory = context.getFilesDir();
File file = new File(directory, filename);

Cache-Dateien erstellen

Wenn Sie sensible Daten nur vorübergehend speichern müssen, sollten Sie die Funktion im internen Speicher festgelegtes Cache-Verzeichnis zum Speichern der Daten. Wie auch die für den gesamten App-spezifischen Speicher gilt, werden die in diesem Verzeichnis gespeicherten Dateien werden entfernt, wenn der Nutzer deine App deinstalliert. Die Dateien in diesem Verzeichnis werden möglicherweise früher entfernt.

Um eine im Cache gespeicherte Datei zu erstellen, rufen Sie File.createTempFile():

Kotlin

File.createTempFile(filename, null, context.cacheDir)

Java

File.createTempFile(filename, null, context.getCacheDir());

Ihre Anwendung greift mithilfe der Methode cacheDir-Eigenschaft eines Kontextobjekt und die File API:

Kotlin

val cacheFile = File(context.cacheDir, filename)

Java

File cacheFile = new File(context.getCacheDir(), filename);

Cache-Dateien entfernen

Auch wenn Android Cache-Dateien manchmal selbst löscht, sollten Sie sich nicht darauf verlassen, auf dem System, um diese Dateien für Sie zu bereinigen. Sie sollten Ihre die Cache-Dateien der App im internen Speicher.

Um eine Datei aus dem Cache-Verzeichnis im internen Speicher zu entfernen, verwenden Sie eine der die folgenden Methoden verwenden:

  • Die Methode delete() für ein File-Objekt für die Datei:

    Kotlin

    cacheFile.delete()
    

    Java

    cacheFile.delete();
    
  • Die deleteFile() -Methode des Anwendungskontexts, wobei der Name der Datei übergeben wird:

    Kotlin

    context.deleteFile(cacheFileName)
    

    Java

    context.deleteFile(cacheFileName);
    

Zugriff von externem Speicher

Wenn der interne Speicher nicht genügend Speicherplatz für App-spezifische Dateien bietet, sollten Sie stattdessen einen externen Speicher verwenden. Das System stellt Verzeichnisse innerhalb von Externer Speicher, in dem eine App Dateien organisieren kann, die dem Nutzer einen Mehrwert bieten nur innerhalb Ihrer App. Ein Verzeichnis ist für die persistente und eine weitere Datei enthält die im Cache gespeicherten Dateien.

Unter Android 4.4 (API-Level 19) oder höher muss Ihre App keine speicherbezogene Berechtigungen für den Zugriff auf anwendungsspezifische Verzeichnisse innerhalb externer Speicherplatz. Die in diesen Verzeichnissen gespeicherten Dateien werden entfernt, wenn Ihre Anwendung deinstalliert.

Auf Geräten mit Android 9 (API-Level 28) oder niedriger kann deine App auf die App-spezifische Dateien, die zu anderen Apps gehören. Voraussetzung ist, dass Ihre App die die entsprechenden Speicherberechtigungen haben. Um Nutzern mehr Kontrolle über ihre Dateien und werden Apps für Android 10 (API-Level 29) und höher beschränkter Zugriff auf externen Speicher oder begrenzter Zugriff Speicherplatz. Auf Ebene des Umfangs aktiviert ist, können Apps nicht auf die App-spezifischen Verzeichnisse zugreifen, auf andere Apps.

Prüfen, ob Speicherplatz verfügbar ist

Externer Speicher befindet sich auf einem physischen Volume, das der Nutzer möglicherweise entfernen können, prüfen Sie, ob das Volume zugänglich ist, bevor Sie versuchen, es zu lesen App-spezifische Daten aus einem externen Speicher abrufen oder anwendungsspezifische Daten in einen externen Speicher schreiben.

Sie können den Status des Volumes abfragen, indem Sie Environment.getExternalStorageState() Wenn der zurückgegebene Status MEDIA_MOUNTED, dann können Sie anwendungsspezifische Dateien im externen Speicher lesen und schreiben. Wenn es MEDIA_MOUNTED_READ_ONLY, können Sie diese Dateien nur lesen.

Die folgenden Methoden sind beispielsweise nützlich, um den Speicherbedarf zu ermitteln. Verfügbarkeit:

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

Auf Geräten ohne externen Wechseldatenträger können Sie mit dem folgenden Befehl Aktivieren Sie ein virtuelles Volume zum Testen der Verfügbarkeitslogik für externen Speicher:

adb shell sm set-virtual-disk true

Physischen Speicherort auswählen

Manchmal kann ein Gerät, das eine Partition seines internen Speichers hat das externe Speichergerät auch einen SD-Kartensteckplatz. Das bedeutet, dass das Gerät die externen Speicher enthalten könnten. Auswählen, welches für Ihren App-spezifischen Speicher verwendet werden soll.

Wenn Sie auf die verschiedenen Standorte zugreifen möchten, rufen Sie ContextCompat.getExternalFilesDirs() Wie im Code-Snippet gezeigt, ist das erste Element im zurückgegebenen Array als primäres externes Speicher-Volume. Diese Lautstärke nicht verwenden, es sei denn, sie ist voll oder nicht verfügbar sind.

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

Um auf appspezifische Dateien aus dem externen Speicher zuzugreifen, rufen Sie getExternalFilesDir()

Um die Leistung deiner App aufrechtzuerhalten, solltest du nicht die gleichen Elemente öffnen und schließen, zu wiederholen.

Das folgende Code-Snippet zeigt, wie getExternalFilesDir() aufgerufen wird:

Kotlin

val appSpecificExternalDir = File(context.getExternalFilesDir(null), filename)

Java

File appSpecificExternalDir = new File(context.getExternalFilesDir(null), filename);

Cache-Dateien erstellen

Um eine app-spezifische Datei zum Cache im externen Speicher hinzuzufügen, rufen Sie eine Verweis auf die externalCacheDir:

Kotlin

val externalCacheFile = File(context.externalCacheDir, filename)

Java

File externalCacheFile = new File(context.getExternalCacheDir(), filename);

Cache-Dateien entfernen

Um eine Datei aus dem externen Cache-Verzeichnis zu entfernen, verwenden Sie die Methode Methode delete() für ein File-Objekt, das steht für die Datei:

Kotlin

externalCacheFile.delete()

Java

externalCacheFile.delete();

Medieninhalte

Wenn Ihre App mit Mediendateien arbeitet, die für den Nutzer nur innerhalb speichern Sie sie am besten in App-spezifischen Verzeichnissen innerhalb 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;
}

Es ist wichtig, dass Sie Verzeichnisnamen verwenden, die von API-Konstanten bereitgestellt werden, z. B. DIRECTORY_PICTURES Diese Verzeichnisnamen stellen sicher, dass die Dateien vom System ordnungsgemäß behandelt werden. Wenn keines der vordefinierten Unterverzeichnisse Namen zu Ihren Dateien passen, können Sie übergeben Sie stattdessen null an getExternalFilesDir(). Dadurch wird der Stamm Anwendungsspezifisches Verzeichnis innerhalb des externen Speichers.

Freien Speicherplatz abfragen

Viele Nutzer haben auf ihren Geräten nicht viel Speicherplatz, sodass Ihre App umsichtig Platz einnehmen.

Wenn Sie im Voraus wissen, wie viele Daten Sie speichern, können Sie ermitteln, viel Speicherplatz, den das Gerät Ihrer App zur Verfügung stellen kann, indem Sie getAllocatableBytes() Der Rückgabewert von getAllocatableBytes() ist möglicherweise größer als der aktuelle Wert freien Speicherplatz auf dem Gerät. Das liegt daran, dass das System Dateien, die aus anderen Apps entfernt werden können Cache-Verzeichnisse.

Wenn genügend Speicherplatz vorhanden ist, um die App-Daten zu speichern, rufen Sie allocateBytes() Andernfalls kann Ihre App den Nutzer auffordern, einige davon zu entfernen Dateien vom Gerät aus oder entferne den gesamten Cache Dateien vom Gerät.

Das folgende Code-Snippet zeigt ein Beispiel dafür, wie Ihre App freien Speicherplatz abfragen kann auf dem Gerät:

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, Der Nutzer kann die Daten verwalten, die Ihre App auf dem Gerät des Nutzers gespeichert hat. Ich diesen benutzerdefinierten „Speicherplatz verwalten“ deklarieren mit dem android:manageSpaceActivity in der Manifestdatei. Dateimanager-Apps können diese Aktivität auch wenn Ihre App die Aktivitäten nicht exportiert; also wenn Ihre Aktivität android:exported bis false

Nutzer bitten, einige Gerätedateien zu entfernen

Wenn der Nutzer Dateien auf dem Gerät auswählen soll, die entfernt werden sollen, rufen Sie einen Intent auf mit dem ACTION_MANAGE_STORAGE Aktion ausführen. Mit diesem Intent wird dem Nutzer eine Aufforderung angezeigt. Bei Bedarf kann diese Aufforderung die Menge an freiem Speicherplatz anzuzeigen, die auf dem Gerät verfügbar ist. Zum Anzeigen verwenden Sie das Ergebnis der folgenden Berechnung:

StorageStatsManager.getFreeBytes() / StorageStatsManager.getTotalBytes()

Nutzer bitten, alle Cache-Dateien zu entfernen

Alternativ kannst du den Nutzer auffordern, die Cache-Dateien aus allen Apps auf dem Gerät. Rufen Sie dazu einen Intent auf, der den ACTION_CLEAR_APP_CACHE Intent-Aktion.

Weitere Informationen

Weitere Informationen zum Speichern von Dateien im Gerätespeicher findest du in der in den folgenden Ressourcen.

Videos