Android to get SD card path:
The external SD card path may not be used by many students in their daily work, because many models do not support external SD cards (this is also a Google goal), so there is no need to consider the path issue of external SD cards. In addition to developing applications in file management, other applications can meet their needs using some static methods in Environment class. But there are some special needs to use the external SD card path. So how can we accurately obtain the path of the external SD card?
Method 1
//Built-in SD card pathString sdcardPath = ("EXTERNAL_STORAGE"); //Built-in SD card pathString sdcardPath = ().getAbsolutePath(); //Output SD card pathString extSdcardPath = ("SECONDARY_STORAGE"); existEnviromentObtained from the source code of the classsdThe calorie path is actually through () Method to implement,Such as hidden methods: /** {@hide} */ public static File getLegacyExternalStorageDirectory() { return new File((ENV_EXTERNAL_STORAGE)); }
Note: For more detailed content, please check the Environment source code.
Also note that SECONDARY_STORAGE is removed in the API 23 version.
Method 2
private static String getStoragePath(Context mContext, boolean is_removale) { StorageManager mStorageManager = (StorageManager) (Context.STORAGE_SERVICE); Class<?> storageVolumeClazz = null; try { storageVolumeClazz = (""); Method getVolumeList = ().getMethod("getVolumeList"); Method getPath = ("getPath"); Method isRemovable = ("isRemovable"); Object result = (mStorageManager); final int length = (result); for (int i = 0; i < length; i++) { Object storageVolumeElement = (result, i); String path = (String) (storageVolumeElement); boolean removable = (Boolean) (storageVolumeElement); if (is_removale == removable) { return path; } } } catch (ClassNotFoundException e) { (); } catch (InvocationTargetException e) { (); } catch (NoSuchMethodException e) { (); } catch (IllegalAccessException e) { (); } return null; }
Use the method getVolumeList() in the class StroageVolume hidden in sdk in reflective way to get all storage space (Stroage Volume), and then use the parameter is_removable to get the paths of internal storage and external storage (internal and external sd cards). When the parameter is_removable is false, the built-in sd card path is obtained, and if true, it is the external sd card path.
In the internal class UserEnvironment in API 23 Environment class, there is a method getExternalDirs like this, the code is as follows:
public File[] getExternalDirs() { final StorageVolume[] volumes = (mUserId,StorageManager.FLAG_FOR_WRITE); final File[] files = new File[]; for (int i = 0; i < ; i++) { files[i] = volumes[i].getPathFile(); } return files; }
Let’s look at the getExternalStorageDirectory method implementation of Environment:
public static File getExternalStorageDirectory() { throwIfUserRequired(); return ()[0]; }
It can be seen that in API 23, the File[] array of all storage spaces is first obtained through getExternalDirs(). The first value of this array is: getExternalDirs()[0], which is the path where the built-in SD card is located.
In the versions before API 23, there is no method similar to getExternalDirs() that directly obtains storage space (Storage Volume) through StorageVolume, and it is implemented in other ways, depending on the source code of the key method:
public static File getExternalStorageDirectory() { throwIfUserRequired(); return ()[0]; }
The function of getExternalDirsForApp() here and getExternalDirs() above is the same, both of which get File[] arrays of all storage spaces.
public File[] getExternalDirsForApp() { return mExternalDirsForApp; }
mExternalDirsForApp is initialized in the constructor of the internal class UserEnvironment in the Environment class. The source code of the Environment#UserEnvironment constructor is as follows:
public UserEnvironment(int userId) { // See storage config details at /tech/storage/ String rawExternalStorage = (ENV_EXTERNAL_STORAGE); String rawEmulatedSource = (ENV_EMULATED_STORAGE_SOURCE); String rawEmulatedTarget = (ENV_EMULATED_STORAGE_TARGET); String rawMediaStorage = (ENV_MEDIA_STORAGE); if ((rawMediaStorage)) { rawMediaStorage = "/data/media"; } ArrayList<File> externalForVold = (); ArrayList<File> externalForApp = (); if (!(rawEmulatedTarget)) { // Device has emulated storage; external storage paths should have // userId burned into them. final String rawUserId = (userId); final File emulatedSourceBase = new File(rawEmulatedSource); final File emulatedTargetBase = new File(rawEmulatedTarget); final File mediaBase = new File(rawMediaStorage); // /storage/emulated/0 (buildPath(emulatedSourceBase, rawUserId)); (buildPath(emulatedTargetBase, rawUserId)); // /data/media/0 mEmulatedDirForDirect = buildPath(mediaBase, rawUserId); } else { // Device has physical external storage; use plain paths. if ((rawExternalStorage)) { (TAG, "EXTERNAL_STORAGE undefined; falling back to default"); rawExternalStorage = "/storage/sdcard0"; } // /storage/sdcard0 (new File(rawExternalStorage)); (new File(rawExternalStorage)); // /data/media mEmulatedDirForDirect = new File(rawMediaStorage); } // Splice in any secondary storage paths, but only for owner final String rawSecondaryStorage = (ENV_SECONDARY_STORAGE); if (!(rawSecondaryStorage) && userId == UserHandle.USER_OWNER) { for (String secondaryPath : (":")) { (new File(secondaryPath)); (new File(secondaryPath)); } } mExternalDirsForVold = (new File[()]); mExternalDirsForApp = (new File[()]); }
You can also obtain a method that obtains the path to all storage spaces based on this method:
/** * Returns all available SD-Cards in the system (include emulated) * <p/> * Warning: Hack! Based on Android source code of version 4.3 (API 18) * Because there is no standard way to get it. * TODO: Test on future Android versions 4.4+ * * @return paths to all available SD-Cards in the system (include emulated) */ private static final Pattern DIR_SEPARATOR = ("/"); public List<String> getStorageDirectories() { // Final set of paths final ArrayList<String> rv = new ArrayList<String>(); // Primary physical SD-CARD (not emulated) final String rawExternalStorage = ("EXTERNAL_STORAGE"); // All Secondary SD-CARDs (all exclude primary) separated by ":" final String rawSecondaryStoragesStr = ("SECONDARY_STORAGE"); // Primary emulated SD-CARD final String rawEmulatedStorageTarget = ("EMULATED_STORAGE_TARGET"); if ((rawEmulatedStorageTarget)) { // Device has physical external storage; use plain paths. if ((rawExternalStorage)) { // EXTERNAL_STORAGE undefined; falling back to default. ("/storage/sdcard0"); } else { (rawExternalStorage); } } else { // Device has emulated storage; external storage paths should have // userId burned into them. final String rawUserId; if (.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { rawUserId = ""; } else { final String path = ().getAbsolutePath(); final String[] folders = DIR_SEPARATOR.split(path); final String lastFolder = folders[ - 1]; boolean isDigit = false; try { (lastFolder); isDigit = true; } catch (NumberFormatException ignored) { } rawUserId = isDigit ? lastFolder : ""; } // /storage/emulated/0[1,2,...] if ((rawUserId)) { (rawEmulatedStorageTarget); } else { (rawEmulatedStorageTarget + + rawUserId); } } // Add all secondary storages if (!(rawSecondaryStoragesStr)) { // All Secondary SD-CARDs splited into array final String[] rawSecondaryStorages = (); (rv, rawSecondaryStorages); } rootmode = ("rootmode", false); if (rootmode) ("/"); File usb = getUsbDrive(); if (usb != null && !(())) (()); return rv; } public File getUsbDrive() { File parent; parent = new File("/storage"); try { for (File f : ()) { if (() && ().toLowerCase().contains("usb") && ()) { return f; } } } catch (Exception e) { } parent = new File("/mnt/sdcard/usbStorage"); if (() && ()) return (parent); parent = new File("/mnt/sdcard/usb_storage"); if (() && ()) return parent; return null; }
To sum up, both methods 1 and 2 can correctly obtain the internal and external SD card paths, but there are the following problems with Method 1:
1. Method 1 is invalid when API>=23 (not tested yet)
2. Some manufacturers have too many changes to Rom, and there are problems with the support for related native APIs. At this time, there may be problems with the method.
3. The causes of some other situations (basically similar to 2, which are caused by factors such as ROM)
Therefore, when using it, it is recommended to use Method 2 to get the internal and external SD card path. It should be OK to use getStorageDirectories() before API 23 (Android 6.0).
Thank you for reading, I hope it can help you. Thank you for your support for this site!