Samsung Galaxy S3 posiada zewnętrzne gniazdo na kartę SD, do którego jest montowany /mnt/extSdCard
.
Jak mogę uzyskać tę ścieżkę przez coś takiego Environment.getExternalStorageDirectory()
?
To powróci mnt/sdcard
i nie mogę znaleźć interfejsu API dla zewnętrznej karty SD. (Lub wymienna pamięć USB w niektórych tabletach.)
android
android-sdcard
Romulus Urakagi Ts'ai
źródło
źródło
Odpowiedzi:
Mam odmianę rozwiązania, które znalazłem tutaj
public static HashSet<String> getExternalMounts() { final HashSet<String> out = new HashSet<String>(); String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*"; String s = ""; try { final Process process = new ProcessBuilder().command("mount") .redirectErrorStream(true).start(); process.waitFor(); final InputStream is = process.getInputStream(); final byte[] buffer = new byte[1024]; while (is.read(buffer) != -1) { s = s + new String(buffer); } is.close(); } catch (final Exception e) { e.printStackTrace(); } // parse output final String[] lines = s.split("\n"); for (String line : lines) { if (!line.toLowerCase(Locale.US).contains("asec")) { if (line.matches(reg)) { String[] parts = line.split(" "); for (String part : parts) { if (part.startsWith("/")) if (!part.toLowerCase(Locale.US).contains("vold")) out.add(part); } } } } return out; }
Oryginalna metoda została przetestowana i wykorzystana
Nie jestem pewien, w której wersji Androida były one włączone podczas testowania.
Przetestowałem moją zmodyfikowaną wersję z
i niektóre pojedyncze urządzenia pamięci masowej, które używają sdcard jako głównego magazynu
Z wyjątkiem Incredible wszystkie te urządzenia zwróciły tylko wymienną pamięć masową. Prawdopodobnie powinienem przeprowadzić dodatkowe kontrole, ale jest to przynajmniej trochę lepsze niż jakiekolwiek rozwiązanie, które znalazłem do tej pory.
źródło
Znalazłem bardziej niezawodny sposób na uzyskanie ścieżek do wszystkich kart SD w systemie. Działa to na wszystkich wersjach Androida i zwraca ścieżki do wszystkich magazynów (w tym emulowanych).
Działa poprawnie na wszystkich moich urządzeniach.
PS: Na podstawie kodu źródłowego klasy Environment.
private static final Pattern DIR_SEPORATOR = Pattern.compile("/"); /** * Raturns all available SD-Cards in the system (include emulated) * * Warning: Hack! Based on Android source code of version 4.3 (API 18) * Because there is no standart way to get it. * TODO: Test on future Android versions 4.4+ * * @return paths to all available SD-Cards in the system (include emulated) */ public static String[] getStorageDirectories() { // Final set of paths final Set<String> rv = new HashSet<String>(); // Primary physical SD-CARD (not emulated) final String rawExternalStorage = System.getenv("EXTERNAL_STORAGE"); // All Secondary SD-CARDs (all exclude primary) separated by ":" final String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE"); // Primary emulated SD-CARD final String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET"); if(TextUtils.isEmpty(rawEmulatedStorageTarget)) { // Device has physical external storage; use plain paths. if(TextUtils.isEmpty(rawExternalStorage)) { // EXTERNAL_STORAGE undefined; falling back to default. rv.add("/storage/sdcard0"); } else { rv.add(rawExternalStorage); } } else { // Device has emulated storage; external storage paths should have // userId burned into them. final String rawUserId; if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { rawUserId = ""; } else { final String path = Environment.getExternalStorageDirectory().getAbsolutePath(); final String[] folders = DIR_SEPORATOR.split(path); final String lastFolder = folders[folders.length - 1]; boolean isDigit = false; try { Integer.valueOf(lastFolder); isDigit = true; } catch(NumberFormatException ignored) { } rawUserId = isDigit ? lastFolder : ""; } // /storage/emulated/0[1,2,...] if(TextUtils.isEmpty(rawUserId)) { rv.add(rawEmulatedStorageTarget); } else { rv.add(rawEmulatedStorageTarget + File.separator + rawUserId); } } // Add all secondary storages if(!TextUtils.isEmpty(rawSecondaryStoragesStr)) { // All Secondary SD-CARDs splited into array final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator); Collections.addAll(rv, rawSecondaryStorages); } return rv.toArray(new String[rv.size()]); }
źródło
Pattern
for/
System.getenv("SECONDARY_STORAGE")
zwraca/storage/sdcard1
. Ta lokalizacja nie istnieje, ale rzeczywista lokalizacja to miejsce/storage/42CE-FD0A
, w którym 42CE-FD0A to numer seryjny woluminu sformatowanej partycji.Myślę, że aby użyć zewnętrznej karty SD, musisz użyć tego:
new File("/mnt/external_sd/")
LUB
new File("/mnt/extSdCard/")
w Twoim przypadku...
w miejsce
Environment.getExternalStorageDirectory()
Pracuje dla mnie. Powinieneś najpierw sprawdzić, co jest w katalogu mnt i zacząć od tego miejsca.
Powinieneś użyć jakiejś metody wyboru, aby wybrać, której karty SD użyć:
File storageDir = new File("/mnt/"); if(storageDir.isDirectory()){ String[] dirList = storageDir.list(); //TODO some type of selecton method? }
źródło
Aby pobrać wszystkie zewnętrzne magazyny (niezależnie od tego, czy są to karty SD, czy wewnętrzne niewymienne pamięci ), możesz użyć następującego kodu:
final String state = Environment.getExternalStorageState(); if ( Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) ) { // we can read the External Storage... //Retrieve the primary External Storage: final File primaryExternalStorage = Environment.getExternalStorageDirectory(); //Retrieve the External Storages root directory: final String externalStorageRootDir; if ( (externalStorageRootDir = primaryExternalStorage.getParent()) == null ) { // no parent... Log.d(TAG, "External Storage: " + primaryExternalStorage + "\n"); } else { final File externalStorageRoot = new File( externalStorageRootDir ); final File[] files = externalStorageRoot.listFiles(); for ( final File file : files ) { if ( file.isDirectory() && file.canRead() && (file.listFiles().length > 0) ) { // it is a real directory (not a USB drive)... Log.d(TAG, "External Storage: " + file.getAbsolutePath() + "\n"); } } } }
Alternatywnie możesz użyć System.getenv („EXTERNAL_STORAGE”), aby pobrać podstawowy katalog zewnętrznej pamięci masowej (np. „/ Storage / sdcard0” ) i System.getenv („SECONDARY_STORAGE”), aby pobrać listę wszystkich drugorzędnych katalogów (np. „ / storage / extSdCard: / storage / UsbDriveA: / storage / UsbDriveB ” ). Pamiętaj, że również w tym przypadku możesz chcieć przefiltrować listę katalogów pomocniczych, 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ć zgodnie z życzeniem).
źródło
Używałem Dmitriy Lozenko „s rozwiązanie, dopóki nie sprawdził na Asus Zenfone2 , Marshmallow 6.0.1 i rozwiązanie nie działa. Rozwiązanie nie powiodło się podczas pobierania EMULATED_STORAGE_TARGET , szczególnie dla ścieżki microSD, tj .: / storage / F99C-10F4 / . Edytowałem kod, aby uzyskać emulowane ścieżki główne bezpośrednio z emulowanych ścieżek aplikacji
context.getExternalFilesDirs(null);
i dodać bardziej znane ścieżki fizyczne specyficzne dla modelu telefonu .Aby ułatwić nam życie, stworzyłem tutaj bibliotekę . Możesz go używać za pomocą systemu kompilacji gradle, maven, sbt i leiningen.
Jeśli podoba Ci się staroświecki sposób, możesz również skopiować i wkleić plik bezpośrednio stąd , ale nie będziesz wiedział, czy w przyszłości będzie aktualizacja, bez sprawdzania jej ręcznie.
Jeśli masz jakieś pytania lub sugestie, daj mi znać
źródło
context.getExternalFilesDirs(null)
wrócinull
po jeden z plików i będzie wyjątek w następnej pętli. Proponuję dodaćif (file == null) continue;
jako pierwszą linię w pętli.Dobre wieści! W KitKat jest teraz publiczny interfejs API do interakcji z tymi dodatkowymi współdzielonymi urządzeniami magazynującymi.
Nowe metody
Context.getExternalFilesDirs()
iContext.getExternalCacheDirs()
mogą zwracać wiele ścieżek, w tym zarówno urządzenia podstawowe, jak i pomocnicze. Następnie możesz je iterować, sprawdzaćEnvironment.getStorageState()
iFile.getFreeSpace()
określać najlepsze miejsce do przechowywania plików. Te metody są również dostępneContextCompat
w bibliotece support-v4.Pamiętaj również, że jeśli jesteś zainteresowany tylko używaniem katalogów zwróconych przez
Context
, nie potrzebujesz już uprawnieńREAD_
lubWRITE_EXTERNAL_STORAGE
. Idąc dalej, zawsze będziesz mieć dostęp do odczytu / zapisu do tych katalogów bez dodatkowych uprawnień.Aplikacje mogą również kontynuować pracę na starszych urządzeniach, kończąc ich prośbę o pozwolenie w następujący sposób:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />
źródło
Wykonałem następujące czynności, aby uzyskać dostęp do wszystkich zewnętrznych kart SD.
Z:
File primaryExtSd=Environment.getExternalStorageDirectory();
otrzymasz ścieżkę do głównego zewnętrznego SD Następnie za pomocą:
File parentDir=new File(primaryExtSd.getParent());
otrzymujesz katalog nadrzędny podstawowej pamięci zewnętrznej, a także jest on nadrzędny dla wszystkich zewnętrznych dysków sd. Teraz możesz wyświetlić listę wszystkich magazynów i wybrać ten, który chcesz.
Mam nadzieję, że jest to przydatne.
źródło
Oto jak otrzymuję listę ścieżek kart SD (z wyłączeniem podstawowej pamięci zewnętrznej):
/** * returns a list of all available sd cards paths, or null if not found. * * @param includePrimaryExternalStorage set to true if you wish to also include the path of the primary external storage */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static List<String> getSdCardPaths(final Context context,final boolean includePrimaryExternalStorage) { final File[] externalCacheDirs=ContextCompat.getExternalCacheDirs(context); if(externalCacheDirs==null||externalCacheDirs.length==0) return null; if(externalCacheDirs.length==1) { if(externalCacheDirs[0]==null) return null; final String storageState=EnvironmentCompat.getStorageState(externalCacheDirs[0]); if(!Environment.MEDIA_MOUNTED.equals(storageState)) return null; if(!includePrimaryExternalStorage&&VERSION.SDK_INT>=VERSION_CODES.HONEYCOMB&&Environment.isExternalStorageEmulated()) return null; } final List<String> result=new ArrayList<>(); if(includePrimaryExternalStorage||externalCacheDirs.length==1) result.add(getRootOfInnerSdCardFolder(externalCacheDirs[0])); for(int i=1;i<externalCacheDirs.length;++i) { final File file=externalCacheDirs[i]; if(file==null) continue; final String storageState=EnvironmentCompat.getStorageState(file); if(Environment.MEDIA_MOUNTED.equals(storageState)) result.add(getRootOfInnerSdCardFolder(externalCacheDirs[i])); } if(result.isEmpty()) return null; return result; } /** Given any file/folder inside an sd card, this will return the path of the sd card */ private static String getRootOfInnerSdCardFolder(File file) { if(file==null) return null; final long totalSpace=file.getTotalSpace(); while(true) { final File parentFile=file.getParentFile(); if(parentFile==null||parentFile.getTotalSpace()!=totalSpace||!parentFile.canRead()) return file.getAbsolutePath(); file=parentFile; } }
źródło
externalCacheDirs[0].getParentFile().getParentFile().getParentFile().getParentFile().getAbsolutePath()
To jest przepis na katastrofę. Jeśli to robisz, równie dobrze możesz po prostu zakodować ścieżkę, którą chcesz, ponieważ jeśli otrzymasz katalog pamięci podręcznej z czymkolwiek innym niż 4 rodziców, otrzymasz NullPointerException lub złą ścieżkę.Dzięki za wskazówki dostarczone przez was, zwłaszcza @SmartLemon, mam rozwiązanie. Na wypadek, gdyby ktoś tego potrzebował, umieściłem tutaj moje ostateczne rozwiązanie (aby znaleźć pierwszą wymienioną zewnętrzną kartę SD):
public File getExternalSDCardDirectory() { File innerDir = Environment.getExternalStorageDirectory(); File rootDir = innerDir.getParentFile(); File firstExtSdCard = innerDir ; File[] files = rootDir.listFiles(); for (File file : files) { if (file.compareTo(innerDir) != 0) { firstExtSdCard = file; break; } } //Log.i("2", firstExtSdCard.getAbsolutePath().toString()); return firstExtSdCard; }
Jeśli nie ma tam zewnętrznej karty SD, zwraca pamięć na pokładzie. Użyję go, jeśli sdcard nie istnieje, być może będziesz musiał ją zmienić.
źródło
zapoznaj się z moim kodem, mam nadzieję, że pomoże ci to:
Runtime runtime = Runtime.getRuntime(); Process proc = runtime.exec("mount"); InputStream is = proc.getInputStream(); InputStreamReader isr = new InputStreamReader(is); String line; String mount = new String(); BufferedReader br = new BufferedReader(isr); while ((line = br.readLine()) != null) { if (line.contains("secure")) continue; if (line.contains("asec")) continue; if (line.contains("fat")) {//TF card String columns[] = line.split(" "); if (columns != null && columns.length > 1) { mount = mount.concat("*" + columns[1] + "\n"); } } else if (line.contains("fuse")) {//internal storage String columns[] = line.split(" "); if (columns != null && columns.length > 1) { mount = mount.concat(columns[1] + "\n"); } } } txtView.setText(mount);
źródło
W rzeczywistości w niektórych urządzeniach domyślna nazwa zewnętrznej karty SD jest wyświetlana tak, jak w
extSdCard
przypadku innychsdcard1
.Ten fragment kodu pomaga znaleźć dokładną ścieżkę i pomaga pobrać ścieżkę do urządzenia zewnętrznego.
String sdpath,sd1path,usbdiskpath,sd0path; if(new File("/storage/extSdCard/").exists()) { sdpath="/storage/extSdCard/"; Log.i("Sd Cardext Path",sdpath); } if(new File("/storage/sdcard1/").exists()) { sd1path="/storage/sdcard1/"; Log.i("Sd Card1 Path",sd1path); } if(new File("/storage/usbcard1/").exists()) { usbdiskpath="/storage/usbcard1/"; Log.i("USB Path",usbdiskpath); } if(new File("/storage/sdcard0/").exists()) { sd0path="/storage/sdcard0/"; Log.i("Sd Card0 Path",sd0path); }
źródło
Tak. Różni producenci używają innej nazwy karty SD, jak w Samsung Tab 3, jej extsd, a inne urządzenia Samsung używają sdcard, tak jak ten inny producent używa różnych nazw.
Miałem takie same wymagania jak ty. więc utworzyłem dla Ciebie przykładowy przykład z mojego projektu. Przejdź do tego linku Przykład selektora katalogu systemu Android, który używa biblioteki androi-dirchooser. Ten przykład wykrywa kartę SD i wyświetla listę wszystkich podfolderów, a także wykrywa, czy urządzenie ma więcej niż jedną kartę SD.
Część kodu wygląda następująco. Aby uzyskać pełny przykład, przejdź do łącza Android Directory Chooser
/** * Returns the path to internal storage ex:- /storage/emulated/0 * * @return */ private String getInternalDirectoryPath() { return Environment.getExternalStorageDirectory().getAbsolutePath(); } /** * Returns the SDcard storage path for samsung ex:- /storage/extSdCard * * @return */ private String getSDcardDirectoryPath() { return System.getenv("SECONDARY_STORAGE"); } mSdcardLayout.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { String sdCardPath; /*** * Null check because user may click on already selected buton before selecting the folder * And mSelectedDir may contain some wrong path like when user confirm dialog and swith back again */ if (mSelectedDir != null && !mSelectedDir.getAbsolutePath().contains(System.getenv("SECONDARY_STORAGE"))) { mCurrentInternalPath = mSelectedDir.getAbsolutePath(); } else { mCurrentInternalPath = getInternalDirectoryPath(); } if (mCurrentSDcardPath != null) { sdCardPath = mCurrentSDcardPath; } else { sdCardPath = getSDcardDirectoryPath(); } //When there is only one SDcard if (sdCardPath != null) { if (!sdCardPath.contains(":")) { updateButtonColor(STORAGE_EXTERNAL); File dir = new File(sdCardPath); changeDirectory(dir); } else if (sdCardPath.contains(":")) { //Multiple Sdcards show root folder and remove the Internal storage from that. updateButtonColor(STORAGE_EXTERNAL); File dir = new File("/storage"); changeDirectory(dir); } } else { //In some unknown scenario at least we can list the root folder updateButtonColor(STORAGE_EXTERNAL); File dir = new File("/storage"); changeDirectory(dir); } } });
źródło
To rozwiązanie (zestawione z innych odpowiedzi na to pytanie) rozwiązuje fakt (jak wspomniał @ono), który
System.getenv("SECONDARY_STORAGE")
nie jest przydatny w przypadku Marshmallow.Przetestowane i pracuję nad:
Samsung Galaxy Tab A (Android 6.0.1 - w magazynie)
/** * Returns all available external SD-Card roots in the system. * * @return paths to all available external SD-Card roots in the system. */ public static String[] getStorageDirectories() { String [] storageDirectories; String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { List<String> results = new ArrayList<String>(); File[] externalDirs = applicationContext.getExternalFilesDirs(null); for (File file : externalDirs) { String path = file.getPath().split("/Android")[0]; if((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Environment.isExternalStorageRemovable(file)) || rawSecondaryStoragesStr != null && rawSecondaryStoragesStr.contains(path)){ results.add(path); } } storageDirectories = results.toArray(new String[0]); }else{ final Set<String> rv = new HashSet<String>(); if (!TextUtils.isEmpty(rawSecondaryStoragesStr)) { final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator); Collections.addAll(rv, rawSecondaryStorages); } storageDirectories = rv.toArray(new String[rv.size()]); } return storageDirectories; }
źródło
rawSecondaryStoragesStr.contains(path)
może pozwolić na dodanie pamięci wewnętrznej; możemy lepiej usunąć ten warunek .. Napotkałem ten problem, ponieważ moje urządzenie zwraca wewnętrzny katalog pamięci zSystem.getenv("SECONDARY_STORAGE")
, ale zwraca ścieżkę zewnętrznej karty pamięci zSystem.getenv(EXTERNAL_STORAGE)
na KitKat; wygląda na to, że różni dostawcy zaimplementowali to inaczej, bez żadnego cholernego standardu ..Na niektórych urządzeniach (na przykład samsung galaxy sII) wewnętrzna karta pamięci może być w formacie vfat. W tym przypadku użyj odwołania do ostatniego kodu, otrzymamy ścieżkę do wewnętrznej karty pamięci (/ mnt / sdcad), ale bez karty zewnętrznej. Kod poniżej rozwiązuje ten problem.
static String getExternalStorage(){ String exts = Environment.getExternalStorageDirectory().getPath(); try { FileReader fr = new FileReader(new File("/proc/mounts")); BufferedReader br = new BufferedReader(fr); String sdCard=null; String line; while((line = br.readLine())!=null){ if(line.contains("secure") || line.contains("asec")) continue; if(line.contains("fat")){ String[] pars = line.split("\\s"); if(pars.length<2) continue; if(pars[1].equals(exts)) continue; sdCard =pars[1]; break; } } fr.close(); br.close(); return sdCard; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }
źródło
File[] files = null; File file = new File("/storage");// /storage/emulated if (file.exists()) { files = file.listFiles(); } if (null != files) for (int j = 0; j < files.length; j++) { Log.e(TAG, "" + files[j]); Log.e(TAG, "//--//--// " + files[j].exists()); if (files[j].toString().replaceAll("_", "") .toLowerCase().contains("extsdcard")) { external_path = files[j].toString(); break; } else if (files[j].toString().replaceAll("_", "") .toLowerCase() .contains("sdcard".concat(Integer.toString(j)))) { // external_path = files[j].toString(); } Log.e(TAG, "--///--///-- " + external_path); }
źródło
Jestem pewien, że ten kod z pewnością rozwiąże Twoje problemy ... U mnie działa dobrze ... \
try { File mountFile = new File("/proc/mounts"); usbFoundCount=0; sdcardFoundCount=0; if(mountFile.exists()) { Scanner usbscanner = new Scanner(mountFile); while (usbscanner.hasNext()) { String line = usbscanner.nextLine(); if (line.startsWith("/dev/fuse /storage/usbcard1")) { usbFoundCount=1; Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/usbcard1" ); } } } if(mountFile.exists()){ Scanner sdcardscanner = new Scanner(mountFile); while (sdcardscanner.hasNext()) { String line = sdcardscanner.nextLine(); if (line.startsWith("/dev/fuse /storage/sdcard1")) { sdcardFoundCount=1; Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/sdcard1" ); } } } if(usbFoundCount==1) { Toast.makeText(context,"USB Connected and properly mounted", 7000).show(); Log.i("-----USB--------","USB Connected and properly mounted" ); } else { Toast.makeText(context,"USB not found!!!!", 7000).show(); Log.i("-----USB--------","USB not found!!!!" ); } if(sdcardFoundCount==1) { Toast.makeText(context,"SDCard Connected and properly mounted", 7000).show(); Log.i("-----SDCard--------","SDCard Connected and properly mounted" ); } else { Toast.makeText(context,"SDCard not found!!!!", 7000).show(); Log.i("-----SDCard--------","SDCard not found!!!!" ); } }catch (Exception e) { e.printStackTrace(); }
źródło
to nieprawda. / mnt / sdcard / external_sd może istnieć, nawet jeśli karta SD nie jest zamontowana. Twoja aplikacja ulegnie awarii podczas próby zapisu do / mnt / sdcard / external_sd, gdy nie jest zamontowana.
musisz najpierw sprawdzić, czy karta SD jest zamontowana za pomocą:
boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
źródło
getExternalStorageState()
Myślę, że jest to bez znaczenia, gdy zwraca się pamięć wewnętrzną, a nie zewnętrzną kartę SD.String path = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_PICTURES; File dir = new File(path);
źródło
Możesz użyć czegoś takiego jak - Context.getExternalCacheDirs () lub Context.getExternalFilesDirs () lub Context.getObbDirs (). Dają specyficzne dla aplikacji katalogi we wszystkich zewnętrznych urządzeniach pamięci masowej, w których aplikacja może przechowywać swoje pliki.
Coś takiego - Context.getExternalCacheDirs () [i] .getParentFile (). GetParentFile (). GetParentFile (). GetParent () może uzyskać ścieżkę główną zewnętrznych urządzeń pamięci masowej.
Wiem, że te polecenia mają inny cel, ale inne odpowiedzi mi nie pomogły.
Ten link dał mi dobre wskazówki - https://possiblemobile.com/2014/03/android-external-storage/
źródło
System.getenv("SECONDARY_STORAGE")
zwraca wartość null dla Marshmallow. To kolejny sposób na znalezienie wszystkich reżimów zewnętrznych. Możesz sprawdzić, czy jest wymienny, co określa, czy jest wewnętrzny / zewnętrznyif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { File[] externalCacheDirs = context.getExternalCacheDirs(); for (File file : externalCacheDirs) { if (Environment.isExternalStorageRemovable(file)) { // It's a removable storage } } }
źródło
Wypróbowałem rozwiązania dostarczone przez Dmitriya Lozenko i Gnathonic na moim Samsung Galaxy Tab S2 (model: T819Y), ale żadne nie pomogło mi odzyskać ścieżki do zewnętrznego katalogu na karcie SD.
mount
wykonanie polecenia zawierało wymaganą ścieżkę do zewnętrznego katalogu karty SD (np. / Storage / A5F9-15F4), ale nie było zgodne z wyrażeniem regularnym, dlatego nie zostało zwrócone. Nie rozumiem mechanizmu nazewnictwa katalogów, po którym jest Samsung. Dlaczego odbiegają od standardów (np. Extsdcard) i wymyślają coś naprawdę podejrzanego, jak w moim przypadku (np. / Storage / A5F9-15F4) . Czy jest coś, czego mi brakuje? Tak czy inaczej, po zmianach w wyrażeniach regularnych Gnathonic rozwiązanie pomogło mi uzyskać prawidłowy katalog sdcard:final HashSet<String> out = new HashSet<String>(); String reg = "(?i).*(vold|media_rw).*(sdcard|vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*"; String s = ""; try { final Process process = new ProcessBuilder().command("mount") .redirectErrorStream(true).start(); process.waitFor(); final InputStream is = process.getInputStream(); final byte[] buffer = new byte[1024]; while (is.read(buffer) != -1) { s = s + new String(buffer); } is.close(); } catch (final Exception e) { e.printStackTrace(); } // parse output final String[] lines = s.split("\n"); for (String line : lines) { if (!line.toLowerCase(Locale.US).contains("asec")) { if (line.matches(reg)) { String[] parts = line.split(" "); for (String part : parts) { if (part.startsWith("/")) if (!part.toLowerCase(Locale.US).contains("vold")) out.add(part); } } } } return out;
Nie jestem pewien, czy to poprawne rozwiązanie i czy da wyniki na innych tabletach Samsunga, ale na razie rozwiązało mój problem. Poniżej znajduje się kolejna metoda odzyskiwania ścieżki wymiennej karty SD w systemie Android (wersja 6.0). Przetestowałem tę metodę na Androidzie marshmallow i działa. Zastosowane w nim podejście jest bardzo podstawowe i na pewno sprawdzi się w innych wersjach, ale testowanie jest obowiązkowe. Pomocny będzie wgląd w to:
public static String getSDCardDirPathForAndroidMarshmallow() { File rootDir = null; try { // Getting external storage directory file File innerDir = Environment.getExternalStorageDirectory(); // Temporarily saving retrieved external storage directory as root // directory rootDir = innerDir; // Splitting path for external storage directory to get its root // directory String externalStorageDirPath = innerDir.getAbsolutePath(); if (externalStorageDirPath != null && externalStorageDirPath.length() > 1 && externalStorageDirPath.startsWith("/")) { externalStorageDirPath = externalStorageDirPath.substring(1, externalStorageDirPath.length()); } if (externalStorageDirPath != null && externalStorageDirPath.endsWith("/")) { externalStorageDirPath = externalStorageDirPath.substring(0, externalStorageDirPath.length() - 1); } String[] pathElements = externalStorageDirPath.split("/"); for (int i = 0; i < pathElements.length - 1; i++) { rootDir = rootDir.getParentFile(); } File[] files = rootDir.listFiles(); for (File file : files) { if (file.exists() && file.compareTo(innerDir) != 0) { // Try-catch is implemented to prevent from any IO exception try { if (Environment.isExternalStorageRemovable(file)) { return file.getAbsolutePath(); } } catch (Exception e) { e.printStackTrace(); } } } } catch (Exception ex) { ex.printStackTrace(); } return null; }
Prosimy o podzielenie się, jeśli masz inne podejście do rozwiązania tego problemu. Dzięki
źródło
String secStore = System.getenv("SECONDARY_STORAGE"); File externalsdpath = new File(secStore);
Spowoduje to uzyskanie ścieżki do zewnętrznej pamięci masowej SD.
źródło
//manifest file outside the application tag //please give permission write this //<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> File file = new File("/mnt"); String[] fileNameList = file.list(); //file names list inside the mnr folder String all_names = ""; //for the log information String foundedFullNameOfExtCard = ""; // full name of ext card will come here boolean isExtCardFounded = false; for (String name : fileNameList) { if (!isExtCardFounded) { isExtCardFounded = name.contains("ext"); foundedFullNameOfExtCard = name; } all_names += name + "\n"; // for log } Log.d("dialog", all_names + foundedFullNameOfExtCard);
źródło
Aby uzyskać dostęp do plików na mojej karcie SD , na moim HTC One X (Android), używam tej ścieżki:
file:///storage/sdcard0/folder/filename.jpg
Zwróć uwagę na potrójny „/”!
źródło
W Galaxy S3 Android 4.3 ścieżka, której używam, to ./storage/extSdCard/Card/ i spełnia swoje zadanie. Mam nadzieję, że to pomoże,
źródło
Poniższe kroki zadziałały dla mnie. Musisz tylko napisać te linie:
String sdf = new String(Environment.getExternalStorageDirectory().getName()); String sddir = new String(Environment.getExternalStorageDirectory().getPath().replace(sdf,""));
Pierwsza linia poda nazwę katalogu sd i wystarczy jej użyć w metodzie zamiany dla drugiego ciągu. Drugi ciąg będzie zawierał ścieżkę do wewnętrznego i wymiennego sd (/ storage / w moim przypadku) . Potrzebowałem tylko tej ścieżki dla mojej aplikacji, ale możesz przejść dalej, jeśli jej potrzebujesz.
źródło