Skip to content

How to Fix Android Permission Denied (Runtime Permission) Error

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about How to Fix Android Permission Denied (Runtime Permission) Error. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

The Problem

Your app crashes or silently fails when accessing a feature:

java.lang.SecurityException: Permission Denial:
reading com.android.providers.contacts.ContactsProvider
requires android.permission.READ_CONTACTS

Or the API returns no data without an error message because the permission was denied.

Quick Fix

Step 1: Declare the permission in AndroidManifest.xml

<manifest ...>
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

<uses-permission> declares the permission to the system. For dangerous permissions (camera, location, contacts, etc.), runtime request is also required.

Step 2: Request permission at runtime (API 23+)

private val CAMERA_PERMISSION_CODE = 100

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
    != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(
        this,
        arrayOf(Manifest.permission.CAMERA),
        CAMERA_PERMISSION_CODE
    )
} else {
    openCamera()
}

Step 3: Handle the permission result

override fun onRequestPermissionsResult(
    requestCode: Int, permissions: Array<String>, grantResults: IntArray
) {
    when (requestCode) {
        CAMERA_PERMISSION_CODE -> {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                openCamera()
            } else {
                // Show rationale and guide user to Settings
            }
        }
    }
}

Step 4: Handle permanently denied permission

If the user checked "Never ask again," shouldShowRequestPermissionRationale returns false:

if (!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
    // Navigate user to app settings
    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
        data = Uri.fromParts("package", packageName, null)
    }
    startActivity(intent)
}

Step 5: Check for permission on Android 13+

Android 13 introduces granular photo and notification permissions:

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

Replace READ_EXTERNAL_STORAGE with READ_MEDIA_IMAGES for API 33+.

Step 6: Test with permission off

On emulator or device:

Settings > Apps > Your App > Permissions > Toggle off

Verify the app degrades gracefully instead of crashing.

Prevention

  • Request permissions only when the feature is accessed, not at app launch.
  • Show a rationale dialog before requesting sensitive permissions.
  • Handle the "never ask again" case with a Settings deep link.

Common Mistakes with permission denied

  1. Using return to exit a function early instead of wrapping a pure value in the monad
  2. Mixing let bindings with <- bindings in do notation, producing type errors
  3. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors

These mistakes appear frequently in real-world Android code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Do I need runtime permission for all declarations in the manifest?

No. Only dangerous permissions need runtime request. Normal permissions (INTERNET, VIBRATE) are granted automatically at install time.

What is the difference between checkSelfPermission and requestPermissions?

checkSelfPermission checks the current grant status without prompting. requestPermissions shows the system dialog. Always check before requesting.

Why does my permission dialog not show?

On Android 6+, the dialog appears only when you call requestPermissions. If permission is already granted, it returns immediately without the dialog. Also, some emulators have permission settings that auto-deny.

DodaTech Tool Reference

Durga Antivirus Pro analyzes permission usage across installed apps and flags over-permissioned applications. Use Doda Browser's Privacy Dashboard to audit which permissions your app requests at runtime.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro