Skip to content

Expert: features and shipping · Permissions, Material 3 and polish · topic 35 of 50 · 35 min

Runtime permissions

Explanation

Android protects private data and hardware with permissions. Normal permissions (like INTERNET) are granted at install. Dangerous permissions (camera, location, contacts, microphone, and notifications on Android 13+) must be declared in the manifest and also requested at run time, at the moment the feature is used, with rememberLauncherForActivityResult and ActivityResultContracts.RequestPermission. Always handle "denied" gracefully.

Why permissions?

A phone holds very personal things: photos, location history, contacts, messages, the microphone. Android does not let apps touch these freely. A permission is a declared right to use a protected feature. Since Android 6.0 (API 23), sensitive permissions are granted by the user while the app runs, not silently at install, so users understand why each one is needed.

TypeExamplesHow it is granted
NormalINTERNET, ACCESS_NETWORK_STATE, VIBRATEAutomatically at install (still declared in the manifest)
Dangerous (runtime)CAMERA, ACCESS_FINE_LOCATION, READ_CONTACTS, RECORD_AUDIO, POST_NOTIFICATIONS (Android 13+)User approves in a system dialog at run time
SpecialSYSTEM_ALERT_WINDOW, exact alarms on some versionsUser enables in a Settings screen

Step 1: declare in the manifest

xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
Declaration is required for every permission, runtime or not.

Step 2: request at the moment of use

kotlin
@Composable
fun ScanQrButton(onScan: () -> Unit) {
    val context = LocalContext.current
    var showRationale by remember { mutableStateOf(false) }

    val launcher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { granted ->
        if (granted) onScan() else showRationale = true
    }

    Button(onClick = {
        val alreadyGranted = ContextCompat.checkSelfPermission(
            context, Manifest.permission.CAMERA
        ) == PackageManager.PERMISSION_GRANTED
        if (alreadyGranted) onScan() else launcher.launch(Manifest.permission.CAMERA)
    }) { Text("Scan QR to pay") }

    if (showRationale) {
        Text("Camera access is needed to scan QR codes. You can still pay by entering a UPI ID.")
    }
}
Check first; if not granted, launch the system dialog; handle both answers.

Ask in context: request the camera when the user taps "Scan QR", not on the first launch. People say yes much more often when the reason is obvious. If the user says no, explain why the feature needs it and offer another way (enter the UPI ID by hand).

When the user says no twice

If the user denies a permission repeatedly, Android stops showing the dialog (the user chose "don't ask again", or the system decided so). launch then returns denied immediately. The polite response is to explain the benefit and offer a button that opens the app's page in system Settings, where the user can enable it if they change their mind.

Notifications on Android 13+

Since Android 13 (API 33), apps that target it must request POST_NOTIFICATIONS at run time before showing notifications. Ask after the user has seen value, for example after their first order ("Get updates when your order is out for delivery?").

Ask for less

Every permission is a privacy cost and a review risk. Google Play restricts some permissions (SMS, call log, background location) to apps whose core feature truly needs them, and asks you to declare why. Often an alternative avoids a permission entirely: the system photo picker needs no storage permission, and approximate location (ACCESS_COARSE_LOCATION) is enough for "nearby stores".

Think of it like this: Permissions are like a guest asking to enter different rooms of your house. The drawing room is open to everyone (normal permissions). To enter the bedroom or open the cupboard, the guest must ask you, at that moment, with a reason. A polite guest who is refused does not keep knocking; they explain once and find another way.

Common mistakes

  • Asking for all permissions on the first screen: users deny, and some uninstall.
  • Forgetting the manifest declaration: the request is denied silently.
  • Crashing or showing a blank screen when the user says no. Always have a fallback.
  • Requesting permissions the app does not really need, which can get the app rejected on Play.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Runtime permissions · 1/7

Privacy first

Permissions protect private data and hardware like the camera, location and contacts.

Prefer a video by a teacher? Find free videos on “android runtime permissions jetpack compose rememberLauncherForActivityResult” on YouTube ↗

In real life: Find nearby pharmacies

A health app has a "Pharmacies near me" button. Only when the user taps it does the app request ACCESS_COARSE_LOCATION (approximate location is enough). If granted, it shows pharmacies within 2 km; if denied, it shows a search box for typing a locality or PIN code. The app never asks for background location, because it does not need it.

kotlin
val locationLauncher = rememberLauncherForActivityResult(
    ActivityResultContracts.RequestPermission()
) { granted ->
    if (granted) viewModel.loadNearby() else viewModel.showPinCodeSearch()
}

Button(onClick = { locationLauncher.launch(Manifest.permission.ACCESS_COARSE_LOCATION) }) {
    Text("Pharmacies near me")
}
Both answers lead somewhere useful.

Practice (0/3 done)

Task 1 · Question

When is the best time to request the CAMERA permission in a payments app?

Task 2 · Question

Which permission is granted automatically at install?

Task 3 · Practice

Build a "Profile photo" button that asks for CAMERA only when tapped, opens a placeholder "camera" screen when granted, and when denied shows a short explanation plus a "Choose from gallery" option using the system photo picker (ActivityResultContracts.PickVisualMedia), which needs no permission.

Quick quiz

Question 1

1.Since which Android version are dangerous permissions requested at run time?

Question 2

2.Which permission must apps targeting Android 13+ request before showing notifications?

Question 3

3.What should the app do if a permission is denied?

Question 4

4.Which API requests a single runtime permission in Compose?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Since which Android version are dangerous permissions requested at run time?

Answer: Android 6.0 (API 23)

Runtime permissions arrived in Marshmallow.

Which permission must apps targeting Android 13+ request before showing notifications?

Answer: POST_NOTIFICATIONS

POST_NOTIFICATIONS is a runtime permission from API 33.

What should the app do if a permission is denied?

Answer: Explain and offer a fallback or a link to Settings

Respect the choice and stay useful.

Which API requests a single runtime permission in Compose?

Answer: rememberLauncherForActivityResult with ActivityResultContracts.RequestPermission()

The Activity Result API handles the dialog and result.

What do reviewers most often check first in a take-home Android app?Related

Answer: Whether it runs, handles states and rotation, and has clean structure

Working basics and clean structure matter most.

From Interview questions: Android and Compose

Using a bank's logo in your app without permission violates which policy area?Related

Answer: Impersonation / intellectual property

Impersonation is not allowed.

From Play policies: privacy, data safety and targets

Since Android 9, plain http:// requests are…Related

Answer: Blocked by default (cleartext not permitted)

Cleartext HTTP is blocked by default; use HTTPS.

From Networking with Retrofit

Which package offers interceptors, timeouts and upload progress?Related

Answer: dio

dio is a feature-rich HTTP client.

From HTTP requests and FutureBuilder

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Permissions, Material 3 and polish” before its exam: Material 3 theming, Material components, Accessibility and adaptive layouts.
  2. Module 9 exam: Permissions, Material 3 and polish · 13 questions · 25 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Testing Android apps. 50 topics left in the course before the final exam.

← Previous: Offline-first apps and DataStore