Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WRITE_EXTERNAL_STORAGE not working on lollipop even though it's set in the manifest

I'm trying to save images from the apps local data folders to external storage. My manifest contains the following (before the manifest's application tags):

<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23" />

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

When I try the following

try {
        InputStream in = new FileInputStream(filePath);
        File outPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        File outFile = new File(outPath, "mypicture.jpg");


        //try fails at this line
        OutputStream out = new FileOutputStream(outFile);

        byte[] buf = new byte[1024];
        int len;

        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }

        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
} catch (IOException e) {
    e.printStackTrace();
}

I get this error:

java.io.FileNotFoundException: /storage/emulated/0/Pictures/mypicture.jpg: open failed: EACCES (Permission denied)

I've also tried a slightly different output path instead:

 String sdCardPath = Environment.getExternalStorageDirectory() + "/MyFolder";
 new File(sdCardPath).mkdirs();
 File outFile = new File(sdCardPath, "mypicture.jpg");

but that gives me an error too:

java.io.FileNotFoundException: /storage/emulated/0/MyFolder/mypicture.jpg: open failed: ENOENT (No such file or directory)

The device is running Android 4.4.2, so shouldn't need to request permissions at runtime (as far as I'm aware it can't request them).

Is there something else that could be missing in order to allow saving a file to external storage?

like image 591
TheBestBigAl Avatar asked Jan 09 '17 16:01

TheBestBigAl


People also ask

How do I declare permissions in Android manifest?

Add declaration to app manifest To declare a permission that your app might request, include the appropriate <uses-permission> element in your app's manifest file. For example, an app that needs to access the camera has this line in AndroidManifest. xml : <manifest ...>

How do I give permission to internal storage on Android?

Storage permissions Android defines two permissions related to storage: READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE . As you can see, permissions are only defined for accessing external storage. That means that every app, by default, has permissions to access its internal storage.

How do I set storage permissions in Android 11?

On the Settings > Privacy > Permission manager > Files and media page, each app that has the permission is listed under Allowed for all files. If your app targets Android 11, keep in mind that this access to "all files" is read-only.


1 Answers

The cause of the issue was an external library pulled in via gradle which had its own manifest requesting <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18">

My own manifest only worked if maxSdkVersion="18" was NOT included, and so the manifest merger adding that param caused this error. My solution was to change my own manifest to:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="23" tools:replace="android:maxSdkVersion" />

I assume that the maxSdkVersion="18" meant that any devices running SDK 19-22 could not have this permission (with 23+ being able to request it at runtime).

like image 81
TheBestBigAl Avatar answered Nov 15 '22 17:11

TheBestBigAl