Mastering Android Dynamic Permissions: History, Implementation & Best Practices
This article provides a comprehensive overview of Android dynamic (runtime) permissions, tracing their evolution from early Android versions through OEM customizations, and offers step‑by‑step guidance, code samples, and compatibility tips for developers to correctly request and handle dangerous permissions.
Dynamic (Runtime) Permissions Overview
Android 6.0 (Marshmallow) introduced the dangerous‑permission model, requiring apps to request certain privacy‑sensitive permissions (e.g., contacts, SMS, camera, location) at runtime. This protects user privacy by showing a system dialog before the protected API is used.
Android Permission Management History
Stage 1 – Install‑time permissions
Before Android 6.0 all permissions were listed in the manifest and granted automatically when the user installed the app. Users could only accept or reject the whole set.
<!-- PHONE_STATE permission -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- Internet permission -->
<uses-permission android:name="android.permission.INTERNET" />Stage 2 – Third‑party security apps
Security apps such as 360 Mobile Guard or Tencent Mobile Manager began monitoring sensitive permission usage and showing their own warning dialogs, allowing users to deny the request. Compatibility problems arose as OEMs customized ROMs.
Stage 3 – OEM‑integrated prompts
Manufacturers (e.g., Xiaomi MIUI, OPPO ColorOS) integrated permission prompts into the system ROM, turning third‑party dialogs into native system dialogs.
Stage 4 – Google runtime permission model (Android 6.0+)
With Android 6.0 Google required apps to check, request, and handle dangerous permissions at runtime. Some OEM ROMs still lack full support, so developers must code defensively.
Implementing Runtime Permissions
Option 1 – Target SDK below 23
Setting targetSdkVersion below 23 avoids the runtime‑permission flow, but any protected API call on Android 6.0+ will crash if the permission is not granted.
Option 2 – Proper runtime permission flow
1. Check permission before use
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
// perform the operation that needs the permission
}2. Request permission when not granted
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_PHONE_STATE},
PERMISSIONS_REQUEST_PHONE_STATE);
}3. Handle the result callback
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST_PHONE_STATE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission granted – continue with the original operation
} else {
// permission denied – handle the denial (e.g., show rationale or disable feature)
}
}
// handle other request codes if needed
}4. Optional rationale UI
Before showing the system dialog, call shouldShowRequestPermissionRationale() to detect a previous denial and decide whether to present a custom explanatory UI.
Compatibility Notes
Runtime permissions are available from API 23 (Android 6.0). On lower APIs checkSelfPermission() returns PERMISSION_GRANTED because the permission is declared in the manifest.
OEM support varies. Observed behavior:
Mi (Android 6‑based ROM): supported
Huawei: supported on both 6‑ and 7‑based ROMs
OPPO: 6‑based ROM not supported, 7‑based ROM supported
VIVO: 6‑based ROM not supported; 7.1.1 not supported; 7.1.2 partial support
Meizu: supported
Smartisan: 7‑based ROM not supported
360: not supported on 6‑ or 7‑based ROMs
ZTE: supported
Permission Dialog Elements (Android 8.0+)
Permission group icon
App name
Permission description
Allow / Deny buttons
“Don’t ask again” checkbox (may be absent on first request)
Index when multiple dialogs appear
Permission Groups
Dangerous permissions are grouped (e.g., READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE belong to the STORAGE group). Before Android O, granting one permission in a group implicitly granted the others. Starting with Android O, each permission must be requested, but if the user has already granted one permission in the group, subsequent requests are auto‑granted without another dialog.
Key API Functions
/** Check if a specific permission is granted */
public static int checkSelfPermission(Context context, String permission);
/** Show rationale if the user previously denied */
public static boolean shouldShowRequestPermissionRationale(Activity activity, String permission);
/** Request one or more permissions */
public static void requestPermissions(Activity activity, String[] permissions, int requestCode);
/** Callback to receive the result */
public abstract void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults);Typical Implementation Steps
Declare required permissions in AndroidManifest.xml.
Before using a protected API, call checkSelfPermission().
If granted, proceed; if not, optionally call shouldShowRequestPermissionRationale() to decide whether to show a custom rationale UI.
Call requestPermissions() with the needed permission(s).
Override onRequestPermissionsResult() to handle the user’s choice.
References
Google official documentation: https://developer.android.com/training/permissions/requesting.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Huajiao Technology
The Huajiao Technology channel shares the latest Huajiao app tech on an irregular basis, offering a learning and exchange platform for tech enthusiasts.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
