Surprising fact: over 70% of Android users install apps without reviewing what they can access, leaving sensitive data exposed.
Modern Android protects restricted data (contacts, location) and actions (recording audio, pairing devices) with distinct classes of controls. Install-time items show on an app’s detail page in stores like Google Play and are granted at install. Runtime requests appear while the app runs and let the user accept or deny in context.
There are three main categories: install-time (normal and signature), runtime (“dangerous”), and special rights that need separate system screens. Best practice favors transparency, least privilege, and clear prompts so people grant only what an application truly needs.
Key Takeaways
- Android groups access into install-time, runtime, and special categories.
- Install-time items appear on the app store page; runtime prompts happen in-app.
- Users can revoke runtime permission later from device Settings.
- Request the least privilege and explain why your app needs access.
- Special app access is managed under system settings and covers powerful actions.
Understand Android app permissions today: types, workflow, and why they matter
Apps request different kinds of access on Android; each type has its own rules and a specific user-facing workflow. This section explains the levels, when the system prompts, and a concise process you should follow.
Install-time: normal and signature protection
Normal items are low-risk and are granted automatically at install. These show up on an app’s details page so people see them before they install.
Signature items require the same signing certificate as the defining component or OS. Many signature permissions are not available to third‑party apps; they enforce platform integrity at this protection level.
Runtime (dangerous): when prompts appear
Runtime permissions cover private user data and impactful actions like location or contacts. Your app must check each time and request before access.
Ask only when a user triggers the feature. A well-timed prompt builds trust and reduces denial rates.

Special app access and permission groups
Special permissions protect powerful operations (for example, drawing over other apps) and live under Settings > Special app access. Use them only when the use case is essential and obvious.
Android groups related permissions, but groups can change. Code against specific items, not groups.
“Declare only what you need, request at the moment of need, and handle denials gracefully.”
- Minimize asks.
- Declare required items in your manifest; see manifest basics.
- Request at runtime in context and treat timing as a trust signal.
APK permissions guide: how to review, grant, and revoke app access on your device
The system shows runtime prompts when an app requests a sensitive resource. You can grant, deny, or choose “Don’t ask again,” and you can always change choices later from Settings.
When an app requests sensitive access, the prompt names the permission and the app asking so you decide in the moment. Grant only if the request matches the action you just triggered and you trust the developer.

Responding to runtime permission prompts in context
What to watch for: look for relevance. If you tap “Take Photo,” a camera request is reasonable. If a simple note app asks for SMS, that is suspicious.
- Choices: grant, deny, or “Don’t ask again” — changing the last option requires visiting Settings > Apps > [App name] > Permissions.
- Contextual approval: approve only when the app ties the request to a clear action.
- Audit regularly: open Settings > Apps > [App name] > Permissions and revoke anything unnecessary; the system enforces changes at run time.
Managing Special app access in Settings
Powerful toggles live under Settings > Special app access. Review items like “Display over other apps,” “Send SMS,” and “Install unknown apps.” Disable anything that isn’t essential.
“Treat runtime prompts as guardrails — they keep you in control while apps ask for only what they need.”
- Watch for mismatched requests and deny or uninstall if behavior seems risky.
- If an app breaks after denial, expect a clear degraded mode or rationale from the developer.
- Advanced users can use ADB to list, grant, or revoke entries for troubleshooting; most users should stick to the Settings page.
How to declare and request app permissions in code the right way
Declare needed access in the manifest and ask at runtime only when the feature runs. Target API levels correctly so you avoid legacy asks and keep user trust.
Treat the manifest as a contract — declare each capability your application requires and scope it by API level.
Declare in AndroidManifest.xml
Start with <uses-permission> entries for only the capabilities your app needs. For features that only apply on modern devices, use <uses-permission-sdk-23> so older platforms do not inherit runtime-only requirements.
Limit scope with android:maxSdkVersion when sensible (for example, restrict READ_EXTERNAL_STORAGE up to 28 if you target scoped storage on Android 10+). Manifest declarations also show up on Google Play, so be clear and honest.

Request at runtime and make hardware optional
At API level 23+ follow this flow: call checkSelfPermission, present a short rationale if needed, call requestPermissions, then handle results in onRequestPermissionsResult. Re-check before each sensitive operation because users can revoke access at any time.
Use <uses-feature android:required=”false”> for hardware like camera. Check availability with PackageManager.hasSystemFeature and degrade features if the device lacks hardware.
Sample process and checklist
| Step | API | Action | Why it matters |
|---|---|---|---|
| Manifest | All | Add <uses-permission> / <uses-permission-sdk-23> | Informs store and user before install |
| Check | 23+ | call checkSelfPermission | Avoid unnecessary prompts |
| Explain | 23+ | Show brief rationale | Improves acceptance and trust |
| Request | 23+ | requestPermissions → onRequestPermissionsResult | Handle grant/deny and fallback flows |
For a quick checklist before release, map each feature to its access and test flows on devices at different API levels. If you want a pre-install safety check, see our is your app safe checklist.
Practical examples: camera, location, and SMS permission requests
Show the prompt when the feature runs and explain the benefit. Clear timing and brief rationale improve acceptance and keep users in control.
Camera access: why capture must be obvious
Example: when the app opens a “Scan document” screen and the user taps “Capture,” request the camera right then. State that you’ll use the access only to capture the document image.
Tip: stop the viewfinder as soon as capture completes and show a visual indicator while the camera is active.

Location access: foreground vs. contextual need
Example: ask for foreground location when the user starts “Find nearby stores,” not at launch. Explain how precise data improves results and offer a ZIP code fallback.
Prefer coarse location in most cases. Reserve background requests for rare, justified case scenarios and follow platform rules.
SMS interactions: safe send/receive practices
Example: use SMS Retriever APIs to capture one‑time codes instead of asking full SMS rights. If you must request send/receive, do it in context and explain why.
- Group behavior: related SMS items may be grouped by the system; still declare and check each item your app uses.
- Test flows: validate denials, “Don’t ask again,” and Settings toggles so the app degrades gracefully.
“Tie every request to an explicit action and tell users what benefit they get.”
Best practices to keep users safe and your app compliant
Keep access minimal, be clear with users, and audit every library or manifest entry before release.
Keep control and minimize risk by asking only for the exact access your application needs when a user takes an action. Sequence each step so runtime requests appear in context and feel natural.

Request the minimal permission set tied to user actions
Map each feature to the smallest set of rights. Request runtime access only when a user triggers the feature. This reduces attack surface and improves approval at runtime.
Be transparent about what, why, and what happens if denied
Use short in-product copy that explains what you’ll access, why, and how the app behaves if the user denies access. Offer fallbacks and an easy path to settings so the user can re-enable later.
Consider third‑party library dependencies and their permissions
Audit SDK manifests before you ship. Remove libraries that add risky entries without clear value. Add a release‑level review process involving security and product teams.
Rethink broad storage; prefer app-specific directories
Avoid broad READ/WRITE_EXTERNAL_STORAGE on modern levels. Use app-specific external directories (for example, getExternalFilesDir) and scoped storage to keep user files isolated.
“Declare the least, ask in context, and design graceful fallback paths.”
Conclusion
Good practice makes each access prompt predictable, short, and clearly tied to the task. Android’s model centers on runtime control, clear manifest scoping, and Special app access for powerful actions.
What to do now: declare only what your app needs, tie each request to a user action, and make it simple for users to change choices in Settings.
Approve contextual app requests on your device and audit granted entries regularly. Treat camera and location as high‑risk examples and revoke when idle. Keep store page content consistent with actual behavior and the permissions requested.
Developers: document every request path, test degraded modes, and delay runtime prompts until the feature runs. For implementation details, see requesting permissions.
Security is a habit: follow these steps, revisit this content when platform changes land, and make audits part of your release cycle.