Modern mobile operating systems (Android 6.0+ / API 23+ and iOS) utilize runtime permissions for sensitive features like camera, location, contacts, and storage access. Unlike older models where permissions were granted solely at app installation, runtime permissions require your app to explicitly ask the user for permission while the app is running, typically right before a feature that requires it is used. This gives users greater control and transparency over their data and device resources, but it places the responsibility on developers to manage these requests proactively and gracefully.
Before performing any operation that requires a sensitive permission, your app must first check if that permission has already been granted. If not, you then initiate a system-provided permission request dialog. A crucial best practice is to provide context and rationale to the user before showing the system dialog, especially if shouldShowRequestPermissionRationale() returns true (indicating the user has previously denied the permission). Explaining why a permission is needed improves the chances of it being granted and enhances the user's understanding of your app's functionality.
Graceful denial handling is paramount for a good user experience. Users can grant, deny, or permanently deny a permission (often by checking a "Don't ask again" box or repeatedly denying). Your app must be robust enough to handle all these scenarios. If a permission is denied (but not permanently), you might be able to request it again later. However, if a permission is permanently denied, your app cannot prompt the user again. In such cases, you must guide the user to the device's app settings to manually grant the permission, or gracefully degrade the feature, perhaps by disabling it or offering an alternative experience without that specific functionality. Never crash or block the entire app due to a denied permission.
Key Takeaways
- Always check permission status before attempting sensitive operations.
- Request permissions contextually and provide clear rationale using
shouldShowRequestPermissionRationale(). - Implement robust logic to handle both temporary and permanent permission denials.
- For permanent denials, guide the user to device settings or gracefully degrade functionality.
Code Example
import android.Manifest;
import android.content.pm.PackageManager;
import androidx.core.content.ContextCompat;
import androidx.core.app.ActivityCompat;
// Inside your Activity or Fragment
private final int MY_CAMERA_REQUEST_CODE = 123;
private void requestCameraPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
// Permission already granted. Proceed with camera operations.
// For example: initializeCamera();
} else {
// Permission not granted.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
// User previously denied, show an explanation before requesting again.
// A dialog explaining *why* the camera is needed would go here.
// Example: new AlertDialog.Builder(this).setMessage("Camera is essential for scanning QR codes.").show();
}
// Request the permission from the user.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, MY_CAMERA_REQUEST_CODE);
}
}
// Note: Handle the result in your Activity's onRequestPermissionsResult method.
// There you'll check if permission was granted or denied and react accordingly.How this code works
This code's job is to safely ask the user for permission to use the device's camera at runtime, which is a key privacy control in modern mobile operating systems. It gracefully handles different user responses, from immediate approval to repeated denials. The requestCameraPermission method first checks if Manifest.permission.CAMERA is already PackageManager.PERMISSION_GRANTED using ContextCompat.checkSelfPermission. If permission is already in place, the app can proceed directly with camera-related tasks.
If permission isn't granted, the code takes an important step: it checks ActivityCompat.shouldShowRequestPermissionRationale. This is a subtle yet crucial aspect: it returns true specifically when the user has previously denied the permission but has not yet chosen the "Don't ask again" option. In this scenario, the app should provide an explanation (e.g., in an AlertDialog) describing why the camera is needed before requesting it again. Regardless of whether a rationale was shown, the final step is ActivityCompat.requestPermissions, which displays the standard Android system permission dialog to the user, identifying this specific request with MY_CAMERA_REQUEST_CODE. The result of this user interaction is then processed in a separate onRequestPermissionsResult method.