Master Android 14+ Permission Management: Best Practices & Code Samples

Learn how Android 14 and newer versions refine permission handling, covering runtime requests, background location, notifications, Bluetooth, media access, foreground services, and UX best practices, with Kotlin code examples and step‑by‑step guidance to ensure compliance and optimal user trust.

AndroidPub
AndroidPub
AndroidPub
Master Android 14+ Permission Management: Best Practices & Code Samples

Introduction

In mobile development, user trust hinges on proper permission management. Starting with Android 14, the permission model becomes more granular and privacy‑focused, demanding developers handle runtime dialogs, background restrictions, and new permission categories correctly to avoid rejections or malfunction.

Android 14+ Permission Model

Since Android 6, permissions are requested at runtime. Android 13 and Android 14 continue this trend, adding finer‑grained categories and stricter background access controls. Jetpack Compose encourages a single‑request pattern combined with clear UI explanations.

Example: Request Location Permission

val locationPermission = Manifest.permission.ACCESS_FINE_LOCATION
val context = LocalContext.current
val launcher = rememberLauncherForActivityResult(
    contract = ActivityResultContracts.RequestPermission(),
    onResult = { isGranted ->
        if (isGranted) {
            // Execute location‑based operation
        } else {
            // Show rationale or direct user to settings
        }
    }
)
Button(onClick = { launcher.launch(locationPermission) }) {
    Text("请求位置权限")
}

Best Practice: Show Rationale

if (ActivityCompat.shouldShowRequestPermissionRationale(activity, locationPermission)) {
    // Explain why the permission is needed
}

POST_NOTIFICATIONS Permission (Android 13+)

From Android 13 onward, apps must explicitly request notification permission.

val launcher = rememberLauncherForActivityResult(
    contract = ActivityResultContracts.RequestPermission(),
    onResult = { granted ->
        if (granted) {
            // Show notification
        }
    }
)
Button(onClick = { launcher.launch(Manifest.permission.POST_NOTIFICATIONS) }) {
    Text("启用通知")
}

Show the dialog only when the user first triggers a feature that needs notifications; never on app launch.

Background Location Permission (Android 14+)

Requesting background location now requires a two‑step flow:

First request foreground location ( Manifest.permission.ACCESS_FINE_LOCATION).

After foreground permission is granted, request background location ( Manifest.permission.ACCESS_BACKGROUND_LOCATION).

Note: On Android 14+, if foreground location is not granted, the system will not display the background location dialog, and bypassing this flow can cause Play Store rejection.

Bluetooth Permissions (Android 12+)

Bluetooth access is split into three permissions: BLUETOOTH_SCAN – scanning BLUETOOTH_CONNECT – connecting BLUETOOTH_ADVERTISE – advertising

Low‑energy scans may also require location permission.

val permissions = arrayOf(
    Manifest.permission.BLUETOOTH_CONNECT,
    Manifest.permission.BLUETOOTH_SCAN
)

Media Permissions (Android 13+)

Media file access is now divided: READ_MEDIA_IMAGES – images READ_MEDIA_VIDEO – video READ_MEDIA_AUDIO – audio

val permissions = arrayOf(
    Manifest.permission.READ_MEDIA_IMAGES,
    Manifest.permission.READ_MEDIA_VIDEO
)

Request these only when the app needs direct access to shared storage media.

Foreground Service Permission (Android 14+)

Starting a foreground service now requires declaring the appropriate permission in AndroidManifest.xml:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"/>

Omitting the correct permission can cause the service to crash or fail to start.

User Experience (UX) Best Practices

Avoid frequent permission dialogs.

Request only essential permissions at the moment they are needed.

Provide an in‑app explanation before the system dialog appears.

Respect the user’s choice; gracefully degrade functionality if a permission is denied.

If a permission is permanently denied, show a settings‑link intent to let the user manually grant it:

Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
    data = Uri.fromParts("package", context.packageName, null)
    context.startActivity(this)
}

Conclusion

Android 14 and later make the permission system more secure and complex, emphasizing user privacy. Developers must understand the new changes, use the correct APIs, and follow UX guidelines to build powerful apps that respect user trust and comply with Play Store policies.

mobile developmentKotlinbest practicesPermissions
AndroidPub
Written by

AndroidPub

Senior Android Developer & Interviewer, regularly sharing original tech articles, learning resources, and practical interview guides. Welcome to follow and contribute!

0 followers
Reader feedback

How this landed with the community

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.