Gibt es eine universelle Möglichkeit, den Speicherort einer externen SD-Karte zu ermitteln?
Bitte nicht mit externem Speicher verwechseln .
Environment.getExternalStorageState()
Gibt den Pfad zum internen SD-Mount-Punkt zurück, z. B. "/ mnt / sdcard". Die Frage betrifft jedoch die externe SD. Wie erhalte ich einen Pfad wie "/ mnt / sdcard / external_sd" (dieser kann von Gerät zu Gerät unterschiedlich sein)?
Ich denke, ich werde mit dem Filtern der Ausgabe des mount
Befehls nach dem Namen des Dateisystems enden . Aber ich bin mir nicht sicher, ob dieser Weg robust genug ist.
Antworten:
Nein,
Environment.getExternalStorageDirectory()
bezieht sich auf alles, was der Gerätehersteller als "externen Speicher" betrachtet. Bei einigen Geräten handelt es sich um Wechselmedien wie eine SD-Karte. Bei einigen Geräten ist dies ein Teil des Flashs auf dem Gerät. Hier bedeutet "externer Speicher" "das Material, auf das über den USB-Massenspeichermodus zugegriffen werden kann, wenn es auf einem Host-Computer bereitgestellt wird", zumindest für Android 1.x und 2.x.Android hat kein Konzept für "externe SD", abgesehen von externem Speicher, wie oben beschrieben.
Wenn sich ein Gerätehersteller dafür entschieden hat, dass externer Speicher ein integrierter Flash-Speicher ist und auch über eine SD-Karte verfügt, müssen Sie sich an diesen Hersteller wenden, um festzustellen, ob Sie die SD-Karte verwenden können (nicht garantiert) und welche Regeln gelten Verwenden Sie es, z. B. welchen Pfad Sie dafür verwenden möchten.
AKTUALISIEREN
Zwei neue wichtige Dinge:
Erstens haben Sie unter Android 4.4+ keinen Schreibzugriff auf Wechselmedien (z. B. "externe SD"), mit Ausnahme von Speicherorten auf diesen Medien, die möglicherweise von
getExternalFilesDirs()
und zurückgegeben werdengetExternalCacheDirs()
. Siehe Dave Smiths ausgezeichnete Analyse an, insbesondere wenn Sie Details auf niedriger Ebene wünschen.Zweitens, damit sich niemand darüber streiten kann, ob der Zugriff auf Wechselmedien ansonsten Teil des Android SDK ist oder nicht, hier die Einschätzung von Dianne Hackborn :
quelle
Ich habe die folgende Lösung basierend auf einigen hier gefundenen Antworten gefunden.
CODE:
VERWENDUNG:
quelle
Ich hatte eine Anwendung, die einen Ort verwendete, an
ListPreference
dem der Benutzer den Ort auswählen musste, an dem er etwas speichern wollte.In dieser App habe ich gescannt
/proc/mounts
und/system/etc/vold.fstab
nach SD-Karten-Mount-Punkten gesucht. Ich habe die Mount-Punkte aus jeder Datei in zwei separatenArrayList
s gespeichert .Dann habe ich eine Liste mit der anderen verglichen und Elemente verworfen, die nicht in beiden Listen enthalten waren. Das gab mir eine Liste von Root-Pfaden zu jeder SD-Karte.
Von dort testete ich die Wege mit
File.exists()
,File.isDirectory()
undFile.canWrite()
. Wenn einer dieser Tests falsch war, habe ich diesen Pfad aus der Liste gestrichen.Was auch immer in der Liste übrig war, ich habe es in ein
String[]
Array konvertiert, damit es vomListPreference
Attribut values verwendet werden kann.Sie können den Code hier anzeigen: http://sapienmobile.com/?p=204
quelle
Sie können versuchen, die Support-Bibliotheksfunktion ContextCompat.getExternalFilesDirs () zu verwenden :
Der erste ist der primäre externe Speicher, und der Rest sollen echte SD-Kartenpfade sein.
Der Grund für das mehrfache ".getParentFile ()" besteht darin, einen anderen Ordner aufzurufen, da der ursprüngliche Pfad lautet
BEARBEITEN: Hier ist eine umfassendere Methode, die ich erstellt habe, um die SD-Karten-Pfade zu erhalten:
quelle
App
,ContextCompact
,EnvironmentCompact
Um alle externen Speicher abzurufen (unabhängig davon, ob es sich um SD-Karten oder interne nicht entfernbare Speicher handelt ), können Sie den folgenden Code verwenden:
Alternativ können Sie System.getenv ("EXTERNAL_STORAGE") verwenden , um das primäre externe Speicherverzeichnis (z. B. "/ storage / sdcard0" ) abzurufen, und System.getenv ("SECONDARY_STORAGE") , um die Liste aller sekundären Verzeichnisse (z. B. " / storage / extSdCard: / storage / UsbDriveA: / storage / UsbDriveB " ). Denken Sie daran, dass Sie auch in diesem Fall die Liste der sekundären Verzeichnisse filtern möchten, um die USB-Laufwerke auszuschließen.
Bitte beachten Sie auf jeden Fall, dass die Verwendung fest codierter Pfade immer ein schlechter Ansatz ist (insbesondere, wenn jeder Hersteller dies nach Belieben ändern kann).
quelle
System.getenv("SECONDARY_STORAGE")
könnte auch einige Referenzen vertragen, da er nicht dokumentiert zu sein scheint./mnt
SD-Karten nicht sicher bin, ist, dass es auch verschiedene andere Fs-Bäume geben kann, nicht nur SD-Karten und USB-Laufwerke. Ihr Code würde auch alle internen (vielleicht sogar virtuellen) Dateisystem-Mounts auflisten, wenn ich es richtig verstehe, während die Frage nur SD-Karten will .Wie Richard verwende ich auch die Datei / proc / mounts , um die Liste der verfügbaren Speicheroptionen abzurufen
quelle
printStackTrace
? Wann haben wirandroid.util.Log.e
?Es ist möglich herauszufinden, wo zusätzliche SD-Karten eingelegt sind, indem Sie
/proc/mounts
(Standard-Linux-Datei) lesen und mit vold data (/system/etc/vold.conf
) abgleichen . Beachten Sie außerdem, dass der von zurückgegebene SpeicherortEnvironment.getExternalStorageDirectory()
möglicherweise nicht in der Vold-Konfiguration angezeigt wird (bei einigen Geräten kann der interne Speicher nicht abgemeldet werden), muss jedoch weiterhin in die Liste aufgenommen werden. Wir haben jedoch keine gute Möglichkeit gefunden, sie dem Benutzer zu beschreiben .quelle
mount
kompatibler als das Lesen des/proc
Dateisystems. Das Problem ist, dass die SD-Karte nicht unbedingt als FAT formatiert sein muss. Der Kartenmontagepunkt kann auch von ROM zu ROM variieren. Es könnte auch mehrere andere VFAT-Partitionen geben ...mount
ausführbaren Datei, insbesondere da das Starten von ausführbaren Dateien nicht empfohlen wird.Ich versuche diesmal alle Lösungen in diesem Thema. Auf Geräten mit einer externen (entfernbaren) und einer internen (nicht entfernbaren) Karte funktionierten jedoch nicht alle ordnungsgemäß. Pfad der externen Karte nicht möglich vom Befehl 'mount', von der Datei 'proc / mounts' usw.
Und ich erstelle meine eigene Lösung (bei Paulo Luan):
quelle
Wenn Sie sich den Quellcode
android.os.Environment
ansehen, werden Sie feststellen, dass Android in hohem Maße auf Umgebungsvariablen für Pfade angewiesen ist. Sie können die Umgebungsvariable "SECONDARY_STORAGE" verwenden, um den Pfad zur entfernbaren SD-Karte zu finden.Anwendungsbeispiel:
quelle
Verwenden Sie einfach dies:
quelle
SECONDARY_STORAGE
sind mehrere Pfade durch einen Doppelpunkt (":") getrennt. Deshalb habe ich den String geteilt (siehe meine Antwort oben).Auf universelle Weise , wenn Sie offiziellen Weg meinen; ja es gibt eins.
In API - Ebene 19 , dh in Android - Version 4.4 Kitkat, haben sie aufgenommen
File[] getExternalFilesDirs (String type)
inContext
der Klasse , die Anwendungen zum Speichern von Daten / Dateien in Micro - SD - Karten ermöglicht.Android 4.4 ist die erste Version der Plattform, mit der Apps SD-Karten als Speicher verwenden können. Jeder Zugriff auf SD-Karten vor API-Stufe 19 erfolgte über private, nicht unterstützte APIs.
getExternalFilesDirs (String-Typ) gibt absolute Pfade zu anwendungsspezifischen Verzeichnissen auf allen gemeinsam genutzten / externen Speichergeräten zurück. Dies bedeutet, dass Pfade sowohl zum internen als auch zum externen Speicher zurückgegeben werden. Im Allgemeinen ist der zweite zurückgegebene Pfad der Speicherpfad für die microSD-Karte (falls vorhanden).
Beachten Sie jedoch, dass
Die Terminologie für internen und externen Speicher gemäß Google / offiziellen Android-Dokumenten unterscheidet sich erheblich von unserer Meinung.
quelle
getExternalFilesDirs()
Gibt häufig SD-Karten zurück, die nicht austauschbar sind. Nein, dies ist keine universelle Methode, um den Speicherort einer austauschbaren SD-Karte zu ermitteln.Hier ist die Art und Weise, wie ich die externe Karte finde. Verwenden Sie mount cmd return und analysieren Sie dann den vfat-Teil.
quelle
Diese Lösung behandelt die Tatsache, dass
System.getenv("SECONDARY_STORAGE")
Marshmallow keinen Nutzen hat.Getestet und bearbeitet an:
Samsung Galaxy Tab A (Android 6.0.1 - Lager)
quelle
Seit meiner ursprünglichen Antwort oben ist das Scannen von Vold bei den verschiedenen Herstellern nicht mehr möglich.
Ich habe eine zuverlässigere und einfachere Methode entwickelt.
Roots enthalten alle beschreibbaren Root-Verzeichnisse auf dem System, einschließlich aller über USB verbundenen USB-Geräte.
HINWEIS: Die canWrite-Methode benötigt die Berechtigung android.permission.WRITE_EXTERNAL_STORAGE.
quelle
/external_sd
die externe microSD-Karte ist; bei einigen LGs ist es/_ExternalSD
; auf einigen Geräten ist es/sdcard
. Vielleicht ist letzteres ein Symlink zu/storage/sdcard0
oder ähnlich, aber werden diese anderen wirklich zuverlässig von/storage/*
und abgedeckt/mount/*
?pathname.canWrite()
Ist es auch erforderlich, die Berechtigung WRITE_EXTERNAL_STORAGE zu verwenden und zu benötigen? Warum nicht einfach anrufenpathname.canRead()
?Es war so spät, aber endlich habe ich etwas bekommen, das ich bei den meisten Geräten (nach Hersteller- und Android-Versionen) getestet habe. Es funktioniert unter Android 2.2+. Wenn Sie feststellen, dass es nicht funktioniert, kommentieren Sie es mit Ihrem Gerätenamen. ich werde es reparieren. Wenn jemand interessiert ist, werde ich erklären, wie es funktioniert.
quelle
Wenn Sie den folgenden Code schreiben, erhalten Sie den Speicherort:
/ storage / 663D-554E / Android / data / app_package_name / files /
Hier werden Ihre App-Daten unter / android / data in der SD-Karte gespeichert.
Ich habe diesen Code auf einem Moto G4 Plus und einem Samsung-Gerät getestet (alles funktioniert einwandfrei).
hoffe das könnte hilfreich sein.
quelle
Hier ist die Methode, mit der ich eine entfernbare finde SD-Karte . Es ist komplex und in einigen Situationen wahrscheinlich übertrieben, aber es funktioniert mit einer Vielzahl von Android-Versionen und Geräteherstellern, die ich in den letzten Jahren getestet habe. Ich kenne keine Geräte seit API-Level 15, auf denen die SD-Karte nicht gefunden wird, wenn eine gemountet ist. In den meisten Fällen werden keine Fehlalarme zurückgegeben, insbesondere wenn Sie den Namen einer bekannten Datei angeben, nach der gesucht werden soll.
Bitte lassen Sie mich wissen, wenn Sie auf Fälle stoßen, in denen es nicht funktioniert.
PS
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
im Manifest. Stellen Sie auf API-Ebene 23 und höher sicher, dass Sie verwendencheckSelfPermission
/ verwendenrequestPermissions
.findSdCardPath(),
Natürlich anstatt ihn jedes Mal neu zu berechnen, wenn Sie ihn benötigen.Log.d()
obige Code enthält eine Reihe von logging ( ). Es hilft bei der Diagnose von Fällen, in denen der richtige Pfad nicht gefunden wurde. Kommentieren Sie es aus, wenn Sie keine Protokollierung wünschen.quelle
Die einzige funktionierende Lösung, die ich gefunden habe, war diese, die Reflexion verwendet
quelle
Ich weiß nicht warum, aber ich muss .createNewFile () für eine Datei aufrufen, die in den öffentlichen Speicherverzeichnissen erstellt wurde, bevor ich sie verwenden kann. Im Rahmen sagen die Kommentare für diese Methode, dass es nicht nützlich ist. Hier ist ein Beispiel ...
quelle
Ich habe eine Utils-Methode erstellt, um zu überprüfen, ob eine SD-Karte auf dem Gerät verfügbar ist oder nicht, und um den SD-Kartenpfad auf dem Gerät abzurufen, falls verfügbar.
Sie können zwei Methoden unten in die Klasse Ihres Projekts kopieren, die Sie benötigen. Das ist alles.
quelle
Es funktioniert für alle externen Geräte. Stellen Sie jedoch sicher, dass Sie nur den Namen des externen Geräteordners abrufen. Anschließend müssen Sie die Datei mithilfe der Dateiklasse von einem bestimmten Speicherort abrufen.
Berufung:
Zugriff auf externen Speicher
Um Dateien auf dem externen Speicher lesen oder schreiben zu können, muss Ihre App die Systemberechtigungen READ_EXTERNAL_STORAGE oder WRITE_EXTERNAL_STORAGE erwerben . Beispielsweise:
quelle
/ sdcard => Interner Speicher (Es ist ein Symlink, sollte aber funktionieren)
/ mnt / extSdCard => Externe SD-Karte
Dies ist für Samsung Galaxy S3
Sie können sich wahrscheinlich darauf verlassen, dass dies für die meisten gilt ... überprüfen Sie es jedoch noch einmal!
quelle
/sdcard
ist ein Symlink zu extern auf meinem Sony 2305.