Error: open failed: ENOENT (No such file or directory)

I was trying to create a file to save pictures from the camera, it turns out that I can't create the file. But I really can't find the mistake. Can you have a look at it and give me some advice?

    private File createImageFile(){
            File imageFile=null;
            String stamp=new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            File dir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            String imageFileName="JPEG_"+stamp+"_";
            try {
                imageFile=File.createTempFile(imageFileName,".jpg",dir);
            } catch (IOException e) {
                Log.d("YJW",e.getMessage());
            }
            return  imageFile;
        }

And I have added the permission.

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

The method always gives such mistakes:

open failed: ENOENT (No such file or directory)


Solution 1:

The Pictures directory might not exist yet. It's not guaranteed to be there.

In the API documentation for getExternalStoragePublicDirectory(), the code ensures the directory exists using mkdirs:

File path = Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");

try {
    // Make sure the Pictures directory exists.
    path.mkdirs(); 

...so it may be as simple as adding that path.mkdirs() to your existing code before you createTempFile.

Solution 2:

when a user picks a file from the gallery, there is no guarantee that the file that was picked was added or edited by some other app. So, if the user picks on a file that let’s say belongs to another app we would run into the permission issues. A quick fix for that is to add this code in the AndroidManifest.xml file:

<manifest ... >
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

Note: For Android 11 refer Scope storage Enforcement Policy https://developer.android.com/about/versions/11/privacy/storage

Solution 3:

Replace:

Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES)

With:

private File createImageFile() throws IOException {
        // Create an image file name

make sure you call:

mkdirs() // and not mkdir()

Here's the code that should work for you:

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = new File(Environment.getExternalStorageDirectory().toString(), "whatever_directory_existing_or_not/sub_dir_if_needed/");
        storageDir.mkdirs(); // make sure you call mkdirs() and not mkdir()
        File image = File.createTempFile(
                imageFileName,  // prefix
                ".jpg",         // suffix
                storageDir      // directory
        );

        // Save a file: path for use with ACTION_VIEW intents

        mCurrentPhotoPath = "file:" + image.getAbsolutePath();
        Log.e("our file", image.toString());
        return image;
    }

I had a bad experience following the example given in Android Studio Documentation and I found out that there are many others experiencing the same about this particular topic here in stackoverflow, that is because even if we set

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

the problem persists in some devices.

My experience was that the example worked when I tried it in debug mode, after that 3 more tests it so happened that my SD suddenly was corrupted, but I don't think it has to do with their example (funny). I bought a new SD card and tried it again, only to realize that still both release and debug mode did the same error log: directory does not exist ENOENT. Finally, I had to create the directories myself whick will contain the captured pictures from my phone's camera. And I was right, it works just perfect.

I hope this helps you and others out there searching for answers.

Solution 4:

A quick fix for that is to add this code in the AndroidManifest.xml file:

<manifest ... >
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

Note: Applicable for API level 29 or Higher

Solution 5:

I used the contentResolver with the URI and it worked for me. Saw it in another SO post which i can't find.

private String getRealPathFromURI(Uri contentURI) {
    String result;
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) {
        result = contentURI.getPath();
    } else {
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

hope it helps....