Damit Nutzer mehr Kontrolle über ihre Dateien haben und weniger Dateichaos entsteht, wurde mit Android 10 ein neues Speichermodell für Apps eingeführt, das als Scoped Storage bezeichnet wird. Durch die Änderungen am Scoped Storage wird die Art und Weise geändert, wie Apps Dateien im externen Speicher eines Geräts speichern und darauf zugreifen. Dieser Leitfaden enthält Best Practices für gängige Anwendungsfälle bei der Speichernutzung, die Ihnen bei der Migration Ihrer App zur Unterstützung von Scoped Storage helfen sollen. Die Anwendungsfälle sind in zwei Kategorien unterteilt: Mediadateien verarbeiten und Nicht-Mediadateien verarbeiten.
In vielen Fällen erstellt Ihre App Dateien, auf die andere Apps nicht zugreifen müssen oder sollten. Das System bietet app-spezifische Speicherorte zum Verwalten solcher Dateien.
Weitere Informationen zum Speichern und Zugreifen auf Dateien unter Android finden Sie in den Schulungsleitfäden zum Thema Speicher.
Mediendateien verarbeiten
In diesem Abschnitt werden einige gängige Anwendungsfälle für die Verarbeitung von Mediendateien (Video-, Bild- und Audiodateien) beschrieben und der allgemeine Ansatz erläutert, den Ihre App verwenden kann. In der folgenden Tabelle sind die einzelnen Anwendungsfälle zusammengefasst und es wird auf die Abschnitte mit weiteren Details verwiesen.
Anwendungsfall | Zusammenfassung |
---|---|
Alle Bild- oder Videodateien anzeigen | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
Bilder oder Videos aus einem bestimmten Ordner anzeigen | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
Auf Standortinformationen von Fotos zugreifen | Verwenden Sie einen Ansatz, wenn Ihre App den begrenzten Speicher verwendet. Wenn Ihre App den begrenzten Speicher nicht verwendet, müssen Sie einen anderen Ansatz wählen. |
Speicherort für neue Downloads festlegen | Verwenden Sie einen Ansatz, wenn Ihre App den begrenzten Speicher verwendet. Wenn Ihre App den begrenzten Speicher nicht verwendet, müssen Sie einen anderen Ansatz wählen. |
Medien eines Nutzers auf ein Gerät exportieren | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
Mehrere Media-Dateien in einem einzigen Vorgang ändern oder löschen | Verwenden Sie einen Ansatz für Android 11. Bei Android 10 können Sie die Verwendung von Scoped Storage deaktivieren und stattdessen den Ansatz für Android 9 und niedriger verwenden. |
Einzelnes vorhandenes Bild importieren | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
Einzelbild aufnehmen | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
Mediendateien mit anderen Apps teilen | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
Mediendateien mit einer bestimmten App teilen | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
Über Code oder Bibliotheken, die direkte Dateipfade verwenden, auf Dateien zugreifen | Verwenden Sie einen Ansatz für Android 11. Bei Android 10 können Sie die Verwendung von Scoped Storage deaktivieren und stattdessen den Ansatz für Android 9 und niedriger verwenden. |
Bild- oder Videodateien aus mehreren Ordnern anzeigen
Mediensammlung abfragen mit der query()
API. Wenn Sie die Media-Dateien filtern oder sortieren möchten, passen Sie die Parameter projection
, selection
, selectionArgs
und sortOrder
an.
Bilder oder Videos aus einem bestimmten Ordner anzeigen
So gehen Sie vor:
- Folgen Sie den Best Practices unter App-Berechtigungen anfordern und fordern Sie die Berechtigung
READ_EXTERNAL_STORAGE
an. - Ruft Mediendateien basierend auf dem Wert von
MediaColumns.DATA
ab, der den absoluten Dateisystempfad zum Media-Element auf der Festplatte enthält.
Hinweis:Wenn Sie auf eine vorhandene Media-Datei zugreifen, können Sie den Wert der Spalte DATA
in Ihrer Logik verwenden. Das liegt daran, dass dieser Wert einen gültigen Dateipfad hat.
Sie sollten jedoch nicht davon ausgehen, dass die Datei immer verfügbar ist. Sie müssen auf alle dateibasierten E/A-Fehler vorbereitet sein, die auftreten können.
Wenn Sie eine Media-Datei erstellen oder aktualisieren möchten, verwenden Sie die Spalte DATA
nicht. Verwenden Sie stattdessen die Spalten DISPLAY_NAME
und RELATIVE_PATH
.
Auf Standortinformationen von Fotos zugreifen
Wenn Ihre App den eingeschränkten Speicher verwendet, folgen Sie der Anleitung im Abschnitt Standortinformationen in Fotos des Leitfadens zum Speichern von Medien.
Speicherort für neue Downloads festlegen
Wenn Ihre App scoped storage verwendet, müssen Sie darauf achten, wo Sie heruntergeladene Mediendateien speichern.
Wenn andere Apps Zugriff auf Dateien benötigen, sollten Sie für Downloads oder Dokumentsammlungen gut definierte Mediensammlungen verwenden.
Unter Android 11 und höher können andere Apps nicht auf die Dateien in Ihrem externen app-spezifischen Verzeichnis zugreifen, auch wenn Sie DownloadManager
verwenden, um diese Dateien abzurufen.
Nutzer-Mediendateien auf ein Gerät exportieren
Legen Sie einen geeigneten Standardspeicherort für die Speicherung von Medieninhalten der Nutzer fest:
- Nutzern die Möglichkeit geben, mit app-spezifischem Speicher oder freigegebenem Speicher auszuwählen, ob ihre Mediadateien von anderen Apps gelesen werden dürfen.
- Nutzern erlauben, Dateien aus app-spezifischen Verzeichnissen an einen allgemeiner zugänglichen Speicherort zu exportieren. Verwenden Sie die Bild-, Video- und Audio-Sammlungen von MediaStore, um Mediendateien in die Galerie des Geräts zu exportieren.
Mehrere Media-Dateien in einem einzigen Vorgang ändern oder löschen
Integrieren Sie Logik basierend auf den Android-Versionen, auf denen Ihre App ausgeführt wird.
Android 11
So gehen Sie vor:
- Erstellen Sie mit
MediaStore.createWriteRequest()
oderMediaStore.createTrashRequest()
einen ausstehenden Intent für die Schreib- oder Löschanfrage Ihrer App und fordern Sie den Nutzer dann auf, die Berechtigung zum Bearbeiten einer Reihe von Dateien zu erteilen, indem Sie diesen Intent aufrufen. Antwort des Nutzers bewerten:
- Wenn die Berechtigung erteilt wurde, fahren Sie mit dem Änderungs- oder Löschvorgang fort.
- Wenn die Berechtigung nicht gewährt wurde, erklären Sie dem Nutzer, warum die Funktion in Ihrer App die Berechtigung benötigt.
Weitere Informationen zum Verwalten von Gruppen von Mediendateien mit diesen Methoden, die auf Android 11 und höher verfügbar sind
Unter Android 10
Wenn Ihre App auf Android 10 (API-Level 29) ausgerichtet ist, deaktivieren Sie die Verwendung von Storage mit beschränktem Zugriff und verwenden Sie weiterhin den Ansatz für Android 9 und niedriger, um diesen Vorgang auszuführen.
Android 9 oder niedriger
So gehen Sie vor:
- Folgen Sie den Best Practices unter App-Berechtigungen anfordern und fordern Sie die Berechtigung
WRITE_EXTERNAL_STORAGE
an. - Verwenden Sie die
MediaStore
API, um die Media-Dateien zu ändern oder zu löschen.
Einzelnes vorhandenes Bild importieren
Wenn Sie ein einzelnes Bild importieren möchten, das bereits vorhanden ist (z. B. um es als Profilbild eines Nutzers zu verwenden), kann Ihre App entweder ihre eigene Benutzeroberfläche für den Vorgang verwenden oder die Systemauswahl.
Eigene Benutzeroberfläche präsentieren
So gehen Sie vor:
- Folgen Sie den Best Practices unter App-Berechtigungen anfordern und fordern Sie die Berechtigung
READ_EXTERNAL_STORAGE
an. - Verwenden Sie die
query()
API, um eine Mediensammlung abzufragen. - Die Ergebnisse werden in der benutzerdefinierten Benutzeroberfläche Ihrer App angezeigt.
Systemauswahl verwenden
Verwenden Sie den Intent ACTION_GET_CONTENT
, mit dem der Nutzer aufgefordert wird, ein zu importierendes Bild auszuwählen.
Wenn Sie die Arten von Bildern filtern möchten, die in der Systemauswahl angezeigt werden, können Sie setType()
oder EXTRA_MIME_TYPES
verwenden.
Einzelnes Bild aufnehmen
Wenn Sie ein einzelnes Bild für Ihre App aufnehmen möchten, z. B. als Profilfoto eines Nutzers, verwenden Sie den Intent ACTION_IMAGE_CAPTURE
, um den Nutzer aufzufordern, mit der Kamera des Geräts ein Foto aufzunehmen. Das aufgenommene Foto wird in der Tabelle MediaStore.Images
gespeichert.
Mediendateien mit anderen Apps teilen
Verwenden Sie die Methode insert()
, um Datensätze direkt in den MediaStore einzufügen. Weitere Informationen finden Sie im Abschnitt Element hinzufügen des Leitfadens zum Speichern von Media.
Media-Dateien für eine bestimmte App freigeben
Verwenden Sie die Android-Komponente FileProvider
, wie im Leitfaden Dateifreigabe einrichten beschrieben.
Auf Dateien über Code oder Bibliotheken zugreifen, die direkte Dateipfade verwenden
Integrieren Sie Logik basierend auf den Android-Versionen, auf denen Ihre App ausgeführt wird.
Android 11
So gehen Sie vor:
- Folgen Sie den Best Practices unter App-Berechtigungen anfordern und fordern Sie die Berechtigung
READ_EXTERNAL_STORAGE
an. - Über direkte Dateipfade auf die Dateien zugreifen.
Weitere Informationen finden Sie im Abschnitt zum Öffnen von Mediendateien über direkte Dateipfade.
Unter Android 10
Wenn Ihre App auf Android 10 (API-Level 29) ausgerichtet ist, deaktivieren Sie die Verwendung von Storage mit beschränktem Zugriff und verwenden Sie weiterhin den Ansatz für Android 9 und niedriger, um diesen Vorgang auszuführen.
Android 9 oder niedriger
So gehen Sie vor:
- Folgen Sie den Best Practices unter App-Berechtigungen anfordern und fordern Sie die Berechtigung
WRITE_EXTERNAL_STORAGE
an. - Über direkte Dateipfade auf die Dateien zugreifen.
Nicht mediabezogene Dateien verarbeiten
In diesem Abschnitt werden einige der häufigsten Anwendungsfälle für die Verarbeitung von Nicht-Mediendateien beschrieben und der allgemeine Ansatz erläutert, den Ihre App verwenden kann. In der folgenden Tabelle werden die einzelnen Anwendungsfälle zusammengefasst und es wird auf die Abschnitte mit weiteren Details verwiesen.
Anwendungsfall | Zusammenfassung |
---|---|
Dokumentdatei öffnen | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
In Dateien auf sekundären Speichermedien schreiben | Verwenden Sie einen Ansatz für Android 11. Bei älteren Android-Versionen ist ein anderer Ansatz erforderlich. |
Bestehende Dateien von einem alten Speicherort migrieren | Migrieren Sie Ihre Dateien nach Möglichkeit zu Scoped Storage. Bei Bedarf können Sie die Funktion „Scoped Storage“ für Android 10 deaktivieren. |
Inhalte mit anderen Apps teilen | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
Nicht mediabezogene Dateien im Cache speichern | Verwenden Sie für alle Android-Versionen denselben Ansatz. |
Nicht mediabezogene Dateien auf ein Gerät exportieren | Verwenden Sie einen Ansatz, wenn Ihre App den begrenzten Speicher verwendet. Wenn Ihre App den begrenzten Speicher nicht verwendet, müssen Sie einen anderen Ansatz wählen. |
Dokumentdatei öffnen
Verwenden Sie den Intent ACTION_OPEN_DOCUMENT
, um den Nutzer aufzufordern, eine Datei auszuwählen, die mit der Systemauswahl geöffnet werden soll. Wenn Sie die Dateitypen filtern möchten, die in der Systemauswahl angezeigt werden, damit Nutzer eine Auswahl treffen können, können Sie setType()
oder EXTRA_MIME_TYPES
verwenden.
Mit dem folgenden Code können Sie beispielsweise alle PDF-, ODT- und TXT-Dateien finden:
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);
In Dateien auf sekundären Speichervolumes schreiben
Zu den sekundären Speichervolumes gehören SD-Karten. Mit der Klasse StorageVolume
können Sie auf Informationen zu einem bestimmten Speichervolume zugreifen.
Logik basierend auf der Android-Version, auf der Ihre App ausgeführt wird, einbinden
Android 11
So gehen Sie vor:
- Verwenden Sie das Modell Scoped Storage.
- auf Android 10 (API‑Level 29) oder niedriger ausgerichtet sein.
- Deklarieren Sie die Berechtigung
WRITE_EXTERNAL_STORAGE
. - Führen Sie einen der folgenden Zugriffe aus:
- Dateizugriff über die
MediaStore
API. - Direkter Zugriff auf Dateipfade über APIs wie
File
oderfopen()
.
- Dateizugriff über die
Auf älteren Versionen ausführen
Verwenden Sie das Storage Access Framework, mit dem Nutzer den Speicherort auf einem sekundären Speichermedium auswählen können, an dem Ihre App die Datei schreiben darf.
Bestehende Dateien von einem alten Speicherort migrieren
Ein Verzeichnis gilt als alter Speicherort, wenn es sich nicht um ein appspezifisches Verzeichnis oder ein öffentliches freigegebenes Verzeichnis handelt. Wenn Ihre App Dateien an einem alten Speicherort erstellt oder verwendet, empfehlen wir, die Dateien der App an Speicherorte zu migrieren, auf die mit dem eingeschränkten Speicher zugegriffen werden kann. Nehmen Sie außerdem alle erforderlichen Änderungen an der App vor, damit sie mit Dateien im eingeschränkten Speicher funktioniert.
Zugriff auf den alten Speicherort für die Datenmigration beibehalten
Ihre App muss weiterhin Zugriff auf den alten Speicherort haben, um alle App-Dateien zu Speicherorten zu migrieren, auf die mit dem eingeschränkten Speicher zugegriffen werden kann. Welche Methode Sie verwenden sollten, hängt vom Ziel-API-Level Ihrer App ab.
Wenn Ihre App auf Android 11 ausgerichtet ist
Setzen Sie das Flag
preserveLegacyExternalStorage
auftrue
, um das alte Speichermodell beizubehalten. So kann Ihre App die Daten eines Nutzers migrieren, wenn er auf die neue Version Ihrer App aktualisiert, die auf Android 11 ausgerichtet ist.Deaktivieren Sie weiterhin den eingeschränkten Speicher, damit Ihre App weiterhin auf Ihre Dateien am alten Speicherort auf Android 10-Geräten zugreifen kann.
Wenn Ihre App auf Android 10 ausgerichtet ist
Scoped Storage deaktivieren, um das Verhalten Ihrer App über verschiedene Android-Versionen hinweg einfacher beizubehalten.
App-Daten migrieren
Wenn Ihre App bereit für die Migration ist, gehen Sie so vor:
- Ausrichtung auf Android 10 oder niedriger
- Deaktivieren Sie den eingeschränkten Speicher, damit Ihre App auf die Dateien zugreifen kann, die Sie migrieren müssen.
-
Stellen Sie Code bereit, der die
File
API verwendet, um Dateien von ihrem aktuellen Speicherort unter/sdcard/
an einen Speicherort zu verschieben, der mit dem eingeschränkten Speicher zugänglich ist:- Verschieben Sie alle Dateien der privaten App in das Verzeichnis, das von der Methode
getExternalFilesDir()
zurückgegeben wird. - Verschieben Sie alle freigegebenen Nicht-Mediendateien in ein app-spezifisches Unterverzeichnis des Verzeichnisses
Downloads/
.
- Verschieben Sie alle Dateien der privaten App in das Verzeichnis, das von der Methode
- Entfernen Sie die alten Speicherverzeichnisse Ihrer App aus dem Verzeichnis
/sdcard/
.
Nachdem Nutzer die neue Version Ihrer App installiert haben, führen sie die Datenmigration auf ihren Geräten durch. Sie können den Migrationsprozess für alle Ihre Nutzer im Blick behalten, indem Sie ein Analyseereignis erstellen.
Nachdem Nutzer ihre Daten migriert haben, veröffentlichen Sie ein weiteres Update Ihrer App, das auf Android 11 ausgerichtet ist.
Inhalte mit anderen Apps teilen
Wenn Sie die Dateien Ihrer App für eine einzelne andere App freigeben möchten, verwenden Sie einen
FileProvider
. Für Apps, die alle Dateien untereinander austauschen müssen, empfehlen wir, für jede App einen Contentanbieter zu verwenden und die Daten dann zu synchronisieren, wenn Apps der Sammlung hinzugefügt werden.
Nicht mediabezogene Dateien im Cache speichern
Welche Vorgehensweise Sie verwenden sollten, hängt vom Typ der Dateien ab, die Sie im Cache speichern müssen.
- Kleine Dateien oder Dateien mit vertraulichen Informationen: Verwenden Sie
Context#getCacheDir()
. - Große Dateien oder Dateien, die keine vertraulichen Informationen enthalten: Verwenden Sie
Context#getExternalCacheDir()
.
Nicht mediabezogene Dateien auf ein Gerät exportieren
Legen Sie einen geeigneten Standardspeicherort für Nicht-Mediendateien fest. Nutzern erlauben, Dateien aus app-spezifischen Verzeichnissen an einen allgemeiner zugänglichen Speicherort zu exportieren. Verwenden Sie Downloads oder Dokumentensammlungen von MediaStore, um Nicht-Mediendateien auf das Gerät zu exportieren.
App-spezifische Dateien verarbeiten
Wenn Ihre App Dateien erstellt, auf die andere Apps nicht zugreifen müssen oder sollten, können Sie diese Dateien in app-spezifischen Speicherorten speichern.
Verzeichnisse im internen Speicher
Das System verhindert, dass andere Apps auf diese Speicherorte zugreifen. Unter Android 10 (API‑Level 29) und höher werden diese Speicherorte verschlüsselt. An diesen Speicherorten können Sie vertrauliche Daten speichern, auf die nur Ihre App zugreifen kann.
Externe Speicherverzeichnisse
Wenn der interne Speicher nicht genügend Speicherplatz für app-spezifische Dateien bietet, sollten Sie stattdessen den externen Speicher verwenden. 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.
Unter Android 4.4 (API-Level 19) oder höher muss Ihre App keine speicherbezogenen Berechtigungen anfordern, um auf appspezifische Verzeichnisse auf dem externen Speicher zuzugreifen.
Wenn der Nutzer Ihre App deinstalliert, werden die im appspezifischen Speicher gespeicherten Dateien entfernt. Sie sollten diesen Speicher daher nicht verwenden, um Inhalte zu speichern, die unabhängig von Ihrer App bestehen bleiben sollen.
Temporäres Deaktivieren von Scoped Storage
Bevor Ihre App vollständig mit dem eingeschränkten Speicher kompatibel ist, können Sie die Funktion vorübergehend deaktivieren, sowohl in Ihren Tests als auch in Ihrer Produktions-App.
Test deaktivieren
Unter Android 10 (API-Level 29) und höher werden die Tests Ihrer App standardmäßig in einer Speichersandbox ausgeführt. Diese Sandbox verhindert, dass Ihre App auf Dateien außerhalb des app-spezifischen Verzeichnisses und der öffentlich freigegebenen Verzeichnisse zugreift.
Wenn bei einem Test Dateien für den Host ausgegeben werden, z. B. Screenshots, Debugging-Daten, Abdeckungsdaten oder Leistungsmesswerte, können Sie diese Dateien in globale Verzeichnisse schreiben. Fügen Sie dazu dem entsprechenden Harness, der am instrument
aufruft, das folgende Flag hinzu:
-e no-isolated-storage 1
Dieses Flag wirkt sich auf das gesamte Verhalten des instrumentierten Testlaufs und auf den gesamten aufgerufenen Testcode aus. Wenn Sie dieses Flag verwenden, können Sie die Kompatibilität Ihrer App mit dem eingeschränkten Speicher nicht validieren. Für Testausgaben ist es besser, stattdessen in den App-bezogenen Speicher zu schreiben, der von der Shell gelesen werden kann. Anschließend können Sie das verzeichnisbezogene Verzeichnis abrufen. Rufen Sie getExternalMediaDirs()
auf, um zu ermitteln, aus welchem Verzeichnis die Daten abgerufen werden sollen.
Abmeldung in Ihrer Produktions-App
Wenn Ihre App auf Android 10 (API-Level 29) oder niedriger ausgerichtet ist, können Sie die Verwendung von Scoped Storage in Ihrer Produktions-App vorübergehend deaktivieren. Wenn Sie auf Android 10 ausgerichtet sind, müssen Sie in der Manifestdatei Ihrer App den Wert von requestLegacyExternalStorage
auf true
festlegen:
<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Wenn Sie testen möchten, wie sich eine App, die auf Android 10 oder niedriger ausgerichtet ist, bei Verwendung von Scoped Storage verhält, können Sie das Verhalten aktivieren, indem Sie den Wert von requestLegacyExternalStorage
auf false
setzen. Wenn Sie auf einem Gerät mit Android 11 testen, können Sie auch Flags zur App-Kompatibilität verwenden, um das Verhalten Ihrer App mit oder ohne eingeschränkten Speicher zu testen.
Zusätzliche Ressourcen
Weitere Informationen zum Android-Speicher finden Sie in den folgenden Materialien: