Android 11 Scoped storage permissions
Android 11
If you are targeting Android 11 (targetSdkVersion 30
) then you require the following permissions in AndroidManifest.xml for modifying and document access.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
For Android 10 you place the following line in your AndroidManifest.xml tag
android:requestLegacyExternalStorage="true"
the method below checks if the permission is allowed or denied
private boolean checkPermission() {
if (SDK_INT >= Build.VERSION_CODES.R) {
return Environment.isExternalStorageManager();
} else {
int result = ContextCompat.checkSelfPermission(PermissionActivity.this, READ_EXTERNAL_STORAGE);
int result1 = ContextCompat.checkSelfPermission(PermissionActivity.this, WRITE_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
}
}
The below method can be used for requesting a permission in android 11 or below
private void requestPermission() {
if (SDK_INT >= Build.VERSION_CODES.R) {
try {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse(String.format("package:%s",getApplicationContext().getPackageName())));
startActivityForResult(intent, 2296);
} catch (Exception e) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivityForResult(intent, 2296);
}
} else {
//below android 11
ActivityCompat.requestPermissions(PermissionActivity.this, new String[]{WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
}
Handling permission callback for Android 11 or above versions
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 2296) {
if (SDK_INT >= Build.VERSION_CODES.R) {
if (Environment.isExternalStorageManager()) {
// perform action when allow permission success
} else {
Toast.makeText(this, "Allow permission for storage access!", Toast.LENGTH_SHORT).show();
}
}
}
}
Handling permission callback for OS versions below Android 11
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0) {
boolean READ_EXTERNAL_STORAGE = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean WRITE_EXTERNAL_STORAGE = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if (READ_EXTERNAL_STORAGE && WRITE_EXTERNAL_STORAGE) {
// perform action when allow permission success
} else {
Toast.makeText(this, "Allow permission for storage access!", Toast.LENGTH_SHORT).show();
}
}
break;
}
}
NOTE: MANAGE_EXTERNAL_STORAGE
is a special permission only allowed for few apps like Antivirus, file manager, etc. You have to justify the reason while publishing the app to PlayStore.
Android 11 Write Access to sdcard/Android/someapp
Looks like the bottom line is that you will NOT be able to WRITE to another apps external storage folder (/sdcard/Android/data/com.app.someapp) in And11+
Thanks for the help!
Android 11 not fetching path for file
I have fixed it by fetching path from Google drive
private static String getDriveFilePath(Uri uri, Context context) {
Uri returnUri = uri;
Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
/*
* Get the column indexes of the data in the Cursor,
* * move to the first row in the Cursor, get the data,
* * and display it.
* */
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
String name = (returnCursor.getString(nameIndex));
String size = (Long.toString(returnCursor.getLong(sizeIndex)));
File file = new File(context.getCacheDir(), name);
try {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
FileOutputStream outputStream = new FileOutputStream(file);
int read = 0;
int maxBufferSize = 1 * 1024 * 1024;
int bytesAvailable = inputStream.available();
//int bufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
final byte[] buffers = new byte[bufferSize];
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
Log.e("File Size", "Size " + file.length());
inputStream.close();
outputStream.close();
Log.e("File Path", "Path " + file.getPath());
} catch (Exception e) {
Log.e("Exception", e.getMessage());
}
return file.getPath();
}
}
Comprehensive data migration regarding Android 11 scoped storage and compatibility with versions Android 10
replace all Environment.getExternalStorageDirectory()
occurences with getExternalFilesDir(subfolderNameInScopedStorage)
- this need to be called on Context
, so inside Activity
, Service
or you can obtain Context
from e.g. Fragment
by using getContext()
method
both methods are returning File
, which is a directory for storing files (but they have different path ofc), so rest of your code won't change and should work
getExternalFilesDir
is in API since Android 4.4, so on older devices you may still use old getExternalStorageDirectory()
method, just make an if
in proper place - you should have one common (static
?) method for obtaining main dir for storing files
Related Topics
How to Copy Files from 'Assets' Folder to Sdcard
How to Execute Dex: Method Id Not in [0, 0Xffff]: 65536
How to Filter Specific Apps For Action_Send Intent (And Set a Different Text For Each App)
Firebase Onmessagereceived Not Called When App in Background
Android How to Adjust Layout in Full Screen Mode When Softkeyboard Is Visible
How to Get HTML Content from a Webview
Handler VS Asynctask VS Thread
How to Pause/Sleep Thread or Process in Android
How to Implement Onfragmentinteractionlistener
What Does Android:Layout_Weight Mean
Difference Between Gravity and Layout_Gravity in Android
Open Another Application from Your Own (Intent)
How to Set the Part of the Text View Is Clickable
Determining the Current Foreground Application from a Background Task or Service
How to Call Android Contacts List
Getting Exception "Illegalstateexception: Can Not Perform This Action After Onsaveinstancestate"