Permissions in Android: Requesting Access the Right Way
Permissions in Android: Requesting Access the Right Way
Android protects sensitive data and features behind permissions. Some are granted automatically when the app is installed (like internet access); others, called runtime or dangerous permissions (like camera, location, or contacts), must be requested from the user while the app is running, and the user can deny them. To use any permission you first declare it in AndroidManifest.xml, and for runtime permissions you also ask the user with a system dialog. This article shows both, and how to handle a denial gracefully.
Two Kinds of Permissions
- Install-time (normal) permissions are low risk and granted automatically. Example:
INTERNET. You only declare them in the manifest; there is no dialog. - Runtime (dangerous) permissions touch private data or hardware. Examples: camera, fine location, microphone, reading contacts. You declare them in the manifest and request them at runtime, because the user must be able to say no.
Step 1: Declare in the Manifest
Every permission, normal or runtime, must be listed in AndroidManifest.xml.
<!-- Normal permission, granted at install -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Runtime permission, also requires asking the user later -->
<uses-permission android:name="android.permission.CAMERA" />
If you skip the manifest entry, the request will simply fail no matter what you do in code.
Step 2: Check Whether You Already Have It
Before requesting, check if the permission is already granted. The user may have granted it earlier, and you should not nag.
import android.content.Context
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
import android.Manifest
// returns true if the camera permission is already granted
fun hasCameraPermission(context: Context): Boolean {
return ContextCompat.checkSelfPermission(
context,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
}
Want to learn this properly?
Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.
Browse coursesStep 3: Request It in Compose
In Jetpack Compose, you request a permission with an activity result launcher. You register a launcher, then call it when the user does something that needs the permission. The result tells you whether it was granted.
import android.Manifest
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
@Composable
fun CameraButton() {
// remember whether the user granted the permission
var granted by remember { mutableStateOf(false) }
// register a launcher that shows the system permission dialog
val launcher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission()
) { isGranted ->
granted = isGranted // the callback receives the user's choice
}
Button(onClick = {
// launch the request when the user taps the button
launcher.launch(Manifest.permission.CAMERA)
}) {
Text(if (granted) "Camera ready" else "Allow camera")
}
}
Step 4: Handle a Denial Gracefully
The user can deny a permission, and your app must still work, just without that feature. Show a short explanation of why you need it and offer the action again, rather than crashing or repeatedly popping the dialog. Request a permission only when the user is about to use the feature that needs it; that context makes them far more likely to allow it.
Common Mistakes
- Forgetting the manifest entry. Code-side requests fail silently if the permission is not declared.
- Assuming a runtime permission is granted. Always check, and always handle the case where the user says no.
- Requesting everything on app launch. Bombarding the user up front leads to denials. Ask in context, when the feature is used.
- Treating normal and dangerous permissions the same. Internet does not need a dialog; camera does. Know which is which.
- Re-requesting endlessly after a denial. Respect the user's choice; explain the benefit and let them decide, or guide them to settings.
- Not degrading gracefully. If location is denied, the rest of the app should still function.
FAQ
Why does the user have to approve some permissions but not others? Dangerous permissions touch private data or hardware, so Android puts the user in control. Normal permissions are low risk and granted automatically.
Can I force a user to grant a permission? No. You can explain why you need it, but the user can always refuse, and your app must handle that.
What if I only need internet? Internet is a normal permission. Declare it in the manifest and you are done; there is no runtime dialog.
Keep Going
Permissions often unlock networking and storage features, see Calling an API in Android and Local Storage in Android. When your app is ready, learn How to Publish to the Play Store. The full path is at the Android learning hub.
Want hands-on help building apps that use the camera, location, and more? Join the waitlist for the Android Development course at Infoplanet in Jalgaon.
Want to learn this properly?
Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.
Browse coursesFounder, Infoplanet
Atul Kabra founded Infoplanet in 2001 and has spent over two decades teaching programming — C, C++, Java, databases and more — to students across Maharashtra.
Related guides
Activities and Navigation in Android
What an activity is, how its lifecycle works, and how to move between screens cleanly using Navigation Compose, including passing arguments between destinations.
Calling an API in Android with Retrofit and Coroutines
How to call a REST API from an Android app using Retrofit and Kotlin coroutines: declare the endpoint, model the JSON, run the call off the main thread, and handle errors.
Layouts and UI in Android with Jetpack Compose
How to build Android screens with Jetpack Compose: stacking with Column and Row, layering with Box, controlling size and spacing with modifiers, and rendering lists efficiently.
