23

I have switched my app to target API 27 and now it can't be granted WRITE_EXTERNAL_STORAGE permission -- grantResult is always -1.

My app needs this permission since it doesn't use apps private external storage space (which doesn't require WRITE_EXTERNAL_STORAGE starting from API 19).

I know that in API 26 there have been behavior changes for permissions. However this doesn't explain my problem.

I'm requesting both READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions in a standard way:

ActivityCompat.requestPermissions(activity, new String[] {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
    }, requestCode);

(both permissions are declared via <uses-permission in manifest).

The dialog appears and I click "Allow":

enter image description here

However inside onRequestPermissionsResult callback I'm getting a -1(denied) for WRITE_EXTERNAL_STORAGE (and 0 (granted) for READ_EXTERNAL_STORAGE).

Shouldn't the result be 0 for both since I have requested and, presumably, granted both?

I have tried to request WRITE_EXTERNAL_STORAGE alone, but in this case the dialog doesn't appear at all.

One more detail: I have just checked the merged manifest in build/intermediates/manifests/full/debug and noticed that WRITE_EXTERNAL_STORAGE permission has attribute android:maxSdkVersion="18" (there is no such attribute in my manifest). This could be happening because my app has minApiVersion=21, but I'm not sure.

  • "both permissions are declared via – CommonsWare Apr 07 '18 at 16:25
  • 4
    @CommonsWare Yes, both are in the manifest. However, I have just checked the merged manifest in `build/intermediates/manifests/full/debug` and noticed that `WRITE_EXTERNAL_STORAGE` permission has attribute `android:maxSdkVersion="18"` (there is no such attribute in my manifest). Can this be causing the issue? – Denys Kniazhev-Support Ukraine Apr 07 '18 at 16:47
  • 6
    Ah, that could be the problem. Presumably, some library has that, and it is getting merged in. Try adding `tools:remove="android:maxSdkVersion"` on your `` element, and see if that fixes it. – CommonsWare Apr 07 '18 at 16:53
  • I believe read/write belong to the same permissiongroup and thus only one of them needs to be granted. But I might remember wrong on that. – Ch4t4r Apr 07 '18 at 16:55
  • @Ch4t4r: They changed that behavior in 8.0 -- even though they are in the same permission group, you still need to request runtime permissions for both of them. – CommonsWare Apr 07 '18 at 16:58
  • 2
    @CommonsWare it worked! Probably manifest merger has been adding `maxSdkVersion=18` because my `minSdkVersion` is `21`. This feels counterintuitive and is worth filing a bug to google. I have updated the question with the information about the merged manifest. If you post your suggestion as an answer I'll gladly accept it. Thanks! – Denys Kniazhev-Support Ukraine Apr 07 '18 at 17:05
  • 2
    Glad to hear that it is working. I'll make a point to blog about this next week. – CommonsWare Apr 07 '18 at 17:10

2 Answers2

46

Somewhere along the line, you are picking up that android:maxSdkVersion="18" attribute. My guess is that it is coming from a library. Check the "Merged Manifest" tab in Android Studio, when you are editing your own manifest. It will have details of what is contributing the various elements and attributes.

android:maxSdkVersion has the effect of removing your <uses-permission> element on higher Android SDK versions, at least in terms of how runtime permissions work.

Since you need this permission for all versions, adding tools:remove="android:maxSdkVersion" on the <uses-permission> element should revert the android:maxSdkVersion="18" and give you what you expect.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
0

I noticed a space in my permission in manifest, it was <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE "/> and I changed it to <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> and problem solved.