Android 11 Scoped storage permissions

110,662

Solution 1

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.

Solution 2

Android 11 doesn't allow to access directly files from storage you must have to select file from storage and copy that file into your app package chache com.android.myapp. Below is the method to copy file from storage to app package cache

private String copyFileToInternalStorage(Uri uri, String newDirName) {
    Uri returnUri = uri;

    Cursor returnCursor = mContext.getContentResolver().query(returnUri, new String[]{
            OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
    }, 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 output;
    if (!newDirName.equals("")) {
        File dir = new File(mContext.getFilesDir() + "/" + newDirName);
        if (!dir.exists()) {
            dir.mkdir();
        }
        output = new File(mContext.getFilesDir() + "/" + newDirName + "/" + name);
    } else {
        output = new File(mContext.getFilesDir() + "/" + name);
    }
    try {
        InputStream inputStream = mContext.getContentResolver().openInputStream(uri);
        FileOutputStream outputStream = new FileOutputStream(output);
        int read = 0;
        int bufferSize = 1024;
        final byte[] buffers = new byte[bufferSize];
        while ((read = inputStream.read(buffers)) != -1) {
            outputStream.write(buffers, 0, read);
        }

        inputStream.close();
        outputStream.close();

    } catch (Exception e) {

        Log.e("Exception", e.getMessage());
    }

    return output.getPath();
}

Solution 3

Review Android 11 Scoped Storage Updates here

Quick Solution is here :

For Quick Solution if you put your android target and compile sdk version is 29 then your app will run on android 11 with the same implementation as u did on android ten here

gradle is here

In mainfest file

in mainfest

When you updating your android Device from api 10(29) to android 11(30) Api , its not working to retrieve data from your device storage or mobile directory i have checked today on play store thousand of the apps having millions download live on play store they are not working on android 11 , because android 11 introduced new scoped storages update where you have to implement new methods to get media file using MediaStore Object,

some useful information that i wants to share with you after reading the android documentation are listed here:

in android 11 , you can access the cache only for their own specific apps.

apps cannot create their own app-specific directory on external storage. To access the directory that the system provides for your app, call getExternalFilesDirs()

If your app targets Android 11, it cannot access the files in any other app's data directory, even if the other app targets Android 8.1 (API level 27) or lower and has made the files in its data directory world-readable

On Android 11, apps can no longer access files in any other app's dedicated, app-specific directory within external storage.

Apps that run on Android 11 but target Android 10 (API level 29) can still request the requestLegacyExternalStorage attribute. This flag allows apps to temporarily opt out of the changes associated with scoped storage, such as granting access to different directories and different types of media files. After you update your app to target Android 11, the system ignores the requestLegacyExternalStorage flag.

before this on android 10 we were using

 android:requestLegacyExternalStorage="true"
    tools:targetApi="q"

in manifest under application attribute now this method is not working in android 11.

so migrate to the new updates now thanks

Review Here Scoped Storage Updates

follow the tutorial guidelines here Follow the Scoped Storage tutorial at GitHub

Solution 4

According to the Android developers documentation they recently introduced the MANAGE_EXTERNAL_STORAGE permission, but I didn't understand if adding this permission I'm able to continue to access file by Environment or not.

Yes, you will. However, bear in mind that if you intend to distribute your app on the Play Store (and perhaps elsewhere), you will need to justify the reason for requesting that permission. So, unless you have a very good reason to use MANAGE_EXTERNAL_STORAGE, please use something else.

Solution 5

I found this way for Android 11 (SDK R - 30):

1- In Manifest must add this permission: (just for R)

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />

2- Request the OS dialogue to ask for permission:

ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
                                Manifest.permission.MANAGE_EXTERNAL_STORAGE}, 1);

3- Check your app can access to the storage :

if (!Environment.isExternalStorageManager()) 

4- Use Intent to open the "All Files Access " for your app

Intent intent = new Intent();
                    intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
                    Uri uri = Uri.fromParts("package", this.getPackageName(), null);
                    intent.setData(uri);
                    startActivity(intent);

enter image description here

enter image description here

Share:
110,662
Rob B
Author by

Rob B

Updated on July 08, 2022

Comments

  • Rob B
    Rob B almost 2 years

    I'm trying to better understand what I will be able to do once the Android 11 version will be released.

    My App use the file paths of images provided by Environment.getExternalStorageDirectory() to create albums of photos, but with Android 11 I won't be able to access directly files.

    According to the Android developers documentation they recently introduced the MANAGE_EXTERNAL_STORAGE permission, but I didn't understand if adding this permission I'm able to continue to access file by Environment or not.

    Has anyone an idea???

    Thanks

    UPDATE JANUARY 2021

    I tried my application on an Android 11 Virtual device and it seems to work perfectly even without requesting the MANAGE_EXTERNAL_STORAGE permission!

    Reading the documentation on Android Developers, it seems that the applications that uses the FILE API for accessing Photos and Medias only locations can continue to work, but I'am not sure.

    Is there anyone who better understood the Android Documentation???

  • blackapps
    blackapps almost 4 years
    It looks that for the now actual 30 version this does not come true. Adding to the manifest does nothing. In the settings for the app nothing can be done. Has something to be done at runtime? To my surpise there is, by default, read access for external storage which was not the case on 29. Using Pixel emulator api 30.
  • CommonsWare
    CommonsWare almost 4 years
    @blackapps: "Adding to the manifest does nothing" -- adding what? If you mean MANAGE_EXTERNAL_STORAGE, it worked for me on a Pixel 2 the last time I tried it. "In the settings for the app nothing can be done" -- there was for me, when launching Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION. See gitlab.com/commonsguy/cw-android-r/-/tree/v0.3/RawPaths. "To my surpise there is, by default, read access for external storage which was not the case on 29" -- that is "raw paths". Most of external storage is covered, though not all.
  • blackapps
    blackapps almost 4 years
    Indeed that all files access action is needed and works. Even the whole sd card is suddenly writable. Thanks. I meant adding <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> to manifest.
  • Numan Karaaslan
    Numan Karaaslan over 3 years
    @CommonsWare i have a question. I want to trite a document reader program that must be able to read any document anywhere, like an antivirus software, user might have a document inside whatsapp directory and might want to read it inside my app. Does this justify / require all files access permisson?
  • CommonsWare
    CommonsWare over 3 years
    @NumanKaraaslan: I cannot answer that, as I am not a Google employee responsible for such decisions. That being said, while you may think that it "must be able to read any document anywhere", Google may well disagree. But, Google's rules only apply to the Play Store, so you could perhaps distribute your app by other means (e.g., F-Droid, if it is open source).
  • Noor Hossain
    Noor Hossain over 3 years
    not require MANAGE_ALL_FILES permission from playstore ?
  • Nensi Kasundra
    Nensi Kasundra over 3 years
    Thank you!!! It's Working for Android 11 and below os.
  • Ahamadullah Saikat
    Ahamadullah Saikat over 3 years
    This works fine. But what is the equivalent of Environment.getExternalStorageDirectory()? It is deprecated.
  • Ramanjeet
    Ramanjeet about 3 years
    Worked for android 11 but not for Android API 29...
  • Thoriya Prahalad
    Thoriya Prahalad about 3 years
    If you use api 29 don't need this permission. This permission is for API 30 or above.
  • KoalaKoalified
    KoalaKoalified about 3 years
    I tested this on Android Level 30 and it works without the request legacy storage but without the request legacy storage android 29 breaks still...
  • JackHuynh
    JackHuynh about 3 years
    @ThoriyaPrahalad Excuse me, I update from targetsdk 29 to 30 and remove android:requestLegacyExternalStorage flag in manifest. But my function not work in android 10. Can I apply your solution?.
  • JackHuynh
    JackHuynh about 3 years
    If update from sdk 29 to 30?. and requestLegacyExternalStorage is ignored. So can i reslove it?
  • DragonFire
    DragonFire about 3 years
    When I submit to playstore I get : Your APK or Android App Bundle requests the 'android.permission.MANAGE_EXTERNAL_STORAGE' permission, which Google Play doesn't support yet.
  • DragonFire
    DragonFire about 3 years
    When I submit to playstore I get : Your APK or Android App Bundle requests the 'android.permission.MANAGE_EXTERNAL_STORAGE' permission, which Google Play doesn't support yet.
  • DragonFire
    DragonFire about 3 years
    When I submit to playstore I get : Your APK or Android App Bundle requests the 'android.permission.MANAGE_EXTERNAL_STORAGE' permission, which Google Play doesn't support yet.
  • Tushar Monirul
    Tushar Monirul about 3 years
    Do I need to submit any form to google playstore to upload my app with this permission? Just like SMS or Call log permission. Or just simply use these code and everything will be fine?
  • Mori
    Mori about 3 years
    @DragonFire ,Yes you are right. This permission will be available after 5th May as google mentioned it.
  • Vishal kumar singhvi
    Vishal kumar singhvi about 3 years
    @DragonFire I am getting the same error, Have you found something answer or help from anywhere.
  • DragonFire
    DragonFire about 3 years
    @Vishalkumarsinghvi downgrade target to 29 from 30.. that works and remove the code for 30... and wait for google to allow.
  • Vishal kumar singhvi
    Vishal kumar singhvi about 3 years
    Right now I have target SDK 29 but I got a warning We've detected that your app contains the requestLegacyExternalStorage flag in the manifest file of 1 or more of your app bundles or APKs. So I am worried about It they will remove our app or not? @DragonFire
  • DragonFire
    DragonFire about 3 years
    @Vishalkumarsinghvi I have the same flag but no warning better get in touch with google..
  • Tariq Mahmood
    Tariq Mahmood about 3 years
    Having same issue, playstore is not accepting it.
  • Vishal kumar singhvi
    Vishal kumar singhvi about 3 years
    @DragonFire Have you use READ and WRITE_EXTERNAL_STORAGE permission in your app?
  • Максим Петлюк
    Максим Петлюк about 3 years
    Can we still use READ and WRITE_EXTERNAL_STORAGE permissions, if our app target is 29? As I understand those permissions should be replaced with MANAGE_EXTERNAL_STORAGE only for apps targeted 30? so untill google allows to push apps with target 29, we can still use them?
  • KoalaKoalified
    KoalaKoalified about 3 years
    When Google Allows the new API level 30 (Which is coming up May 5th), then this code will fully upgrade your app. Until then go to API level 29 with the request legacy flag.
  • DragonFire
    DragonFire about 3 years
    @Vishalkumarsinghvi yes those permissions I have in manifest and those are the ones I request programatically also
  • Vishal kumar singhvi
    Vishal kumar singhvi about 3 years
    Right now I have target SDK 29 but I am using requestLegacyExternalStorage flag and READ & WRITE_EXTERNAL_STORAGE both permission in the manifest file So I am worried about It they will remove our app or not?
  • Vishal kumar singhvi
    Vishal kumar singhvi about 3 years
    I am thinking in my app i only need pick an image for device that's it so I will use default picker using intent is this correct for me ? @DragonFire.
  • DragonFire
    DragonFire about 3 years
    @Vishalkumarsinghvi build it test it, if you have further questions please open up a new question.. it is out of scope of this one... thanks have a great time coding...
  • Sonu Kumar
    Sonu Kumar about 3 years
    change android:maxSdkVersion 28 to 29 in user-permission
  • Najaf Ali
    Najaf Ali about 3 years
    there are two solutions if you will target your app for api 30 then you can not used requestlegacyExternalstorage permission but you can use this only for android 29 and your app will run on 30 api too .. second solution use media store api and manage request permission and remove requestlegacyexternal permission.
  • Arnab Kundu
    Arnab Kundu about 3 years
    Best answer so far
  • Usama Saeed US
    Usama Saeed US about 3 years
    @AhamadullahSaikat use MediaStore.Files.getContentUri("external") to access all files
  • Phantom Lord
    Phantom Lord about 3 years
    OK, all this code works perfectly, but when I have gained access to all files, in which way can I read/write/delete with these files?
  • ekashking
    ekashking about 3 years
    can you at least explain what in the world is 2296 ???????
  • Thoriya Prahalad
    Thoriya Prahalad about 3 years
    it's request code for requesting permission
  • Uriel Frankel
    Uriel Frankel about 3 years
    @ekashking it is a random number for request code and response. you ask for permission with this code and check if that is the response. you can put other number in all places.
  • Anand Savjani
    Anand Savjani about 3 years
    @Mori is google play store support this permission from now onwards?
  • Mori
    Mori about 3 years
    @AnandSavjani, Yes, but maybe Google asks some other requirements.
  • Yogesh Nikam Patil
    Yogesh Nikam Patil almost 3 years
    Google rejected my app after Implementing this solution.
  • MohanRaj S
    MohanRaj S almost 3 years
    App is rejected by playstore,Action Required: Your app is not compliant with Google Play Policies
  • Md Mohsin
    Md Mohsin almost 3 years
    What is the value of Uri in copyFileToInternalStorage method?
  • vijaya zararia
    vijaya zararia almost 3 years
    @Yogesh Nikam Patil , I am implementing the same solution for my app. Is there any chance of removing app from play store. What will happen if app is removed?
  • Yogesh Nikam Patil
    Yogesh Nikam Patil almost 3 years
    @vijayazararia my app is still on play store and working fine.but play console not accepting my new apk version.I cannot update my apk version.
  • vijaya zararia
    vijaya zararia almost 3 years
    @YogeshNikamPatil Thanks for the answer. I thought like, it will be completely removed.
  • vijaya zararia
    vijaya zararia almost 3 years
    @YogeshNikamPatil Then what's an alternative you used to publish your app with android.permission.MANAGE_EXTERNAL_STORAGE .
  • Yogesh Nikam Patil
    Yogesh Nikam Patil almost 3 years
    I didn't get ay solution yet for my app.
  • Glimpse
    Glimpse almost 3 years
    @YogeshNikamPatil just use context.getExternalFilesDir(null) or context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) if targeting SDK 30, there is no need for write_external_storage or MANAGE_EXTERNAL_STORAGE at all. This "getExternalFilesDir" is returning path of app-specific folder on external storage which does not require any permission. Those permissions are only needed if you want to modify public shared external storage, and app-specific folder isn't that
  • Yogesh Nikam Patil
    Yogesh Nikam Patil almost 3 years
    Thanks @Glimpse, I will try it and let you know its working or not.
  • Al Ro
    Al Ro over 2 years
    This answer is no help for most of us because it requires android.permission.MANAGE_EXTERNAL_STORAGE, which is a no-go for most of us. Google won't accept your app to the play store if you use it.
  • Vivek
    Vivek over 2 years
    is it possible to access whatsapp statuses by using this // ??
  • Akito
    Akito over 2 years
    So... It's November 2021, now. Does Google support it? Couldn't find information about it.
  • ahmetvefa53
    ahmetvefa53 over 2 years
    İs read external storage permission enough To access al files? (Just read not write)
  • Dave
    Dave over 2 years
    Excellent, thanks.
  • sidetrail
    sidetrail over 2 years
    This is currently working for me, however Environment.getExternalStoragePublicDirectory is deprecated in API level 29.
  • Al Ro
    Al Ro over 2 years
    but if you want to get accepted by the play store there's going to be some issues when you submit this app, so this is at best half a fix. See support.google.com/googleplay/android-developer/answer/…
  • Al Ro
    Al Ro over 2 years
    This is at best half a solution if you want to be on the play store: support.google.com/googleplay/android-developer/answer/…
  • Al Ro
    Al Ro over 2 years
    Google strongly restricts use of this permission so if you want to be on the play store this is likely going to get your app flagged: support.google.com/googleplay/android-developer/answer/…
  • mirh
    mirh over 2 years
  • famfamfam
    famfamfam over 2 years
    bad answer when app will be reject by google store
  • famfamfam
    famfamfam over 2 years
    i got error Attempt to invoke interface method 'int android.database.Cursor.getColumnIndex(java.lang.String)' on a null object reference
  • Mori
    Mori over 2 years
  • Er.Nancy Thakkar
    Er.Nancy Thakkar over 2 years
    Same issue is I am facing google rejected my application after adding 'android.permission.MANAGE_EXTERNAL_STORAGE' permission. Let me know if any one found any solution
  • Pawan Jain
    Pawan Jain over 2 years
    In android 10 and above we can't use MANAGE_EXTERNAL_STORAGE for play store app submission unless the app is a file manager or antivirus. Google will reject your app.
  • Thoriya Prahalad
    Thoriya Prahalad over 2 years
    this is risky permission because google allow this permission for some apps only like file manager, antivirus apps and etc. read policy program carefully
  • Kamleshwer Purohit
    Kamleshwer Purohit over 2 years
    Please provide the same for java. is your app is accepted on play store?
  • C_compnay
    C_compnay over 2 years
    Tx alot it saved my day , Your solution worked.
  • Kamleshwer Purohit
    Kamleshwer Purohit over 2 years
    perfect one. should be accept as answer
  • famfamfam
    famfamfam over 2 years
    that not be accepted answer because api 29 were not allowed to publish to stre
  • J. M.
    J. M. over 2 years
    Where do you put the actuale file information, like if i were to make a .txt file with createfile?
  • Saurabh Dhage
    Saurabh Dhage over 2 years
    @J. M. You have to override onActivityResult(). In this method you can write content of the file.
  • J. M.
    J. M. over 2 years
    Can you find all files in folder?
  • Anggrayudi H
    Anggrayudi H over 2 years
    Yup, I can list files under the granted folder. @J.M.
  • J. M.
    J. M. over 2 years
    Can you post an example please, this is all i need to update my app for writing to android 11. Just cant figure out if folder uri is empty and read list of files.
  • J. M.
    J. M. over 2 years
  • Billyjoker
    Billyjoker over 2 years
    Do you know if this workaround is need to apply with SQLite ?
  • Haris Abdullah
    Haris Abdullah over 2 years
    Not a valid answer,all apps will be reject except for some specific
  • Richard Hammond
    Richard Hammond over 2 years
    What a complete and utter mess Android is -
  • bikram
    bikram over 2 years
    Shouldn't it be android:maxSdkVersion="29" in manifest instead of android:maxSdkVersion="28"? We still need write permission to work on SDK 29 if we use manage storage permission for SDK 30+.
  • Raii
    Raii about 2 years
    will user with new mobile see the APP in play store if we set max SDK to 29?
  • M DEV
    M DEV about 2 years
    @CommonsWare File createFile = new File(getApplicationContext().getExternalFilesDir(null)+File.‌​separator+"My App"); Is app specific Storage (Private storage) required WRITE_EXTERNAL_STORAGE Permission?
  • CommonsWare
    CommonsWare about 2 years
    @MDev: No, you do not need permissions to use the directories available from methods on Context, such as getExternalFilesDir().