Hintergrund
Unter Android 4.4 (KitKat) hat Google den Zugriff auf die SD-Karte stark eingeschränkt.
Ab Android Lollipop (5.0) können Entwickler eine neue API verwenden, die den Benutzer auffordert, den Zugriff auf bestimmte Ordner zu bestätigen, wie in diesem Beitrag von Google-Groups beschrieben .
Das Problem
Der Beitrag weist Sie an, zwei Websites zu besuchen:
Dies sieht aus wie ein inneres Beispiel (das vielleicht später in den API-Demos gezeigt wird), aber es ist ziemlich schwer zu verstehen, was los ist.
Dies ist die offizielle Dokumentation der neuen API, enthält jedoch nicht genügend Details zur Verwendung.
Folgendes sagt es Ihnen:
Wenn Sie wirklich vollen Zugriff auf einen gesamten Teilbaum von Dokumenten benötigen, starten Sie zunächst ACTION_OPEN_DOCUMENT_TREE, damit der Benutzer ein Verzeichnis auswählen kann. Übergeben Sie dann die resultierenden getData () an fromTreeUri (Context, Uri), um mit dem vom Benutzer ausgewählten Baum zu arbeiten.
Wenn Sie im Baum der DocumentFile-Instanzen navigieren, können Sie immer getUri () verwenden, um den Uri abzurufen, der das zugrunde liegende Dokument für dieses Objekt darstellt, und um es mit openInputStream (Uri) usw. zu verwenden.
Um Ihren Code auf Geräten zu vereinfachen, auf denen KITKAT oder früher ausgeführt wird, können Sie fromFile (File) verwenden, das das Verhalten eines DocumentsProviders emuliert.
Die Fragen
Ich habe einige Fragen zur neuen API:
- Wie benutzt du es wirklich?
- Laut dem Beitrag wird sich das Betriebssystem daran erinnern, dass die App eine Berechtigung zum Zugriff auf die Dateien / Ordner erhalten hat. Wie überprüfen Sie, ob Sie auf die Dateien / Ordner zugreifen können? Gibt es eine Funktion, die mir die Liste der Dateien / Ordner zurückgibt, auf die ich zugreifen kann?
- Wie gehen Sie mit diesem Problem bei Kitkat um? Ist es ein Teil der Support-Bibliothek?
- Gibt es auf dem Betriebssystem einen Einstellungsbildschirm, auf dem angezeigt wird, welche Apps auf welche Dateien / Ordner zugreifen können?
- Was passiert, wenn eine App für mehrere Benutzer auf demselben Gerät installiert ist?
- Gibt es eine andere Dokumentation / ein anderes Tutorial zu dieser neuen API?
- Können die Berechtigungen widerrufen werden? Wenn ja, gibt es eine Absicht, die an die App gesendet wird?
- Würde das Anfordern der Berechtigung für einen ausgewählten Ordner rekursiv funktionieren?
- Würde die Verwendung der Berechtigung es dem Benutzer auch ermöglichen, nach Wahl des Benutzers eine Mehrfachauswahl zu treffen? Oder muss die App speziell angeben, welche Dateien / Ordner zugelassen werden sollen?
- Gibt es auf dem Emulator eine Möglichkeit, die neue API auszuprobieren? Ich meine, es hat eine SD-Kartenpartition, aber es funktioniert als primärer externer Speicher, sodass der gesamte Zugriff darauf bereits gewährt wird (mit einer einfachen Berechtigung).
- Was passiert, wenn der Benutzer die SD-Karte durch eine andere ersetzt?
quelle
Antworten:
Viele gute Fragen, lasst uns reingehen. :)
Wie benutzt man es?
Hier ist ein großartiges Tutorial für die Interaktion mit dem Storage Access Framework in KitKat:
https://developer.android.com/guide/topics/providers/document-provider.html#client
Die Interaktion mit den neuen APIs in Lollipop ist sehr ähnlich. Um den Benutzer zur Auswahl eines Verzeichnisbaums aufzufordern, können Sie eine Absicht wie die folgende starten:
Anschließend können Sie in Ihrem onActivityResult () die vom Benutzer ausgewählte Uri an die neue DocumentFile-Hilfsklasse übergeben. Hier ist ein kurzes Beispiel, in dem die Dateien im ausgewählten Verzeichnis aufgelistet und anschließend eine neue Datei erstellt werden:
Der von zurückgegebene Uri
DocumentFile.getUri()
ist flexibel genug, um mit möglicherweise verschiedenen Plattform-APIs verwendet zu werden. Zum Beispiel könnten Sie es mit teilenIntent.setData()
mitIntent.FLAG_GRANT_READ_URI_PERMISSION
.Wenn Sie über nativen Code auf diesen Uri zugreifen möchten, können Sie eine herkömmliche POSIX-Dateideskriptor-Ganzzahl aufrufen
ContentResolver.openFileDescriptor()
und dann verwendenParcelFileDescriptor.getFd()
oder abrufendetachFd()
.Wie überprüfen Sie, ob Sie auf die Dateien / Ordner zugreifen können?
Standardmäßig werden die über Storage Access Frameworks-Absichten zurückgegebenen Uris bei Neustarts nicht beibehalten. Die Plattform "bietet" die Möglichkeit, die Berechtigung beizubehalten, aber Sie müssen die Berechtigung trotzdem "nehmen", wenn Sie dies wünschen. In unserem obigen Beispiel würden Sie anrufen:
Sie können jederzeit über die
ContentResolver.getPersistedUriPermissions()
API herausfinden, auf welche dauerhaften Berechtigungen Ihre App Zugriff hat . Wenn Sie keinen Zugriff mehr auf einen dauerhaften Uri benötigen, können Sie ihn mit freigebenContentResolver.releasePersistableUriPermission()
.Ist das auf KitKat verfügbar?
Nein, wir können älteren Versionen der Plattform nicht rückwirkend neue Funktionen hinzufügen.
Kann ich sehen, welche Apps Zugriff auf Dateien / Ordner haben?
Derzeit gibt es keine Benutzeroberfläche, die dies anzeigt. Die Details finden Sie jedoch im Abschnitt "Erteilte Uri-Berechtigungen" der
adb shell dumpsys activity providers
Ausgabe.Was passiert, wenn eine App für mehrere Benutzer auf demselben Gerät installiert ist?
Uri-Berechtigungsgewährungen werden wie alle anderen Funktionen der Mehrbenutzerplattform auf Benutzerbasis isoliert. Das heißt, dieselbe App, die unter zwei verschiedenen Benutzern ausgeführt wird, hat keine überlappenden oder gemeinsam genutzten Uri-Berechtigungen.
Können die Berechtigungen widerrufen werden?
Der unterstützende DocumentProvider kann die Berechtigung jederzeit widerrufen, z. B. wenn ein Cloud-basiertes Dokument gelöscht wird. Der häufigste Weg, diese widerrufenen Berechtigungen zu ermitteln, besteht darin, dass sie aus den
ContentResolver.getPersistedUriPermissions()
oben genannten verschwinden .Berechtigungen werden auch widerrufen, wenn App-Daten für eine der an der Gewährung beteiligten Apps gelöscht werden.
Würde das Anfordern der Berechtigung für einen ausgewählten Ordner rekursiv funktionieren?
Ja, die
ACTION_OPEN_DOCUMENT_TREE
Absicht gibt Ihnen rekursiven Zugriff auf vorhandene und neu erstellte Dateien und Verzeichnisse.Ermöglicht dies eine Mehrfachauswahl?
Ja, seit KitKat wird die Mehrfachauswahl unterstützt, und Sie können dies zulassen, indem Sie
EXTRA_ALLOW_MULTIPLE
beim Starten IhrerACTION_OPEN_DOCUMENT
Absicht eine Einstellung vornehmen. Sie können die Dateitypen verwendenIntent.setType()
oderEXTRA_MIME_TYPES
eingrenzen, die ausgewählt werden können:http://developer.android.com/reference/android/content/Intent.html#ACTION_OPEN_DOCUMENT
Gibt es eine Möglichkeit für den Emulator, die neue API auszuprobieren?
Ja, das primäre gemeinsam genutzte Speichergerät sollte in der Auswahl angezeigt werden, auch auf dem Emulator. Wenn Ihre App nur das Storage Access Framework für den Zugriff auf gemeinsam genutzten Speicher verwendet, benötigen Sie die
READ/WRITE_EXTERNAL_STORAGE
Berechtigungen überhaupt nicht mehr und können sie entfernen oder dieandroid:maxSdkVersion
Funktion verwenden, um sie nur auf älteren Plattformversionen anzufordern.Was passiert, wenn der Benutzer die SD-Karte durch eine andere ersetzt?
Wenn es sich um physische Medien handelt, wird die UUID (z. B. die FAT-Seriennummer) der zugrunde liegenden Medien immer in den zurückgegebenen Uri gebrannt. Das System verwendet dies, um Sie mit dem Medium zu verbinden, das der Benutzer ursprünglich ausgewählt hat, selbst wenn der Benutzer das Medium zwischen mehreren Steckplätzen austauscht.
Wenn der Benutzer eine zweite Karte eintauscht, müssen Sie aufgefordert werden, auf die neue Karte zuzugreifen. Da sich das System Zuschüsse pro UUID merkt, haben Sie weiterhin Zugriff auf die Originalkarte, wenn der Benutzer sie später erneut einlegt.
http://en.wikipedia.org/wiki/Volume_serial_number
quelle
In meinem unten verlinkten Android-Projekt in Github finden Sie Arbeitscode, mit dem in Android 5 auf extSdCard geschrieben werden kann. Es wird davon ausgegangen, dass der Benutzer Zugriff auf die gesamte SD-Karte gewährt und Sie dann überall auf diese Karte schreiben können. (Wenn Sie nur auf einzelne Dateien zugreifen möchten, wird es einfacher.)
Hauptcode-Schnipsel
Auslösen des Storage Access Framework:
Behandeln der Antwort aus dem Storage Access Framework:
Abrufen eines outputStreams für eine Datei über das Storage Access Framework (unter Verwendung der gespeicherten URL, vorausgesetzt, dies ist die URL des Stammordners der externen SD-Karte)
Dies verwendet die folgenden Hilfsmethoden:
Verweis auf den vollständigen Code
https://github.com/jeisfeld/Augendiagnose/blob/master/AugendiagnoseIdea/augendiagnoseLib/src/main/java/de/jeisfeld/augendiagnoselib/fragments/SettingsFragment.java#L521
und
https://github.com/jeisfeld/Augendiagnose/blob/master/AugendiagnoseIdea/augendiagnoseLib/src/main/java/de/jeisfeld/augendiagnoselib/util/imagefile/FileUtil.java
quelle
File
254 mal verwendet. Können Sie sich vorstellen, das zu beheben? Android wird zu einem Albtraum für Entwickler, da es keine Abwärtskompatibilität gibt. Ich habe immer noch keinen Ort gefunden, an dem sie erklären, warum Google all diese dummen Entscheidungen bezüglich des externen Speichers getroffen hat. Einige behaupten "Sicherheit", aber das ist natürlich Unsinn, da jede App den internen Speicher durcheinander bringen kann. Ich vermute, wir müssen versuchen, ihre Cloud-Dienste zu nutzen. Zum Glück löst Rooting die Probleme ... zumindest für Android <6 ...Es ist nur eine ergänzende Antwort.
Nachdem Sie eine neue Datei erstellt haben, müssen Sie möglicherweise ihren Speicherort in Ihrer Datenbank speichern und morgen lesen. Mit dieser Methode können Sie lesen, wie Sie es erneut abrufen:
quelle