How do I grant external storage permissions on Android?

In the last days I've been working on the development of a Capacitor Plugin that allows to launch a native file picker and I faced a new problematic that a lof of android developers seems to be having now. Since Android 11 (apps targeting SDK Version 30) which is by default the target API of a new Capacitor based applications, there's a new update on the Storage policies of apps. The Scoped Storage enforcement has been implemented to enhance the platform, giving better protection to your app and user's data on external storage. This will cause some modifications in which app works since this API as:

  • On Android 11, apps can no longer access files in any other app's dedicated, app-specific directory within external storage.
  • To protect user privacy, on devices that run Android 11 or higher, the system further restricts your app's access to other apps' private directories.

The reason why I faced this problem is because the plugin should allow to select any possible file in the device as it will be used inside a Code Editor application.

Accessing all files

There's a possibility to access all the files in the device using the new permission . However, this automatically will put a restriction in your application as Google Play should review if you really need the mentioned permission when trying to publish the application to the Play Store. 

The permission won't be applied automatically to your app without the user's interaction as the user needs to obligatorily grant access to the files. You can do this in Android following these steps:

1. Request MANAGE_EXTERNAL_STORAGE permission

Modify your AndroidManifest.xml file by requesting the following permissions:

<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.ourcodeworld.plugins.capacitornativefilepicker"
    xmlns:tools="http://schemas.android.com/tools"
>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage"/>
</manifest>

The MANAGE_EXTERNAL_STORAGE permission allows an application a broad access to external storage in scoped storage. Intended to be used by few apps that need to manage files on behalf of the users.

2. Request External Storage Permissions

After declaring the permissions, you need to request the regular READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions. Note that we don't include the MANAGE_EXTERNAL_STORAGE, because if you request it, when verifying if you have access or not, the mentioned permission will always return denied, even though the user has already granted access:

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

The logic of this step is up to you as you may know how to request permissions in your own application.

3. Checking permission of MANAGE_EXTERNAL_STORAGE

Now, instead of the regular permissions request to handle the mentioned permission, you need instead to verify whether the access to the external storage is allowed. In case it isn't, you need to launch a new activity showing the system's dialog where the user should manually allow the access to the external storage to your app like this:

import android.os.Environment;
import android.content.Intent;
import android.provider.Settings;
import android.net.Uri;

// If you have access to the external storage, do whatever you need
if (Environment.isExternalStorageManager()){

// If you don't have access, launch a new activity to show the user the system's dialog
// to allow access to the external storage
}else{
    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);
}

So when the user installs the app and try to access the file picker, if the access to all files isn't granted yet, the following system intent will be launched:

The user will have to explicitly allow access to all files if you want to read files from any source in the device and that should be enough.

Android gives various options for storing apps data which uses a file system similar to the disk-based system on computer platforms

  • App-Specific storage: Store data files within internal volume directories or external. These data files are meant only for the app’s use. It uses internal storage directories to save sensitive information such as a username and password that other app should not access.
  • Shared Storage: Store data files such as images, audio, video, documents, etc. that the app may need to share with other apps.
  • Shared Preferences: Store primitive data type such as integer, float, boolean, string, long in key-value pairs.
  • Databases: Store structured data such as user-information(name,  age, phone, email, address, etc.) into private databases.

Developers are advised to use the options available to store data depending upon the space required, reliable data access, and privacy of data. The data files saved over external storage devices are publicly accessible on shared external storage using USB mass storage transfer. Data files stored over external storage using a FileOutputStream object and can be read using a FileInputStream object.

External Storage Availability

In order to avoid crashing the app first, we need to check storage SD Card is available for reading and write operations. The method getExternalStorageState() is used to determine the state of mounted storage media such as SD Card is missing, read-only or readable, and writable. Below is the code snippet which we will use to check the availability of external storage.

Java




boolean isAvailable=false;

boolean isWritable=false;

boolean isReadable=false;

isAvailable=2

isAvailable=

isAvailable=4isAvailable=5

isAvailable=6isAvailable=7

isAvailable=6isAvailable=false0;

isAvailable=6isWritable=false0;

isAvailable=6isReadable=false0;

;0;1 isAvailable=4 ;3

;4;5

;4isAvailable=false0;

;4isWritable=false;

;4isReadable=false0;

;0;1 isWritable=0

;4isWritable=2

;4isWritable=4false;

;4isWritable=false;

;4isReadable=falsefalse4

;0

Methods to Store data in External Storage

  • getExternalStoragePublicDirectory(): This is the present recommended method to keep files public and these files are not deleted even when the app is uninstalled from the system. For eg: Images clicked by the camera are still available even after we uninstall the camera.
  • getExternalFilesDir(String type): This method is used to store private data that are specific to the app only. And data are removed as we uninstall the app.
  • getExternalStorageDirectory(): This method is not recommended. It is now absolute and it is used to access external storage in older versions, API Level less than 7.

Example

In this example, we would store text data into the external storage and fetch to see that data. A sample GIF is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Java language. 

How do I allow access to external storage on Android?

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.

How do I enable permission for external storage?

Change app permissions.
On your phone, open the Settings app..
Tap Apps..
Tap the app you want to change. If you can't find it, tap See all apps. ... .
Tap Permissions. If you allowed or denied any permissions for the app, you'll find them here..
To change a permission setting, tap it, then choose Allow or Don't allow..

What does external storage writing permission needed mean?

When an app is granted storage permission, it can access the device storage at any time. This means it can upload personal files or even delete sensitive information from the device, so it's better to think twice before giving storage permission to untrusted apps, as it can be harmful.

How do I give app permissions to my SD card?

Go To Device 'Settings' –> Scroll down and tap on 'Developer options' –> Scroll Down and enable 'Force allow apps on external'. This makes any app eligible to be written to external storage.