Czy istnieje uniwersalny sposób na znalezienie lokalizacji zewnętrznej karty SD?
Proszę nie mylić z pamięcią zewnętrzną .
Environment.getExternalStorageState()
zwraca ścieżkę do wewnętrznego punktu montowania SD, na przykład „/ mnt / sdcard”. Ale pytanie dotyczy zewnętrznego SD. Jak uzyskać ścieżkę typu „/ mnt / sdcard / external_sd” (może się różnić w zależności od urządzenia)?
Myślę, że skończę z filtrowaniem danych wyjściowych mount
polecenia według nazwy systemu plików. Ale nie jestem pewien, czy ten sposób jest wystarczająco solidny.
Odpowiedzi:
Nie,
Environment.getExternalStorageDirectory()
odnosi się do wszystkiego, co producent urządzenia uznał za „pamięć zewnętrzną”. Na niektórych urządzeniach są to nośniki wymienne, takie jak karta SD. W niektórych urządzeniach jest to część pamięci flash na urządzeniu. Tutaj „pamięć zewnętrzna” oznacza „rzeczy dostępne w trybie pamięci masowej USB po zamontowaniu na komputerze hosta”, przynajmniej dla Androida 1.xi 2.x.Android nie ma pojęcia „zewnętrznego SD” poza pamięcią zewnętrzną, jak opisano powyżej.
Jeśli producent urządzenia wybrał, aby pamięć zewnętrzna była wbudowaną pamięcią flash, a także ma kartę SD, musisz skontaktować się z tym producentem, aby ustalić, czy możesz użyć karty SD (nie jest to gwarantowane) i jakie są zasady używając go, np. jakiej ścieżki użyć do tego.
AKTUALIZACJA
Dwie ważne rzeczy:
Po pierwsze, w Androidzie 4.4+ nie masz dostępu do zapisu na nośnikach wymiennych (np. „Zewnętrznej karcie SD”), z wyjątkiem miejsc na tych nośnikach, które mogą zostać zwrócone przez
getExternalFilesDirs()
igetExternalCacheDirs()
. Zobacz doskonałą analizę Dave'a Smitha ten temat, szczególnie jeśli potrzebujesz szczegółów niskiego poziomu.Po drugie, aby nikt nie miał wątpliwości, czy dostęp do nośników wymiennych jest w inny sposób częścią zestawu SDK systemu Android, oto ocena Dianne Hackborn :
źródło
Wymyśliłem następujące rozwiązanie w oparciu o niektóre odpowiedzi tutaj.
KOD:
STOSOWANIE:
źródło
Miałem aplikację, w
ListPreference
której użytkownik musiał wybrać lokalizację, w której chciał coś zapisać.W tej aplikacji skanowałem
/proc/mounts
i szukałem/system/etc/vold.fstab
punktów montowania sdcard. Przechowałem punkty montowania z każdego pliku w dwóch osobnychArrayList
.Następnie porównałem jedną listę z pozostałymi i odrzuconymi elementami, których nie było na obu listach. To dało mi listę ścieżek głównych do każdej karty SD.
Stamtąd, ja testowałem ścieżek
File.exists()
,File.isDirectory()
iFile.canWrite()
. Jeśli którykolwiek z tych testów był fałszywy, odrzuciłem tę ścieżkę z listy.Cokolwiek pozostało na liście, przekonwertowałem na
String[]
tablicę, aby mogła zostać wykorzystana przezListPreference
atrybut wartości.Możesz zobaczyć kod tutaj: http://sapienmobile.com/?p=204
źródło
Możesz spróbować użyć funkcji biblioteki pomocniczej o nazwie ContextCompat.getExternalFilesDirs () :
Pierwszy to podstawowa pamięć zewnętrzna, a reszta to prawdziwe ścieżki kart SD.
Powodem wielu „.getParentFile ()” jest przejście do innego folderu, ponieważ pierwotna ścieżka to
EDYCJA: oto bardziej wszechstronny sposób, który stworzyłem, aby uzyskać ścieżki kart SD:
źródło
App
,ContextCompact
,EnvironmentCompact
Aby odzyskać wszystkie zewnętrzne magazyny (bez względu na to, czy są to karty SD, czy wewnętrzne nieusuwalne magazyny ), możesz użyć następującego kodu:
Alternatywnie możesz użyć System.getenv („EXTERNAL_STORAGE”), aby pobrać główny katalog zewnętrznej pamięci masowej (np. „/ Storage / sdcard0” ) i System.getenv („SECONDARY_STORAGE”), aby pobrać listę wszystkich katalogów dodatkowych (np. „ / storage / extSdCard: / storage / UsbDriveA: / storage / UsbDriveB ” ). Pamiętaj, że również w tym przypadku możesz przefiltrować listę katalogów dodatkowych, aby wykluczyć dyski USB.
W każdym razie należy pamiętać, że korzystanie ze ścieżek zakodowanych na stałe jest zawsze złym podejściem (szczególnie, gdy każdy producent może to zmienić z zadowoleniem).
źródło
System.getenv("SECONDARY_STORAGE")
może również dotyczyć niektórych odniesień, ponieważ wydaje się nieudokumentowana./mnt
kart SD, miałem na myśli to, że mogą tam być także inne drzewa fs, nie tylko karty SD i napędy USB. Twój kod wyświetlałby również informacje o wszelkich montowaniach wewnętrznych (być może nawet wirtualnych) systemów plików, jeśli dobrze to rozumiem, podczas gdy pytanie dotyczy tylko kart SD .Podobnie jak Richard, używam również pliku / proc / mounts , aby uzyskać listę dostępnych opcji przechowywania
źródło
printStackTrace
? Gdy mamyandroid.util.Log.e
?Gdzie można zamontować dodatkowe karty SD, można dowiedzieć się, odczytując
/proc/mounts
(standardowy plik Linux) i porównując dane z voldem (/system/etc/vold.conf
). I zwróć uwagę, że zwrócona lokalizacjaEnvironment.getExternalStorageDirectory()
może nie pojawić się w konfiguracji Vold (na niektórych urządzeniach jest to pamięć wewnętrzna, której nie można odmontować), ale nadal musi zostać uwzględniona na liście. Nie znaleźliśmy jednak dobrego sposobu na opisanie ich użytkownikowi .źródło
mount
jest bardziej kompatybilne niż czytanie/proc
systemu plików. Problem polega na tym, że karta SD nie musi być sformatowana jako FAT. Ponadto punkt montowania karty może się różnić w zależności od ROM. Ponadto może istnieć kilka innych partycji VFAT ...mount
pliku wykonywalnego, zwłaszcza, że odradza się uruchamianie plików wykonywalnych.Tym razem wypróbowuję wszystkie rozwiązania zawarte w tym temacie. Ale wszystkie z nich nie działały poprawnie na urządzeniach z jedną kartą zewnętrzną (wymienną) i jedną wewnętrzną (niewymienną). Ścieżka karty zewnętrznej jest niemożliwa do uzyskania z polecenia „mount”, z pliku „proc / mounts” itp.
I tworzę własne rozwiązanie (na temat Paulo Luana):
źródło
Jeśli spojrzysz na kod źródłowy
android.os.Environment
, zobaczysz, że Android w dużym stopniu opiera się na zmiennych środowiskowych dla ścieżek. Możesz użyć zmiennej środowiskowej „SECONDARY_STORAGE”, aby znaleźć ścieżkę do wymiennej karty SD.Przykładowe użycie:
źródło
Po prostu użyj tego:
źródło
SECONDARY_STORAGE
jest kilka ścieżek oddzielonych dwukropkiem („:”). Właśnie dlatego podzieliłem String (patrz moja odpowiedź powyżej).W sposób uniwersalny , jeśli masz na myśli sposób oficjalny; tak jest jeden.
W interfejsie API na poziomie 19, tj. W wersji Android KitKat 4.4, dodano
File[] getExternalFilesDirs (String type)
wContext
klasie, która pozwala aplikacjom przechowywać dane / pliki na kartach micro SD.Android 4.4 to pierwsza wersja platformy, która pozwoliła aplikacjom na używanie kart SD do przechowywania danych. Jakikolwiek dostęp do kart SD przed 19 poziomem API odbywał się za pośrednictwem prywatnych, nieobsługiwanych interfejsów API.
getExternalFilesDirs (typ ciągu) zwraca ścieżki bezwzględne do katalogów specyficznych dla aplikacji na wszystkich współużytkowanych / zewnętrznych urządzeniach pamięci masowej. Oznacza to, że zwróci ścieżki zarówno do pamięci wewnętrznej, jak i zewnętrznej. Zasadniczo druga zwracana ścieżka byłaby przechowywania karty microSD (jeśli istnieje).
Ale zauważ, że
Terminologia dotycząca pamięci wewnętrznej i zewnętrznej według Google / oficjalnych dokumentów Androida jest zupełnie inna niż myślimy.
źródło
getExternalFilesDirs()
często zwraca karty SD, których nie można wyjąć, więc nie, nie jest to uniwersalny sposób na znalezienie lokalizacji wymiennej karty SD.Oto sposób, w jaki używam do znalezienia karty zewnętrznej. Użyj polecenia mount cmd return, a następnie przeanalizuj część vfat.
źródło
To rozwiązanie radzi sobie z faktem, że
System.getenv("SECONDARY_STORAGE")
nie ma zastosowania w przypadku Marshmallow.Testowane i pracujące nad:
Samsung Galaxy Tab A (Android 6.0.1 - dostępny)
źródło
Od mojej pierwotnej odpowiedzi powyżej skanowanie volda nie jest już wykonalne u różnych producentów.
Opracowałem bardziej niezawodną i prostą metodę.
Root będzie zawierał wszystkie zapisywane katalogi root w systemie, w tym wszelkie urządzenia USB podłączone.
UWAGA: Metoda canWrite wymaga pozwolenia android.permission.WRITE_EXTERNAL_STORAGE.
źródło
/external_sd
jest zewnętrzna karta microSD; na niektórych LG to jest/_ExternalSD
; na niektórych urządzeniach to/sdcard
. Może to drugie jest dowiązaniem symbolicznym/storage/sdcard0
lub podobnym, ale czy te inne naprawdę będą naprawdę niezawodnie objęte przez/storage/*
i/mount/*
?pathname.canWrite()
i wymaganie pozwolenia WRITE_EXTERNAL_STORAGE? Dlaczego nie po prostu zadzwonićpathname.canRead()
?było już tak późno, ale w końcu dostałem coś, co przetestowałem na większości urządzeń (od wersji producenta i Androida) na Androida 2.2+. jeśli okaże się, że to nie działa, skomentuj je nazwą urządzenia. naprawię to. jeśli ktoś jest zainteresowany, wyjaśnię, jak to działa.
źródło
Pisząc poniższy kod otrzymasz lokalizację:
/ storage / 663D-554E / Android / data / nazwa_pakietu aplikacji / pliki /
który przechowuje dane Twojej aplikacji w lokalizacji / android / data wewnątrz karty SD.
Testowałem ten kod na moto g4 plus i urządzeniu Samsung (wszystko działa dobrze).
mam nadzieję, że to może pomóc.
źródło
Oto metoda, której używam do znalezienia wymiennej karty SD. Jest skomplikowany i prawdopodobnie przesadza w niektórych sytuacjach, ale działa na wielu wersjach Androida i producentach urządzeń, które testowałem w ciągu ostatnich kilku lat. Nie znam żadnych urządzeń od poziomu API 15, na którym nie znajduje karty SD, jeśli jest ona zamontowana. W większości przypadków nie zwróci wyników fałszywie dodatnich, szczególnie jeśli nadasz mu nazwę znanego pliku do wyszukania.
Daj mi znać, jeśli napotkasz przypadki, w których to nie działa.
PS
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
w manifeście. Na poziomie API 23 i wyższym upewnij się, że używaszcheckSelfPermission
/requestPermissions
.findSdCardPath(),
zamiast ją przeliczać za każdym razem, gdy jej potrzebujesz.Log.d()
powyższym kodzie jest kilka funkcji logowania ( ). Pomaga zdiagnozować wszystkie przypadki, w których nie można znaleźć właściwej ścieżki. Skomentuj, jeśli nie chcesz się logować.źródło
Jedynym działającym rozwiązaniem, które znalazłem, było to, które wykorzystuje odbicie
źródło
Nie wiem dlaczego, ale przed użyciem muszę wywołać funkcję .createNewFile () dla pliku utworzonego w publicznych katalogach pamięci. W ramach komentarzy do tej metody stwierdzono, że nie jest ona użyteczna. Oto próbka ...
źródło
Stworzyłem metodę utils, aby sprawdzić, czy karta SD jest dostępna na urządzeniu, czy nie, i uzyskać ścieżkę karty SD na urządzeniu, jeśli jest dostępna.
Możesz skopiować 2 metody poniżej do klasy projektu, której potrzebujesz. To wszystko.
źródło
Działa na wszystkich urządzeniach zewnętrznych, ale upewnij się, że otrzymujesz tylko nazwę folderu zewnętrznego urządzenia, a następnie musisz pobrać plik z danej lokalizacji za pomocą klasy File.
Powołanie:
Uzyskiwanie dostępu do pamięci zewnętrznej
Aby odczytywać lub zapisywać pliki w pamięci zewnętrznej, aplikacja musi uzyskać uprawnienia systemowe READ_EXTERNAL_STORAGE lub WRITE_EXTERNAL_STORAGE . Na przykład:
źródło
/ sdcard => Pamięć wewnętrzna (to dowiązanie symboliczne, ale powinno działać)
/ mnt / extSdCard => Zewnętrzna karta Sd
To jest dla Samsung Galaxy S3
Prawdopodobnie możesz polegać na tym, że jest to prawdą w przypadku większości ... podwójnych czeków jednak!
źródło
/sdcard
jest dowiązaniem symbolicznym do zewnętrznego na moim Sony