59

I have been trying to create a directory in /sdcard programmatically, but it's not working. The code below always outputs directory not created.

boolean success = (new File("/sdcard/map")).mkdir(); 
if (!success) {
    Log.i("directory not created", "directory not created");
} else {
    Log.i("directory created", "directory created");
}
Nikhil
  • 16,194
  • 20
  • 64
  • 81
sajjoo
  • 6,576
  • 20
  • 65
  • 86

13 Answers13

152

There are three things to consider here:

  1. Don't assume that the sd card is mounted at /sdcard (May be true in the default case, but better not to hard code.). You can get the location of sdcard by querying the system:

    Environment.getExternalStorageDirectory();
    
  2. You have to inform Android that your application needs to write to external storage by adding a uses-permission entry in the AndroidManifest.xml file:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
  3. If this directory already exists, then mkdir is going to return false. So check for the existence of the directory, and then try creating it if it does not exist. In your component, use something like:

    File folder = new File(Environment.getExternalStorageDirectory() + "/map");
    boolean success = true;
    if (!folder.exists()) {
        success = folder.mkdir();
    }
    if (success) {
        // Do something on success
    } else {
        // Do something else on failure 
    }
    
SeyedPooya Soofbaf
  • 2,654
  • 2
  • 29
  • 31
Gopinath
  • 12,981
  • 6
  • 36
  • 50
  • 8
    Before Froyo, SD card was mounted at /sdcard. From Froyo onwards, the sd card is mounted at /mnt/sdcard and a soft link is created to /sdcard so that applications will still behave properly despite the change in mount point. – Gopinath Oct 04 '10 at 11:00
  • 2
    For some reason this code doesn't work for me on my myTouch phone...hmm the .mkdir() always returns false. – JPM Sep 01 '11 at 22:24
  • 3
    I think you should check the permission and that the disk is not mounted on the PC file system. – Gopinath Sep 05 '11 at 12:06
  • Where exactly in the XML file should I place the uses-permission block? – Tomáš Zato Feb 12 '16 at 11:57
  • It should be a sibling of the application element in the AndroidManifest. – Arthur Thompson Jul 29 '16 at 20:54
  • 1
    I had similar issue and found out that if my phone is connected to my computer via USB, it fails to create the directory. When I disconnected my phone and ran the app again, it created the folder and files properly. – Kamran Bigdely Oct 14 '16 at 17:16
28

I had same issue after I updated my Android phone to 6.0 (API level 23). The following solution works on me. Hopefully it helps you as well.

Please check your android version. If it is >= 6.0 (API level 23), you need to not only include

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

in your AndroidManifest.xml, but also request permission before calling mkdir(), using code such as the following that I’ve copied in here from https://developer.android.com/training/permissions/requesting.html

public static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
= 1; public int mkFolder(String folderName){ // make a folder under Environment.DIRECTORY_DCIM
    String state = Environment.getExternalStorageState();
    if (!Environment.MEDIA_MOUNTED.equals(state)){
        Log.d("myAppName", "Error: external storage is unavailable");
        return 0;
    }
    if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
        Log.d("myAppName", "Error: external storage is read only.");
        return 0;
    }
    Log.d("myAppName", "External storage is not read only or unavailable");

    if (ContextCompat.checkSelfPermission(this, // request permission when it is not granted. 
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        Log.d("myAppName", "permission:WRITE_EXTERNAL_STORAGE: NOT granted!");
        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

            // Show an expanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.

        } else {

            // No explanation needed, we can request the permission.

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);

            // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    }
    File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),folderName);
    int result = 0;
    if (folder.exists()) {
        Log.d("myAppName","folder exist:"+folder.toString());
        result = 2; // folder exist
    }else{
        try {
            if (folder.mkdir()) {
                Log.d("myAppName", "folder created:" + folder.toString());
                result = 1; // folder created
            } else {
                Log.d("myAppName", "creat folder fails:" + folder.toString());
                result = 0; // creat folder fails
            }
        }catch (Exception ecp){
            ecp.printStackTrace();
        }
    }
    return result; }

@Override public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    } }
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • The runtime permission request is needed only when you are targeting SDK 23 and higher. When application targets lower SDKs, no runtime requests are necessary and ContextCompat.checkSelfPermission will always return true in this particular case. – d.aemon Oct 12 '16 at 11:53
  • Thanks! Does all permissions has to be provided like this? Or this is required only for permissions related to storage? – balaaagi Nov 28 '16 at 17:24
  • @BalajiSrinivasan, no! only for so-called 'Dangerous permissions'. Check the link at the bottom of my answer to see who they are. –  Dec 05 '16 at 11:37
  • Finally!! I have been searching all day for this information trying to figure out why I'm getting this "fail readDirectory() errno=13" message after specifying permissions in my manifest. Thank you!! – Amber Dec 15 '16 at 23:52
  • I am pretty dense, so this post wasn't quite enough for me. Here is the video I eventually found that demonstrates how to request for permissions really clearly - https://www.youtube.com/watch?v=C8lUdPVSzDk – Shadoninja Apr 09 '17 at 03:22
  • Hi, this post helped me lot not to have exception, and the folder, files to be created. BUT i still cannot see my folder and the files inside. I want to make a new folder in Documents folder, and save my files there. Any idea? device is restarted ... – pillesoft Jul 06 '17 at 12:02
  • Hey Pillesoft, What is your API level? did you see any pop-up for asking your permission to write from Android after you use the code above? If you see them, you should click 'yes'. Thus you grand the permission to write then call mkdir(). Otherwise there might be some errors in your implementation. GL –  Jul 07 '17 at 12:48
  • So essentially https://developer.android.com/training/data-storage/files is not up to date, it doesn't mention runtime permissions :/. – robinst Nov 27 '18 at 08:05
16

The correct path to the sdcard is

/mnt/sdcard/

but, as answered before, you shouldn't hardcode it. If you are on Android 2.1 or after, use

getExternalFilesDir(String type) 

Otherwise:

Environment.getExternalStorageDirectory()

Read carefully https://developer.android.com/guide/topics/data/data-storage.html#filesExternal

Also, you'll need to use this method or something similar

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;
}

then check if you can access the sdcard. As said, read the official documentation.

Another option, maybe you need to use mkdirs instead of mkdir

file.mkdirs()

Creates the directory named by the trailing filename of this file, including the complete directory path required to create this directory.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Maragues
  • 37,861
  • 14
  • 95
  • 96
  • 2
    There is no `getExternalFilesDir()` on `Environment` in any version of Android. You may be thinking of `getExternalFilesDir()` on `Context`, which was added in 2.2. However, that method is somewhat broken -- the directory it gives you will have its contents deleted during an app upgrade. I hope this will be fixed in Gingerbread. – CommonsWare Oct 04 '10 at 11:00
  • Thx, fixed. I quickly browsed through the data storage section and assumed it was accessed just as getExternalStorageDirectory(), which is what I use. – Maragues Oct 04 '10 at 11:07
  • As mentioned i have tested the state. state shows me mounted but i unable to create a folder – Amit Thaper Feb 13 '14 at 13:20
15

Restart your Android device. Things started to work for me after I restarted the device.

Uriel Frankel
  • 14,304
  • 8
  • 47
  • 69
  • I think that I debugged my app and one of the writing locks got locked, and never released. – Uriel Frankel Feb 19 '15 at 13:26
  • Use mediaScan or sendbroadcast to Media_mount in order to refresh media store with new directories http://stackoverflow.com/questions/3300137/how-can-i-refresh-mediastore-on-android – shehzy Jul 08 '15 at 06:53
7

If this is happening to you with Android 6 and compile target >= 23, don't forget that we are now using runtime permissions. So giving permissions in the manifest is not enough anymore.

Kuno
  • 3,492
  • 2
  • 28
  • 44
6

use mkdirs() instead of mkdir()..it worked for me :)

File folder = new File(Environment.getExternalStorageDirectory()+"/Saved CGPA");
if(!folder.exists()){
    if(folder.mkdirs())
    Toast.makeText(this, "New Folder Created", Toast.LENGTH_SHORT).show();
}

File sdCardFile = new File(Environment.getExternalStorageDirectory()+"/Saved CGPA/cgpa.html");
Bala Vishnu
  • 2,588
  • 23
  • 20
3

in android api >= 23

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

instead of

    <app:uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Vahe Gharibyan
  • 5,277
  • 4
  • 36
  • 47
1

Do you have the right permissions to write to SD card in your manifest ? Look for WRITE_EXTERNAL_STORAGE at http://developer.android.com/reference/android/Manifest.permission.html

Matthieu
  • 16,103
  • 10
  • 59
  • 86
  • yes i have added this line in manifest file in application tag but still it does not creating the directory. – sajjoo Oct 04 '10 at 08:43
  • If you are running your application using api 23, you have first to request permission from user https://developer.android.com/training/permissions/requesting.html – Bishoy Fakhry Jun 27 '16 at 10:02
  • Bishoy - That's not exactly true. You must request permission in runtime only when you are targeting API 23 and above. If you're targeting lower SDK, you don't have to request runtime permission even when running on SDK 23+ – d.aemon Oct 12 '16 at 12:04
1

Isn't it already created ? Mkdir returns false if the folder already exists too mkdir

fedj
  • 3,452
  • 1
  • 22
  • 21
1

There are Many Things You Need to worry about 1.If you are using Android Bellow Marshmallow then you have to set permesions in Manifest File. 2. If you are using later Version of Android means from Marshmallow to Oreo now Either you have to go to the App Info and Set there manually App permission for Storage. if you want to Set it at Run Time you can do that by below code

public  boolean isStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
    if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
            == PackageManager.PERMISSION_GRANTED) {
        Log.v(TAG,"Permission is granted");
        return true;
    } else {

        Log.v(TAG,"Permission is revoked");
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        return false;
    }
}
else { //permission is automatically granted on sdk<23 upon installation
    Log.v(TAG,"Permission is granted");
    return true;
}

}

Nadeem Bhat
  • 1,032
  • 7
  • 10
0

I made the mistake of including both:

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

and:

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

in the above order. So when I took out the second permission, (READ), the problem went away.

honk
  • 9,137
  • 11
  • 75
  • 83
  • I Included both the WRITE_EXTERNAL_STORAGE and the READ_EXTERNAL_STORAGE permissions. You only need the first one. – user2638345 Jan 31 '14 at 15:22
0
File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
        + "/FoderName");
if (!f.exists()) {
    f.mkdirs();
}
0

If the error happens with Android 6.0 and API >=23 ; Giving permission in the AndroidManifest.xml is not alone enough.

You have to give runtime permissions, you can refer more here Runtime Permission

                       (or)

Google has a new feature on Android Q: filtered view for external storage. A quick fix for that is to add this code in the AndroidManifest.xml file:

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

    <!-- This attribute is "false" by default on apps targeting Android Q. -->
    <application android:requestLegacyExternalStorage="true">
     ...
     ...
    </application>
</manifest>

You can read more about it here: https://developer.android.com/training/data-storage/compatibility


Internal Storage vs Seconday Storage

The internal storage is referred to as "external storage" in the API ; not the "secondary storage"

Environment.getExternalStorageDirectory();

As mentioned in the Environment Documentation

Saravanan
  • 11
  • 2