You Cannot Hold Non-Existent Permissions
Stack Overflow user skirix ran into
an interesting problem
last week with respect to the Android 6.0 runtime permission system.
Calling ActivityCompat.requestPermissions()
was always
returning that the permission was denied, when running on older devices.
It turns out that the permission was READ_EXTERNAL_STORAGE
and
the devices that ActivityCompat.requestPermissions()
was failing on
ran Android 4.0 or older.
The reason this does not work is simple: READ_EXTERNAL_STORAGE
did
not exist back then. It was added to the SDK in Android 4.1 (API Level 16).
ActivityCompat.requestPermissions()
will use the real requestPermissions()
implementation on Android 6.0+. On older devices, though, rather than
hard-coding a response of PERMISSION_GRANTED
, ActivityCompat.requestPermissions()
will ask PackageManager
to see if you hold the permission. That’s fine,
but it does mean that you have to pay attention to when permissions
you seek were added to Android. PackageManager
will not know about
READ_EXTERNAL_STORAGE
on pre-Android 4.1 devices, and so you will be
told that you do not have the permission… even though you do not need
the permission back then.
In other words, there are limits to the backwards compatibility offered
by ActivityCompat.requestPermissions()
. The method can be called going
back to API Level 4, but the results may vary based upon when that
permission was added to the system.
In this case, since external storage certainly predated API Level 16,
the right answer is to only bother calling ActivityCompat.requestPermissions()
for READ_EXTERNAL_STORAGE
on API Level 16+, and behave as though you
have it on older devices. You will probably just handle this case when
you call ContextCompat.checkSelfPermission()
(which also will suffer
from the same problem as ActivityCompat.requestPermissions()
):
if (Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN ||
ContextCompat.checkSelfPermission(READ_EXTERNAL_STORAGE)==PackageManager.PERMISSION_GRANTED) {
// you're good, go ahead
}
else {
// do the request-permissions thing
}
This is just another one of those “gotcha” cases that we will run into over the next several months as we work out the application of the Android 6.0 runtime permissions to more and more scenarios.