Runtime Permission is a mechanism for requesting permissions at runtime, introduced in Android 6.0 (API 23). Unlike granting permissions at installation, runtime permissions allow the user to grant or revoke access to sensitive data (camera, geolocation, contacts) at any moment. According to Android Developers (2026), more than 85% of apps on Google Play use at least one runtime permission.
Key Takeaways
Runtime Permission is an Android security model where the app requests access to sensitive data at the moment when that functionality is actually needed by the user. Before Android 6.0, all permissions were granted at app installation, and the user could not revoke them without completely uninstalling the app.
Before Android 6.0, the user saw a list of all permissions at installation and could either accept all or decline the installation. A 2015 study showed that 87% of users do not read the permission list at installation. Android 6.0 introduced runtime permissions, dividing permissions into normal (automatic) and dangerous (requiring a request). Android 11 added one-time permissions — automatic revocation after the app is closed. Android 13 introduced Photo Picker and push notifications as separate runtime permissions.
iOS uses a similar model since iOS 10, where access to camera, microphone, and geolocation is requested on first use. However, iOS does not have the concept of “normal permissions” — each permission is explicitly requested, and denial persists until the developer re-requests through system settings.
Runtime Permission works through a system dialog invoked by the requestPermissions() method (AndroidX — ActivityResultLauncher). The system displays a standard dialog with an explanation, and the user chooses “Allow” or “Deny”. After the response, a result callback is triggered where the app handles the user’s decision.
private lateinit var requestPermissionLauncher: ActivityResultLauncher<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
startCamera()
} else {
showPermissionDeniedDialog()
}
}
}
private fun checkCameraPermission() {
when {
ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED -> {
startCamera()
}
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) -> {
showRationaleDialog { requestPermissionLauncher.launch(Manifest.permission.CAMERA) }
}
else -> {
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
}
The shouldShowRequestPermissionRationale method returns true if the user has already denied the request once. In this case, it is recommended to show a dialog explaining why the app needs the permission, and only then re-request. This increases the likelihood of user consent by 30–40% (Google I/O 2024 data).
Android classifies all permissions into several protection levels: normal, dangerous, signature, and special. Normal permissions are granted automatically at installation. Dangerous permissions require a runtime request. Signature permissions are only available to apps signed with the same certificate.
| Group | Permissions | API Level |
|---|---|---|
| CAMERA | CAMERA | API 23+ |
| LOCATION | ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_BACKGROUND_LOCATION | API 23+ (background — API 29+) |
| STORAGE | READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, READ_MEDIA_IMAGES (API 33+) | API 23+ (changes in API 33) |
| PHONE | READ_PHONE_STATE, CALL_PHONE, READ_CALL_LOG | API 23+ |
| MICROPHONE | RECORD_AUDIO | API 23+ |
| CONTACTS | READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS | API 23+ |
| NOTIFICATIONS | POST_NOTIFICATIONS | API 33+ |
Special permissions (SYSTEM_ALERT_WINDOW, WRITE_SETTINGS, MANAGE_EXTERNAL_STORAGE) require an additional navigation to system settings via Settings.ACTION_MANAGE_OVERLAY_PERMISSION. These permissions cannot be requested through the standard system dialog and require an explicit user action in the settings screen.
Android 12 introduced significant changes to the runtime permissions model. One-time permissions allow granting access to camera, microphone, or geolocation for only one session. Once the user closes the app, the permission is automatically revoked. Privacy indicators are green indicators in the status bar showing when an app is using the camera or microphone.
// Android 12+ — handling one-time location permission
private fun checkLocationPermission() {
val permissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val fineLocationGranted = permissions[Manifest.permission.ACCESS_FINE_LOCATION]
val coarseLocationGranted = permissions[Manifest.permission.ACCESS_COARSE_LOCATION]
if (fineLocationGranted == true) {
showUserLocation()
} else {
showLocationDisabledDialog()
}
}
permissionLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
}
// Check if the permission was revoked by the system (Android 12+)
class PermissionReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_PERMISSION_REVOCATION) {
handleRevokedPermission(intent.getStringExtra(Intent.EXTRA_REVOKED_PERMISSION))
}
}
}
Android 13 added the POST_NOTIFICATIONS permission to the dangerous group, requiring an explicit request to send push notifications. Android 14 introduced restrictions on background geolocation: the app must receive explicit user approval each time it requests background location. Photo Picker (API 33+) replaced the need for READ_EXTERNAL_STORAGE for image selection.
User denial of a permission request is a normal situation that must be handled correctly. There are two types of denial: one-time (user tapped “Deny”) and permanent (user selected “Never ask again”). In the second case, the system dialog will no longer appear, and the app must redirect the user to system settings.
After the first denial, the app should show a rationale dialog — its own explanation of why the permission is necessary. If the user refuses again, the app should redirect to the app settings screen via Settings.ACTION_APPLICATION_DETAILS_SETTINGS. Material 3 recommends using PermissionRequestBottomSheet for a more natural UX.
It is important not to completely block app functionality upon denial. For example, if the user denied geolocation, the app should offer manual address input. For camera, allow uploading an image from the gallery. Google recommends always providing a fallback mechanism for all runtime permissions.
Runtime permissions are not just a technical mechanism but also an element of user trust in the app. Requesting permission at an inappropriate time (e.g., on first launch) significantly reduces the likelihood of consent. Google Play Store analyzes the frequency and context of permission requests: apps with aggressive requests receive lower search rankings.
Context — request permission immediately before performing the action that requires it. Minimum — request only the permissions that are truly necessary for the feature to work. Transparency — explain to the user why the permission is needed before the system dialog. Revocation — subscribe to ACTION_PERMISSION_REVOCATION to correctly handle permission revocation at runtime.
For testing runtime permissions, use adb commands: adb shell pm revoke <package> android.permission.CAMERA allows simulating permission revocation without reinstalling the app. Espresso and UiAutomator support testing permission dialogs via GrantPermissionRule. Integrating these tools into the CI/CD pipeline is mandatory for apps with runtime permissions.
Google Play Console provides a Permission auditing section, where developers can see how often permissions are requested, what percentage of users grant access, and which permissions were revoked. Analyzing this data helps identify ineffective requests and optimize UX. For example, if fewer than 40% of users grant geolocation, consider revising the request timing and adding a more compelling rationale.
Using Android Vitals for monitoring permission-related ANR (Application Not Responding) is also critical. If a permission request is executed on the main thread or the system dialog blocks the UI, it may cause ANR on slow devices. Move permission checking and requests to a separate thread or use Kotlin coroutines for asynchronous handling to avoid blocking the user interface.
Frequently Asked Questions
shouldShowRequestPermissionRationale returns false for permanent denial (when the user selected “Never ask again”). The method returns true for a one-time denial, allowing a rationale dialog to be shown. If the method returns false, the only option is to redirect the user to system settings.
Yes, ActivityResultContracts.RequestMultiplePermissions allows requesting an array of permissions in a single call. The system will sequentially display dialogs for each permission. It is recommended to group logically related permissions (e.g., CAMERA and RECORD_AUDIO for video recording), but not to request more than 2–3 at a time.
Android TV uses the same runtime permissions model with dialogs displayed on the TV screen. Wear OS version 3+ supports runtime permissions, but dialogs are displayed on the watch. For Android Auto, all permissions are requested on the phone, and the car system receives already approved permissions via a bridge connection.
According to preliminary information, Android 16 introduces “permission expiration” for one-time permissions with automatic revocation after 24 hours. Stricter requirements for background location and an expanded list of dangerous permissions for new categories (environment sensors, Wi-Fi scanning) are also expected. Exact details will appear in Q3 2027.
iOS does not support “normal permissions” — each permission is explicitly requested through a system dialog. The user can revoke permission at any time through settings. The main difference is that iOS does not pre-check permission status via an equivalent of checkSelfPermission: the system automatically shows a dialog on first access to a protected API.
Summary
POST_NOTIFICATIONS as a runtime permission; Android 14 tightened background geolocation requirements.READ_EXTERNAL_STORAGE for image selection.We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also