Mobile Development 19 min read

Understanding and Implementing Dynamic Permissions in Android

This article explains the concept, history, and implementation of Android dynamic (runtime) permissions, detailing the evolution of permission models, code examples for checking and requesting permissions, handling callbacks, compatibility across Android versions and OEM customizations, and best‑practice strategies for developers.

360 Tech Engineering
360 Tech Engineering
360 Tech Engineering
Understanding and Implementing Dynamic Permissions in Android

Dynamic (runtime) permissions were introduced in Android 6.0 (Marshmallow) to protect user privacy by requiring apps to request dangerous permissions at the moment they are needed. The article first reviews the evolution of Android permission management, from pre‑Marshmallow static permissions to the four stages of modern permission handling, including OEM‑added security apps and manufacturer‑level dialogs.

To adopt dynamic permissions, developers must declare the required permissions in <uses-permission android:name="android.permission.READ_PHONE_STATE" /> and <uses-permission android:name="android.permission.INTERNET" /> in the AndroidManifest. At runtime, the app should check the permission status with ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED . If the permission is not granted, the app should request it using ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), PERMISSIONS_REQUEST_PHONE_STATE) .

The result of the request is handled in override fun onRequestPermissionsResult(requestCode: Int, permissions: Array , grantResults: IntArray) { ... } , where the app can react to the user’s choice, proceed with the operation if granted, or show a rationale or fallback if denied.

For devices running Android versions lower than 6.0, checkSelfPermission() will always return PERMISSION_GRANTED for permissions declared in the manifest, so the same code works without modification. However, many OEM ROMs modify the permission flow; the article lists compatibility tables for major Chinese manufacturers (Xiaomi, Huawei, OPPO, VIVO, etc.) and explains how their custom dialogs differ from stock Android.

Best‑practice recommendations include:

Show a pre‑permission rationale UI before invoking the system dialog, especially for permissions that seem unrelated to the core feature.

Use shouldShowRequestPermissionRationale() to detect whether the user previously denied a permission and adapt the UI accordingly.

Group related permissions and request them together, e.g., ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_CODE) , to reduce the number of dialogs.

Handle the “Don’t ask again” option by directing users to the system settings when necessary.

The article also covers permission groups, changes in Android O and later that require each permission in a group to be requested separately, and the impact of different ROM customizations on permission dialogs and user experience.

Finally, a concise step‑by‑step checklist is provided:

Declare needed permissions in the manifest.

Before performing an operation, call checkSelfPermission() to verify authorization.

If not authorized, optionally show a rationale UI, then call requestPermissions() .

Process the result in onRequestPermissionsResult() .

Optionally guide the user to settings if they selected “Don’t ask again”.

AndroidKotlinPermission ManagementDynamic PermissionsRuntime Permission
360 Tech Engineering
Written by

360 Tech Engineering

Official tech channel of 360, building the most professional technology aggregation platform for the brand.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.