Can't create a directory in external sd card (Lollipop)
That is due to the design of Android Lollipop.
Environment.getExternalStorageDirectory()
will return only the path of emulated external storage.
Android does not expose any API that gives you the path of the sdcard.
Also, in Lollipop, apps cannot write to location outside of their own directory in the sdcard, unless user permission is obtained through Storage Access Framework.
Try context.getExternalFilesDirs()
. That gives you a list of paths where your app can write data to. One of it will be in the sdcard and will go like /storage/sdcardname/Android/data/yourAppName/files
Comments
-
cgr almost 2 years
I have no problem with internal storage but I want to create a directory on the external SD card, with versions prior to KitKat,
File.mkdirs()
works.There is part of my code:
//external sd card DocumentFile.fromFile(new File("/storage/sdcard1/")).exists(); //returns true DocumentFile.fromFile(new File("/storage/sdcard1/")).canRead(); //returns true DocumentFile.fromFile(new File("/storage/sdcard1/")).canWrite(); //returns true DocumentFile.fromFile(new File("/storage/sdcard1/test")).exists(); //returns false DocumentFile.fromFile(new File("/storage/sdcard1/")).createDirectory("test"); //returns null //internal storage DocumentFile.fromFile(new File("/storage/emulated/0/")).exists(); //returns true DocumentFile.fromFile(new File("/storage/emulated/0/test")).exists(); //returns false DocumentFile.fromFile(new File("/storage/emulated/0/")).createDirectory("test"); //it works DocumentFile.fromFile(new File("/storage/emulated/0/test")).exists(); //returns true DocumentFile.fromFile(new File("/storage/emulated/0/test")).createFile("text", "file.txt"); //it works //external sd card (new File("/storage/sdcard1/test2/subfolder")).exists(); //returns false (new File("/storage/sdcard1/test2/subfolder")).mkdirs(); //returns false //internal storage (new File("/storage/emulated/0/test2/subfolder")).exists(); //returns false (new File("/storage/emulated/0/test2/subfolder")).mkdirs(); //returns true
In AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Testing with an BQ Aquaris e4, Android Lollipop 5.0 and a 1GB micro SD card.
UPDATE: This is how I get the volume list:
private static ArrayList<StorageInfo> listAvaliableStorage(Context context) { ArrayList<StorageInfo> storagges = new ArrayList<>(); StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); try { Class<?>[] paramClasses = {}; Method getVolumeList = StorageManager.class.getMethod("getVolumeList", paramClasses); getVolumeList.setAccessible(true); Object[] params = {}; Object[] invokes = (Object[]) getVolumeList.invoke(storageManager, params); if (invokes != null) { StorageInfo info; for (Object obj : invokes) { Method getPath = obj.getClass().getMethod("getPath"); String path = (String) getPath.invoke(obj); info = new StorageInfo(path); File file = new File(info.getPath()); if ((file.exists()) && (file.isDirectory()) //&& (file.canWrite()) ) { info.setTotalStorage(file.getTotalSpace()); info.setFreeStorage(file.getUsableSpace()); Method isRemovable = obj.getClass().getMethod("isRemovable"); String state; try { Method getVolumeState = StorageManager.class.getMethod("getVolumeState", String.class); state = (String) getVolumeState.invoke(storageManager, info.getPath()); info.setState(state); info.setRemovable((Boolean) isRemovable.invoke(obj)); } catch (Exception e) { e.printStackTrace(); } storagges.add(info); } } } } catch (NoSuchMethodException | IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } storagges.trimToSize(); return storagges; }
The hard coded paths is only for this example
UPDATE 2: I've created the directory: "test" in SD Card with a file explorer. When I execute this code:
File file = new File("/storage/sdcard1/test/", "file.txt"); fileOutput = new FileOutputStream(file);
The second line throws
FileNotFoundException: /storage/sdcard1/test/file.txt: open failed: EACCES (Permission denied)
What am I doing wrong?
-
cgr over 8 yearsgetExternalFilesDirs() returns "/storage/emulated/0/Android/data/packagename/files" but this is not the external sdcard. Solved with Storage Access Framework, here a good explanation stackoverflow.com/questions/26744842/…
-
somesh over 8 yearsAre you sure you used getExternalFilesDirs and not getExternalFilesDir? Dir will return only the emulated path. Dirs will return emulated path and sdcard path.
-
cgr over 7 yearsEnvironment.getExternalStorageDirectory.getPath() returns "/storage/emulated/0/", this is not the external sdcard
-
Wraithious over 7 yearscorrect that is why i did not use that in my above code, first i got the Environment.getExternalStorageDirectory() and then put the string together with File folder = new File(Root.getAbsolutePath() , not getPath, I tested it on api 4.1 and 6, it worked and made the folders that the user can easily find whereas all other methods I've seen posted on here didn't work (for me at least)
-
Deep Dave over 7 yearsAny Solutions? @cgr
-
cgr over 7 yearsyes @DeepDave, using Storage Access Framework, see this answer stackoverflow.com/questions/26744842/…