Android Marshmallow Storage Permission Handling Mechanism and Best Practices

Nov 20, 2025 · Programming · 11 views · 7.8

Keywords: Android Permissions | Marshmallow | WRITE_EXTERNAL_STORAGE | Runtime Permissions | Permission Handling

Abstract: This article provides an in-depth analysis of the runtime permission mechanism introduced in Android 6.0 Marshmallow, focusing on the handling of WRITE_EXTERNAL_STORAGE permission in download functionality. By comparing permission differences between Lollipop and Marshmallow, it details the complete implementation process of permission checking, requesting, and callback handling, and offers compatibility solutions to help developers resolve storage permission issues when upgrading from Lollipop to Marshmallow.

Runtime Permission Mechanism Overview

Android 6.0 Marshmallow introduced significant changes to the permission model, dividing permissions into normal permissions and dangerous permissions. WRITE_EXTERNAL_STORAGE falls under dangerous permissions and requires dynamic runtime requests in Marshmallow and later versions, unlike Lollipop where permissions were granted once during installation. This change significantly enhances user control over privacy and data security.

Root Cause Analysis of Permission Issues

In the Lollipop system, applications received all permissions declared in AndroidManifest.xml during installation. However, in Marshmallow, even if WRITE_EXTERNAL_STORAGE permission is declared in the manifest file, the application still needs to explicitly request this permission from the user during first use. This is the fundamental reason why download functionality that worked normally in Lollipop crashes after upgrading to Marshmallow.

Complete Permission Handling Process

To implement Marshmallow-compatible storage permission handling, the following complete process must be followed:

Permission Checking Mechanism

Before performing any file operations, it is essential to first check whether the required permissions have been granted. This can be achieved using the checkSelfPermission() method:

if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
    Log.v(TAG, "Permission is granted");
    // Execute file writing logic
    return true;
}

Permission Request Process

When it is detected that the permission has not been granted, a permission request must be initiated to the user:

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);

The system will display a standard permission request dialog where the user can choose to allow or deny the permission.

Version Compatibility Handling

Since the runtime permission mechanism only applies to Marshmallow and later versions, version checking logic must be added:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    // Execute Marshmallow-specific permission checks
} else {
    // For earlier versions, permissions were automatically granted during installation
}

Complete Permission Management Implementation

Below is a complete implementation example of a permission checking and requesting method:

public boolean isStoragePermissionGranted() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            Log.v(TAG, "Permission is granted");
            return true;
        } else {
            Log.v(TAG, "Permission is revoked");
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            return false;
        }
    } else {
        Log.v(TAG, "Permission is granted");
        return true;
    }
}

Permission Request Result Handling

The Activity must implement the onRequestPermissionsResult callback method to handle the user's permission choices:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        Log.v(TAG, "Permission: " + permissions[0] + " was " + grantResults[0]);
        // Resume tasks requiring this permission
    }
}

Practical Application Scenario Analysis

In download manager scenarios, the correct approach is to perform permission checks before calling DownloadManager.enqueue(). If the permission has not been granted, the download operation should be paused and permission requested. Only after the user grants permission in the permission callback should the download task proceed.

Best Practice Recommendations

1. Perform permission checks during application startup or when using permission-required features for the first time

2. Clearly explain to users why the permission is needed to enhance user experience

3. Handle cases where users deny permissions by providing graceful degradation solutions

4. Regularly test permission behavior across different Android versions

Conclusion

While Android Marshmallow's runtime permission mechanism increases development complexity, it provides crucial protection for user privacy. Through proper permission checking, requesting, and handling processes, developers can build applications that are both secure and user-friendly. Understanding and correctly implementing these mechanisms is essential for ensuring stable application operation on Marshmallow and later versions.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.