6

This is driving me crazy. I have tried all kinds of syntaxes but both mkdir() and mkdirs() return false.

My code:

String extStorageDirectory = Environment.getExternalStorageDirectory().toString();

File folder = new File(extStorageDirectory, "myportal");
boolean bool = folder.mkdir();

File pdfFile = new File(folder, fileName);

try{
    pdfFile.createNewFile();
}catch (IOException e){
    e.printStackTrace();
}
FileDownloader.downloadFile(fileUrl, pdfFile);

I was getting and IOException: No such file or directory when trying to create the file. The logcat part showed me that no directory was created:

Log.d("BG", "URL: " + fileUrl);
Log.d("BG", "pdfFile: " + pdfFile);
Log.d("BG", "Ext Storage: " + extStorageDirectory);
Log.d("BG", "Ext storage state: " + Environment.getExternalStorageState().toString());
Log.d("BG", "Mkdir return: " + bool);
Log.d("BG", "IsDirectory: " + folder.isDirectory());

And what is printed:

05-26 22:43:03.797 19364-30646/com.kristmiha.myportal2 D/BG: URL: http://192.168.100.65:80/myportal/upload/orari.pdf
05-26 22:43:03.798 19364-30646/com.kristmiha.myportal2 D/BG: pdfFile: /storage/emulated/0/myportal/orari.pdf
05-26 22:43:03.798 19364-30646/com.kristmiha.myportal2 D/BG: Ext Storage: /storage/emulated/0
05-26 22:43:03.804 19364-30646/com.kristmiha.myportal2 D/BG: Ext storage state: mounted
05-26 22:43:03.805 19364-30646/com.kristmiha.myportal2 D/BG: Mkdir return: false
05-26 22:43:03.805 19364-30646/com.kristmiha.myportal2 D/BG: IsDirectory: false

I've double checked permissions and I've put them in the right place. I think I read somewhere that after KitKat we are not allowed to write in the external storage, but have found no solution yet.

Aleksandar G
  • 1,163
  • 2
  • 20
  • 25
user3484582
  • 557
  • 1
  • 6
  • 22
  • Why are you trying to create the directories? – Michael Aaron Safyan May 26 '16 at 21:43
  • Trying to download a file and then open it. – user3484582 May 26 '16 at 21:44
  • What version of Android are you testing on? See also https://stackoverflow.com/questions/32635704/android-permission-doesnt-work-even-if-i-have-declared-it and https://commonsware.com/blog/2015/08/31/hey-where-did-my-permission-go.html – CommonsWare May 26 '16 at 21:45
  • I'm testing on 6.0.1.Thank you, will take a look! – user3484582 May 26 '16 at 21:49
  • Can you look my answer its working good for me : http://stackoverflow.com/questions/36916703/how-to-create-a-directory-and-save-a-picture-to-it-in-android/36917734#36917734 – Yasin Kaçmaz May 26 '16 at 21:49
  • Do you have accepted the RuntimePermission before doing the write process? – Vincent D. May 26 '16 at 22:00
  • I'm looking into that now. Implementing `requestPermission()` in my app. Will get back with the result – user3484582 May 26 '16 at 22:03
  • Well I just implemented `requestPermission()` and the same happens. I got the dialog asking for permissions when I launched the app, pressed accept, and I'm using logcat with `checkSelfPermissions()` which returns 0, meaning the permissions are granted. Any more ideas? – user3484582 May 26 '16 at 23:32
  • I resolved it by this, Open this answer it will help you : https://stackoverflow.com/a/61360528/6826102 – Chirag Prajapati Aug 16 '20 at 15:00

8 Answers8

9

Applicable only if your targetSdkVersion 29

Environment.getExternalStorageDirectory() is deprecated in API level 29.

To get the same functionality use this line

File mediaStorageDir = context.getExternalFilesDir(null);

If you have checked all the possible error then try this fix.

Priyankchoudhary
  • 786
  • 9
  • 12
  • 1
    For targetSdkVersion 29, there may be some differences. getExternalFilesDir(null) is the directory of the app which is created in .../Android/data/ with app-package-name. If someone's old app created some directory in other place, such like in root. This answer cannot cover the issue because they are two different directories. A temporary solution should be this: https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage – Fisher Sep 19 '20 at 15:54
5

Creating external storage directories requires the WRITE_EXTERNAL_STORAGE permission; without this permission, attempts to write external storage will fail. Also, not all directories are necessarily writable; use getExternalStoragePublicDirectory() to get a directory that has shared write access (other external directories may be read-only). However, if the purpose of writing to external storage is to share the file with other applications, you should strongly consider using the FileProvider API, instead (see also Setting Up File Sharing); with this strategy, your app stores files in its own, internal app-specific directories, but then enables selective sharing of these files to other apps through a content provider. This strategy provides greater security for the files and also makes it possible for you to provide greater access control over reading/writing of the files.

Since you say that you already have the required permission*, most likely where you are getting things wrong is in the call to toString(). There is no guarantee that the toString() method on a file returns its full path. Use getPath() or getAbsolutePath() when concatenating these. It is also advisable, when choosing to write to external storage, that you first check its state; the external storage can in some cases be ejected/unmounted and not available.

*You should verify this with ContextCompat.checkSelfPermission(). You should add a call to requestPermissions() if the permissions are not present.

Michael Aaron Safyan
  • 93,612
  • 16
  • 138
  • 200
  • 1
    I have used the write external storage permission and I've double checked it's in the right place. Will take a look at what you recommend though – user3484582 May 26 '16 at 21:53
  • I have tried those too. Nonetheless, if you see the logcat, the filepath looks correct, right? – user3484582 May 26 '16 at 21:55
  • @user3484582 true. It's possible that your app simply doesn't have permission to that directory. The getExternalStoragePublicDirectory() method (which takes a parameter indicating the type of file), will likely get you a directory to which you actually have write permission [assuming you intend to use shared storage rather than writing internally]. – Michael Aaron Safyan May 26 '16 at 21:58
  • If you see my original post I do check its state with the logcat and it's mounted. I just implemented `requestPermission()` and the same happens. I got the dialog asking for permissions when I launched the app, pressed accept, and I'm using logcat with `checkSelfPermissions()` which returns 0, meaning the permissions are granted. Any more ideas? – user3484582 May 26 '16 at 23:33
  • @user3484582 in addition to printing folder.isDirectory(), can you print folder.exists()? I'm wondering if you're attempting to create a directory with the name of an existing file. – Michael Aaron Safyan May 26 '16 at 23:42
  • I ended up using `getExternalStoragePublicDirectory()` as I don't want my file to be private and it works like a charm. The problem wasn't that the folder didn't exist, otherwise it would work, as it working with `getExternalStoragePublicDirectory()`. Got one question though. Browsing through the directory in my phone's file manager, I can't actually locate those folders. EDIT: It's in my downloads folder. Thanks for the help! – user3484582 May 26 '16 at 23:45
2

try this:

String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File folder = new File(extStorageDirectory, "pdf");
folder.mkdir();

in manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com....">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

also if you are testing on android 6.0 + api 23 there is changes in rights, you must request some of them on runtime, manifest declaration is ignored )

Stepan Maksymov
  • 2,618
  • 19
  • 31
  • What is this the difference of this code to mine? Apart from changing the folder name? I have already put the permissions on the manifest file. – user3484582 May 26 '16 at 21:51
  • 1
    if you are testing on android 6.0 + starting from api 23 some of rights can be requested ONLY in runtime. – Stepan Maksymov May 26 '16 at 22:00
  • Well I just implemented `requestPermission()` and the same happens. I got the dialog asking for permissions when I launched the app, pressed accept, and I'm using logcat with `checkSelfPermissions()` which returns 0, meaning the permissions are granted. Any more ideas? – user3484582 May 26 '16 at 23:34
  • did you ever fix this? – 68060 Jan 12 '18 at 09:13
  • what do you mean by fix? - i wrote above that you must request rights write external storage live, right before attempt to create directory ) search please how to check rights, and do actions on rights request results. – Stepan Maksymov Jan 17 '18 at 12:31
1

One more possible reason: Environment.getExternalStorageDirectory() is deprecated in API level 29

1

if you already allowed R/W permission(Runtime Permission too) and still doesn't work add this below mentioned line in your AndroidManifest.xml

<application ........ ........ android:requestLegacyExternalStorage="true"> Note: this must required if you'r targeting Android 10+

0

If you're target Android api 29 add this line in the AndroidManifest <application android:requestLegacyExternalStorage="true">

Also Environment.getExternalStorageDirectory() is deprecated in api 29 use this instead

File mediaStorageDir = context.getExternalFilesDir(null);
0

I had same issue, tried many things but finally fixed with this: add android:requestLegacyExternalStorage="true" into your Manifest file inside Application tag.

 <application
    .
    .
    .
    android:requestLegacyExternalStorage="true">
Vishva Vijay
  • 340
  • 3
  • 11
-1

just remove .toString() like:

String extStorageDirectory = Environment.getExternalStorageDirectory().toString();

to

String extStorageDirectory = Environment.getExternalStorageDirectory();

薛宇涛
  • 1
  • 1