28

i need to save an image from camera on android. i used the write external storage permission in manifest and i am using this code

File dir = new File(Environment.getExternalStorageDirectory(), "Test");
if (!dir.exists() || !dir.isDirectory())
    dir.mkdirs();

String path = dir.getAbsolutePath();
Log.d(TAG, path);                     //log show the path
File file = new File(dir.getAbsolutePath() + "/Pic.jpg");
Log.d(TAG, file.getAbsolutePath());   //again path is shown here

outStream = new FileOutputStream(file);
outStream.write(bytes);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + bytes.length);   //fail here
} catch (FileNotFoundException e) {
Log.d(TAG, "not done");                       //error is here (this exception is thrown)
} catch (IOException e) {
Log.d(TAG, "not");
} finally {  }

i also tried mkdir() instead of mkdirs() same result.

any idea what went wrong in the code?

thanks

lallous34
  • 483
  • 1
  • 4
  • 12
  • 5
    Perhaps [you do not have runtime permissions implemented](https://stackoverflow.com/questions/32635704/android-permission-doesnt-work-even-if-i-have-declared-it). Beyond that, **never catch an exception without logging it**. Add `e` as a third parameter to your `Log.d()` calls, then use LogCat to examine the Java stack trace associated with your crash. – CommonsWare Oct 17 '16 at 13:14
  • Could you show us the stacktrace ? – ToYonos Oct 17 '16 at 13:18
  • 3
    `if (!dir.exists() || !dir.isDirectory()) dir.mkdirs();`. Nice example of bad code. First if it is indeed not a directory, hence a file mkdirs will not convert that file to a directory. Second you should check the return value of mkdirs as it might fail. Which it did by the way. – greenapps Oct 17 '16 at 17:30
  • 1
    Try this it may be work stackoverflow.com/a/41221852/5488468 – Bipin Bharti Jan 03 '17 at 11:21
  • nice question! Helpful – Androider Dec 25 '20 at 07:29

11 Answers11

62

For those not as experienced like me. I fought this issue, lost hair for some time. I am targeting api 21 (for compatibility sake) and it worked on lollipop but on marshmallow it would not create the directory. I did have the "uses" permission in the manifest but it still would not work. Apparently in Marshmallow when you install with Android studio it never asks you if you should give it permission it just quietly fails, like you denied it. You must go into Settings, apps, select your application and flip the permission switch on.

protocolkey
  • 636
  • 6
  • 3
  • 3
    Try this it may be work stackoverflow.com/a/41221852/5488468 – Bipin Bharti Jan 03 '17 at 11:20
  • @RobbyPatel thank you for this. it worked like a charm. but i have a question if i need 2 permissions (lets say storage and camera). and i use this code to check permission, it check for the first one but not checking for the other. is there a way to do that? – lallous34 Jan 13 '17 at 08:25
  • can put permission in array? – Bipin Bharti Jan 13 '17 at 09:15
  • This resolves allowing logback to write out the file. How do you retrieve it from a device running 6.0? From all I've read- you cannot. Or perhaps, the only use for a file appender is with a device emulator (whcih works fine). – XMAN Nov 20 '17 at 17:28
  • My app was the device owner, so I assumed it would not have any issue with permissions. I was dead wrong. This solved it. – OoDeLally Aug 05 '19 at 11:08
44

Some one like me who was trying in Android10. Please use below API in manifest:

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

Latest Update From Google: After you update your app to target Android 11, the system ignores the requestLegacyExternalStorage flag.

Navinpd
  • 772
  • 7
  • 15
7

IDIOT ME! i have used the Manifest Permission but when installed the app on phone i didnt grant permission for storage!... i understand a negative on this question... but i hope if someone else face the same..check your phone permission. sorry all for inconvenience.

lallous34
  • 483
  • 1
  • 4
  • 12
7

Did you put

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

in your AndroidManifest? If you are using android M you must request user permission to write on sd, look here an example

mcatta
  • 481
  • 5
  • 12
3

you have created directory, not file. Create new file with following code

File file = new File(dir.getAbsolutePath() + "/Pic.jpg");
file.createNewFile()
Ravi
  • 34,851
  • 21
  • 122
  • 183
3

if you are testing on android M, you should probably check Settings > App > Permission to see if permission to access storage is granted. This saved me.

Eaweb
  • 811
  • 1
  • 12
  • 16
2

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+

1

Starting from API 30 you can only write in your app-specific files

 File dir = new File(context.getFilesDir(), "YOUR_DIR");
 dir.mkdirs();

or in the external storage of your app Android/data

File dir = new File(myContext.getExternalFilesDir("FolderName"),"YOUR_DIR");

UPDATE

this answer provided another solution https://stackoverflow.com/a/65744517/8195076

UPDATE

another way is to grant this permission in manifest

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

like this answer https://stackoverflow.com/a/66968986/8195076

Wowo Ot
  • 1,362
  • 13
  • 21
0

Try this. Provide runtime permission for marshmallow it is perfectly work in my Application code :

 private String getFilename(String strFileName) {
        String filepath = Environment.getExternalStorageDirectory().getPath();
        File fileBase = new File(filepath, "Test");
        if (!fileBase.exists()) {
            fileBase.mkdirs();
        }
        return (file.getAbsolutePath() + "/" + strFileName + file_exts[currentFormat]);
    }

new File(getFilename(edt.getText().toString().trim()))
Mayur Patel
  • 2,300
  • 11
  • 30
0

outputFile = new File(apkStorage + "/" + downloadFileName ); //Create Output file in Main File

            //Create New File if not present
            if (!outputFile.exists()) {
                isExternalStorageWritable();
                outputFile.getParentFile().mkdirs();
                outputFile.createNewFile();
                Log.e(TAG, "File Created");
                OutputStream fos = new FileOutputStream(outputFile);//Get OutputStream for NewFile Location
                InputStream fis = c.getInputStream();//Get InputStream for connection
                byte[] buffer = new byte[1024];//Set buffer type
                int len1 = 0;//init length
                while ((len1 = fis.read(buffer)) >0) {
                    fos.write(buffer, 0, len1);//Write new file
                }

                //Close all connection after doing task
                fos.close();
                fis.close();

I wrote this code for creating a file, but it is not working in android 11

  • Please provide more info. Is there some logcat error? The code used to work in older Android versions? Have you debugged step by step to see what is happening in each step? – Iogui May 12 '21 at 21:08
0

when writing code for android API 29 and above use the following permission in your application manifest (AndroidManifest.xml)

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

Adjust your code to read like the following

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

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());

    file = new File(Environment.getExternalStorageDirectory().getPath(), "TestDirectory/Document/");
    if (!file.exists()) {
        try {
            file.mkdirs();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
Dharman
  • 30,962
  • 25
  • 85
  • 135