this is regarding the new model of runtime permissions introduced in Android Marshmallow when requesting Manifest.permission.WRITE_EXTERNAL_STORAGE
permission.
In short, what I am experiencing is that if I request (and the user allows) Manifest.permission.WRITE_EXTERNAL_STORAGE
permission, the app won't be able to read and write from the external storage directory until I destroy and restart the app.
This is what I am doing/experiencing:
My app starts from a state where:
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
This is, I don't have permissions to to access external storage.
Then, I request permission to Manifest.permission.WRITE_EXTERNAL_STORAGE just as Google explains
private void requestWriteExternalStoragePermission() {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(this)
.setTitle("Inform and request")
.setMessage("You need to enable permissions, bla bla bla")
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MendeleyActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_PERMISSION_WRITE_EXTERNAL_STORAGE);
}
})
.show();
} else {
ActivityCompat.requestPermissions(MendeleyActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_PERMISSION_WRITE_EXTERNAL_STORAGE);
}
}
Once the user allows the permission, onRequestPermissionsResult
gets invoked.
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case RC_PERMISSION_WRITE_EXTERNAL_STORAGE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && PackageManager.PERMISSION_GRANTED
// allowed
} else {
// denied
}
break;
}
}
}
The allowed
block is executed, confirming the user has granted permissions.
Immediately after this, if I don't destroy and open the app again, I still have no access permission to external storage. More specifically:
hasWriteExternalStoragePermission(); // returns true
Environment.getExternalStorageDirectory().canRead(); // RETURNS FALSE!!
Environment.getExternalStorageDirectory().canWrite(); // RETURNS FALSE!!
So, it seems the Android runtime thinks I have permissions, but the file system doesn't...
Indeed, trying to access Environment.getExternalStorageDirectory()
throws the exception:
android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:438)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87)?
at java.io.FileOutputStream.<init>(FileOutputStream.java:72)?
If I now destroy the app and open it again, the behaviour becomes as it should, being able to read and write in the external storage folder.
Is anyone experiencing this?
I am using one official emulator with:
- Latest Android 6.0 (API 23) API 23, Rev 1.
- Emulator running Intel x86 Atom System Image, API 23, Rev 1.
I build the app with:
android {
compileSdkVersion 23
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 16
targetSdkVersion 23
}
...
}
If someone confirms this and I am not the only one I guess we'll need to open a bug, but I hope I am doing something wrong, as I think such a core feature is unlikely to be buggy in the SDK.
See Question&Answers more detail:
os