Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WRITE_EXTERNAL_STORAGE when targeting Android 10

There is a lint warning in AS with regards to android.permission.WRITE_EXTERNAL_STORAGE. The warning says that the permission will no longer provide write access when targeting Android 10 and above. Removal of the said permission can still write in internal storage folder Pictures/MY_APP_NAME to save images, but it only works on Android 10 (SDK 29) and/or above (haven't tested yet on Android R). When I tested it again on lower version such as Android M (SDK 23), saving images stop working so I decided to return the android.permission.WRITE_EXTERNAL_STORAGE thus the warning shows up again. Is it possible that the lint is just false positive that incorrectly diagnosed the problem on different cases? Because currently my support SDK starts with 21 up to the latest which is 30 but the lint only point out that it is no longer needed when targeting Android 10 (SDK 29) and did not consider looking back at the project's minimum SDK support.

like image 781
Mihae Kheel Avatar asked Oct 06 '20 07:10

Mihae Kheel


People also ask

How do I get write external permissions in Android 11?

On the Settings > Privacy > Permission manager > Files and media page, each app that has the permission is listed under Allowed for all files. If your app targets Android 11, keep in mind that this access to "all files" is read-only.

What is write external storage permission android?

Android 11 introduces the MANAGE_EXTERNAL_STORAGE permission, which provides write access to files outside the app-specific directory and MediaStore . To learn more about this permission, and why most apps don't need to declare it to fulfill their use cases, see the guide on how to manage all files on a storage device.

How do I add read external storage permissions on Android?

To read and write data to external storage, the app required WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE system permission. These permissions are added to the AndroidManifest. xml file. Add these permissions just after the package name.


5 Answers

A workaround is to actually ignore the warning, as it is just informational and therefore harmless. By setting maxSdkVersion to 28 no need to worry anymore.

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28"
    tools:ignore="ScopedStorage" />

Note that using the android:requestLegacyExternalStorage flag as stated in other answers is not a solution, is just a temporary patch which will no longer work at all in Android 11 (API 30), and future versions

UPDATE, to clarify the doubts and confusions shown by some developers in the comments:

  • If using the requestLegacyExternalStorage flag in Android 10 (API 29) then request the WRITE_EXTERNAL_STORAGE permission as usual.

  • The flag requestLegacyExternalStorage does nothing in Android 11 (API 30), it is completely ignored, and there is not workaround for it.

  • WRITE_EXTERNAL_STORAGE does not give any privileges in Android 11 (API 30), it does nothing at all, therefore in API 11 you need to set the maxSdkVersion to 29.

  • If in Android 10 (API 29) you are also not using requestLegacyExternalStorage then set maxSdkVersion to 28 instead of 29.

  • Starting in Android 11 (API 30), the older File API can again be used but "only" when accessing the public "shared storage" folders (DCIM, Music, etc.), or your app "private" directory. For other locations the DocumentFile API is required.

  • Consider that the File API is now much slower in Android 11 (API 30), because has been refactored becoming essentially a wrapper. This is to enforce its usage just to the allowed locations. So, is no longer a fast system file API, is just a wrapper that internally delegates the work to the MediaStore. When using the File API in Android 11 or above you should consider the performance penalty hit, as according to the Android team it will be 2 to 3 times slower than if accessing directly the MediaStore.

like image 81
PerracoLabs Avatar answered Oct 18 '22 06:10

PerracoLabs


Try to add this in your Manifest:

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true" //Add this Line
android:label="@string/app_name">

 ---------<Activity, Sevices or Recivers>----------

</application>

and remove the READ_EXTERNAL_STORAGE permission again:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
like image 37
Francesco Bocci Avatar answered Oct 18 '22 04:10

Francesco Bocci


Using File-apis ?

Based on @PerracoLabs reply the following changes will make your app work on the devices running

  1. Android-9 and less
  2. Android-10
  3. Android-11 and above

File: "AndroidManifest.xml"

<!-- Without this folders will be inaccessible in Android-11 and above devices -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

<!-- Without this entry storage-permission entry will not be visible under app-info permissions list Android-10 and below -->
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29"
tools:ignore="ScopedStorage"/>

<!-- Without this entry the folders will remain in-accessible in Android-10, even if WRITE_EXTERNAL_STORAGE as above is present. -->
<application
    android:requestLegacyExternalStorage="true"/>

Java Source:

  1. Don't forget to give Runtime-permissions, before doing file operation. - Needed for Android-10 and below. DONT request for runtime permissions for Android-11, they are to be requested for Android-10 and below.

  2. Navigate the user to app-permission page to allow him to enable file-permissions using the following code (needed for Android-11 and above support):

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && false == Environment.isExternalStorageManager()) {
         Uri uri = Uri.parse("package:" + BuildConfig.APPLICATION_ID);
         startActivity(new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri));
     }
    
like image 14
shyguy Avatar answered Oct 18 '22 04:10

shyguy


As answered @PerracoLabs the warning is just informational. It will be better if at first you'll read his answer. https://stackoverflow.com/a/65477206/6055194

I use WRITE_EXTERNAL_STORAGE permission only for downloading of .pdf-files into Downloads and app "private" directories by using of DownloadManager (that's important and you can understand why if you will read discussion under @PerracoLabs answer). So I've just added max level of SDK for this permission and ignore tag for scoped storage.

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28"
    tools:ignore="ScopedStorage" />

P.S. if tools tag not recognized, than you must declare it by adding xmlns:tools="http://schemas.android.com/tools" to your AndroidManifest.xml like this.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.app.my">

But you must note that after it onRequestPermissionsResult function will not be called for Build.VERSION_CODES.Q and higher (API 29+). So you must call request permission WRITE_EXTERNAL_STORAGE only for API lower than 29.

So you can add check write external storage function like this (Kotlin).

   private fun hasWriteStoragePermission(): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            return true
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(activity!!, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(
                        arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
                        REQUEST_PERMISSIONS_CODE_WRITE_STORAGE
                )

                return false
            }
        }

        return true
    }
like image 10
Zhebzhik Babich Avatar answered Oct 18 '22 05:10

Zhebzhik Babich


Add the line:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>

and add the below code to to AndroidManifest.xml:

 android:requestLegacyExternalStorage="true"
like image 1
Ali Reza Zarghi Avatar answered Oct 18 '22 06:10

Ali Reza Zarghi