16

I have

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

in my manifest file, however I fail when trying to create a directory

    Log.d(LOG_STRING, android.os.Environment.getExternalStorageState() );
    java.io.File folder = new java.io.File(Environment.getExternalStorageDirectory() + java.io.File.separator + "test");
    boolean success = true;
    if (!folder.exists()) {
        success = folder.mkdir();
    }
    if (success) {
        Log.d(LOG_STRING, "Created directory");
    } else {
        Log.d(LOG_STRING, "FAILED WHILE CREATING DIRECTORY");
    }

The status of external storage is "mounted", but the test directory cannot be created and the output is "FAILED WHILE CREATING DIRECTORY".

Browsing in the phone to the "App Info", the permission "modify or delete the contents of your USB storage" is marked to be activated for my application.

What could be the cause of this? Some special setting of the phone? It's a Samsung GT-I9506 with Android 4.3 (API18). To be noted is that the getExternalStorageDirectory is not on the SD card, but on the internal storage (/storage/emulated/0/).


Update:

Speaking with colleagues, it seems that this device has undergone several tweaking after having been rooted (to allow a specific application to directly write on the SD card). It's probably not worth to investigate further, I will simply switch to another device. I'll keep the device for a while and if anybody will show up with an answer I will quickly test if it solves the problem.


Update 2: (Bounty end)

The problem remains unsolved, but as stated before, it is most likely something very specific to this one device. It's not possible to write on any path, being it external or internal storage, not even in the path returned by getExternalCacheDir().

Antonio
  • 19,451
  • 13
  • 99
  • 197
  • 1
    If you are not on kitkat this should not be a problem. Can you try to debug the sdcard state as explained here and post the results? http://developer.android.com/intl/es/reference/android/os/Environment.html#getExternalStorageDirectory() – bonnyz Oct 26 '15 at 10:18
  • 1
    @bonnyz I know it's not the complete test, but as a first quick feedback, just before trying to create the directory the following returns true: `Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState() )` (according to the code you linked, that should give write access). – Antonio Oct 26 '15 at 10:30
  • 1
    yes you're right. Did you managed to test on other devices? – bonnyz Oct 26 '15 at 10:34
  • 1
    Something wrong in /system/etc/permissions/platform.xml maybe. – Quark Oct 26 '15 at 10:39
  • 1
    @bonnyz With a Galaxy Note 4 (API21) it works. – Antonio Oct 26 '15 at 10:45
  • 1
    Maybe you are running out of space on the Samsung GT-I9506? Just guessing, try to check the available space and then reboot the phone. – bonnyz Oct 26 '15 at 10:46
  • 1
    @bonnyz Hmm... There's plenty of space and I rebooted several times. I have to investigate more about the history of this device with my colleagues. – Antonio Oct 26 '15 at 10:51
  • 1
    Yea I was just guessing ;) Keep us updated, I'm courious! – bonnyz Oct 26 '15 at 10:52
  • 1
    can you make a directory by handling in /storage/emulated/0/? and can you read files from getExternalStorageDirectory()? – xxxzhi Oct 26 '15 at 11:38
  • 1
    @Antonio Have you tried using mkdirs api? The File.mkdirs() method will create all needed directories; mkdir() will only create the last directory in the pathname.I think it may work and during debugging if USB option is selected as MTP or File Transfer then SDCard won't be available – Madhukar Hebbar Oct 26 '15 at 12:56
  • 1
    @MadhukarHebbar My code creates only one folder (no subfolder) in the directory returned by `getExternalStorageState()` – Antonio Oct 26 '15 at 14:05
  • 1
    @Antonio mkdirs will make sure all the folders are available/created. Have you checked whether storage is mounted by code like this `android.os.Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED);` – Madhukar Hebbar Oct 26 '15 at 14:08
  • 1
    @MadhukarHebbar If you see the code and explanation in the question, I am calling getExternalStorageState and the device results to be mounted. As explained above in the comments, `Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState‌​() )` also returns true. – Antonio Oct 26 '15 at 14:10
  • 1
    Please try this one once : http://stackoverflow.com/a/7439425/4596556 – Madhukar Hebbar Oct 26 '15 at 14:13
  • 1
    @Tron Sorry, I could not verify that because I cannot install a File Manager – Antonio Oct 27 '15 at 08:16
  • 1
    @Tron I am now able to access `/system/etc/permissions/platform.xml`, what should I look for? – Antonio Oct 30 '15 at 13:07
  • Look for android.permission.WRITE_EXTERNAL_STORAGE (internal storage should be ****, external SD card ). As it is on: http://www.sammobile.com/2013/08/11/android-4-3-on-galaxy-s4-google-edition-breaks-sd-card-writing-for-apps-heres-a-fix/ – Quark Oct 31 '15 at 16:00
  • This will help http://stackoverflow.com/questions/3853472/creating-a-directory-in-sdcard-fails – Sulabh Deep Puri Nov 02 '15 at 06:29
  • @Tron My /system/etc/permission/platform.xml seems to be ok in that section (it's exactly corresponding to the link you sent). – Antonio Nov 02 '15 at 09:52
  • @bonnyz It remained a mystery until the end :) – Antonio Nov 02 '15 at 10:04
  • 1
    @Antonio yet another Samsung tale! – bonnyz Nov 02 '15 at 10:15

4 Answers4

4

In my case I had to go under Settings -> Apps -> NameOfApp -> Permissions and activate the Storage permissions. I don't know why this comes deactivated by default if I have all the permissions on AndroidManifest.xml. I'm on a Moto G (3rd Gen) with Android Marshmallow 6.0.

Mostafiz
  • 7,243
  • 3
  • 28
  • 42
Mauricio
  • 839
  • 2
  • 13
  • 26
  • I found out why it comes deactivated by default. Since `Marshmallow` you have to request permissions at runtime. See [this nice tutorial](https://www.learn2crack.com/2015/10/android-marshmallow-permissions.html) – Mauricio May 29 '16 at 17:14
3

You first need to use file.mkdirs() instead of folder.mkdir().

And if it also not worked then you need to check if you can access the sdcard or not.

For checking you can use below method.

boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();

if (Environment.MEDIA_MOUNTED.equals(state)) {

    // We can read and write the media
    mExternalStorageAvailable = mExternalStorageWriteable = true;

} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {

    // We can only read the media
    mExternalStorageAvailable = true;
    mExternalStorageWriteable = false;

} else {

    // Something else is wrong. It may be one of many other states, but all we need
    //  to know is we can neither read nor write
    mExternalStorageAvailable = mExternalStorageWriteable = false;

}

Read at official document .

Hope it will give some clue to you.

KishuDroid
  • 5,411
  • 4
  • 30
  • 47
  • I already got [the same suggestion](http://stackoverflow.com/questions/33305100/cannot-create-directory-in-external-storage-although-permissions-are-apparently/33408627#comment54482064_33305100) from bonnyz, and [Madhukar Hebbar](http://stackoverflow.com/questions/33305100/cannot-create-directory-in-external-storage-although-permissions-are-apparently/33408627#comment54487944_33305100)... – Antonio Oct 29 '15 at 09:01
  • one last suggestion to see that what's problem. Try hard coded path "**/mnt/sdcard**" instead of "**Environment.getExternalStorageState()**". – KishuDroid Oct 29 '15 at 09:08
  • I am unable to create the directory also in "mnt/sdcard". – Antonio Oct 29 '15 at 10:10
  • Have you read the last section of the question (Update) and the comments below the question? :) Yes, I did, and the code works for other devices. – Antonio Oct 29 '15 at 10:41
  • I mean other device but having same model and API **Samsung GT-I9506 with Android 4.3 (API18) ** . – KishuDroid Oct 29 '15 at 10:43
  • No, I don't have another similar device. – Antonio Oct 29 '15 at 10:44
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/93667/discussion-between-kishudroid-and-antonio). – KishuDroid Oct 29 '15 at 10:44
  • @Antonio : Thanks for bounty..:) – KishuDroid Nov 03 '15 at 11:26
3

You can try this code. I have also emulated sd card on Lg g2 mini and I can only access external card in my package folder

for(File f : getExternalFilesDirs(null)){
    try {
        File f2 = new File(f.getAbsolutePath(), "testFile");

        Log.d("test log", "file path " + f2.getAbsolutePath());
        f2.createNewFile();
        Log.d("test log", "file exist " + f2.exists());
    } catch (IOException e) {
        Log.d("test log", "error");
    }
}

and output is:

D/test log? file path /storage/emulated/0/Android/data/my.awesome.package/files/testFile
D/test log? file exist true
D/test log? file path /storage/external_SD/Android/data/my.awesome.package/files/testFile
D/test log? file exist true
jan hruska
  • 249
  • 1
  • 9
  • Where do I find `getExternalFilesDirs`? I tried with `android.os.Environment.getExternalFilesDirs(null)` to no avail... – Antonio Oct 30 '15 at 15:06
  • Sry it was called from activity, you can call it directly from context and it is from api 19. On older version this problem probably not exists so it is ok. (dis)advantage of this is when your app is uninstalled, all files that it creates are also removed. – jan hruska Oct 30 '15 at 16:07
  • I am afraid here we're dealing with api 18 – Antonio Oct 30 '15 at 16:16
  • You are lucky, it is from api 19 http://developer.android.com/guide/topics/manifest/uses-permission-element.html . You even dont need write permission from 19 api, if this article is right – jan hruska Oct 30 '15 at 16:29
  • In which way am I lucky? :) – Antonio Oct 30 '15 at 16:31
  • you can make condition it api is 18 and less and access sd card old fashin way and if newer, you can use getExternalFilesDirs . I think it can work, with little praying – jan hruska Oct 30 '15 at 16:37
  • The point of this thread is that I have a very specific device with API 18 for which I cannot get a directory where my application can write. – Antonio Oct 30 '15 at 16:55
  • I have same issue with my app, I will probably use internal memory for older devices with emulated sd cards and without permissions to write to external sd card or maybe someone will tell us how to solve it.. – jan hruska Oct 30 '15 at 17:22
  • did you try to hardcode path, same as is in my log with yout package? It is not nice sollution, but it is interesting, if it is working. You can try to create file, and if it throw exception, then use internal memory – jan hruska Oct 30 '15 at 17:40
  • I cannot write on any memory, or any path – Antonio Oct 30 '15 at 22:37
0

Try this:

     final File externalStoragePublicDirectory = Environment.getExternalStorageDirectory();
     File file = new File(externalStoragePublicDirectory, "test");
     file.mkdirs();
Henry
  • 17,490
  • 7
  • 63
  • 98