Manage External Storage Permission -Android Studio — Java

Katwere Leo
4 min readApr 13, 2023

--

Google always rolls out a new Android Version every other year. If you have been doing Android Development for quite sometime, you must have noticed that, with every new Android update, new major features and code breaking changes are made.

Most of the latest improvements and changes are meant to improve the security and provide a better user experience. But, to the developers, this usually means relearning some of the concepts used.

This article is meant to guide you on the process of requesting for storage permissions on Android 13 (Api level 33) down to Api level 21. I assume you have basic / beginner knowledge in Android Development with Java.

I guess its about time to dive right in:

Step 1: Add Permission to Manifest

The first step in requesting storage permission on Android is to add the permission to the app’s manifest file. To do this, open the AndroidManifest.xml file and add the following code within the <manifest> tag:

For Android 11 (R) and above, add

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

Short Note

(Google has put in place restrictions on apps that use the Manage External Storage permission. Specifically, apps that request this permission must be able to demonstrate a “core user benefit” that cannot be achieved without access to external storage. This means that apps that do not provide a clear and compelling reason for using this permission may be rejected from the Google Play Store.)

For Android Versions Below 11, add:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Step 2 : Check For Permissions At Runtime

Once the permissions have been added to the manifest file, the next step is to check if the user has granted the app Storage permissions at runtime. To do this, add the following code to the activity or fragment where you want to access the storage:

public boolean checkStoragePermissions(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
//Android is 11 (R) or above
return Environment.isExternalStorageManager();
}else {
//Below android 11
int write = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int read = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);

return read == PackageManager.PERMISSION_GRANTED && write == PackageManager.PERMISSION_GRANTED;
}
}

This code checks if Storage Permissions have been granted and returns a boolean.

Step 3 : Request For Storage Permissions

Once you have confirmed that the user has not yet granted storage results, the next step is to request for the Storage Permissions.

In this example, we are going to use the RequestPermission contract, included in an AndroidX library, where you allow the system to manage the permission request code for you. Using the RequestPermission contract simplifies your logic, and it is the recommended solution when possible.

To allow the system to manage the request code that’s associated with a permissions request, add dependencies of the following libraries in your module’s build.gradle file:

After adding the above dependencies and building your project, add the following code to request for storage permissions

private static final int STORAGE_PERMISSION_CODE = 23;

private void requestForStoragePermissions() {
//Android is 11 (R) or above
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
try {
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);
storageActivityResultLauncher.launch(intent);
}catch (Exception e){
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
storageActivityResultLauncher.launch(intent);
}
}else{
//Below android 11
ActivityCompat.requestPermissions(
this,
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
},
STORAGE_PERMISSION_CODE
);
}

}

The function above requests for storage permissions for Android Versions Below and Above Android 11.

For Versions Above Android 11, we request for storage permissions using the Activity Result Launcher Api. This simplifies the process of starting activities and handling their results, making it easier for developers to write cleaner and more maintainable code. For more info, check it out via the official Android Website.

For Versions Below Android 11, we request the permissions by using the requestPermissions method. This method requires the application Context, a String containing the permissions being requested for, and a Request Code Integer. In this case, the request code is a variable named STORAGE_PERMISSION_CODE

Step 3: Handle Permission Request Result

After requesting for the permissions, the app needs to handle the user’s response to the request. To do this, add the following code to the activity or fragment:

private ActivityResultLauncher<Intent> storageActivityResultLauncher =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>(){

@Override
public void onActivityResult(ActivityResult o) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){
//Android is 11 (R) or above
if(Environment.isExternalStorageManager()){
//Manage External Storage Permissions Granted
Log.d(TAG, "onActivityResult: Manage External Storage Permissions Granted");
}else{
Toast.makeText(MainActivity.this, "Storage Permissions Denied", Toast.LENGTH_SHORT).show();
}
}else{
//Below android 11

}
}
});

In the code above, the registerForActivityResult() method is used to register a permission request contract with the launcher. The RequestPermission() contract takes an intent and handles the result via a callback method. A Toast message is displayed in either case, however, you can handle this logic as you wish.

To handle permission request results for Android Versions below 11, add the following code.

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == STORAGE_PERMISSION_CODE){
if(grantResults.length > 0){
boolean write = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean read = grantResults[1] == PackageManager.PERMISSION_GRANTED;

if(read && write){
Toast.makeText(MainActivity.this, "Storage Permissions Granted", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this, "Storage Permissions Denied", Toast.LENGTH_SHORT).show();
}
}
}
}

This code handles the result of the permission request.

A Toast message is displayed in either case, however, you can handle this logic as you wish.

Conclusion

Requesting for permissions on Android is an important aspect of app development. I hope you found this article helpfull.

Kuddos.. To more fun coding

Leo Katwere

--

--