How to Manage and Revoke Runtime App Permissions on Android Using ADB

In modern Android versions, applications must request user authorization for sensitive hardware and data access at runtime. These protected capabilities—classified as dangerous permissions—include access to the device microphone, camera, background location, contacts, and notification channels. When developing automated test suites, testing permission denial recovery, or setting up test devices in Continuous Integration (CI) pipelines, manually tapping on-screen confirmation dialogues is inefficient. The Android Debug Bridge (ADB) pm (Package Manager) and cmd permission services allow developers and QA engineers to grant, revoke, and reset permissions programmatically from the terminal.

Understanding Android Runtime Permission Architecture

Android permissions fall into two primary architectural classifications:

  • Normal Permissions: Granted automatically at installation time without user prompting (such as internet access or Bluetooth pairing).
  • Runtime (Dangerous) Permissions: Access sensitive user data or physical sensors. Even if declared in the app’s AndroidManifest.xml, the app cannot access the underlying resource until granted by the user or an administrative controller.

Permissions are tracked per package name and scoped to specific Android user profiles (such as User 0 for personal or User 10 for work profiles). The ADB shell command bypasses graphical prompts and directly modifies the system’s runtime permission database.

Auditing Permissions Declared and Granted to an App

Before modifying permissions, inspect which dangerous permissions an application package declares and what their current authorization status is.

Ensure your Android device has USB Debugging enabled, connect it to your computer, and verify connectivity:

adb devices

To inspect all permissions associated with a specific package (for example, com.example.myapp), execute the dumpsys package command filtered for permission records:

adb shell dumpsys package com.example.myapp | grep -A 20 "runtime permissions:"

The output enumerates each dangerous permission alongside its state:

runtime permissions:
  android.permission.ACCESS_FINE_LOCATION: granted=false, flags=[ USER_SET ]
  android.permission.CAMERA: granted=true, flags=[ USER_SET|GRANTED_BY_DEFAULT ]
  android.permission.RECORD_AUDIO: granted=false, flags=[ USER_SET ]
  android.permission.POST_NOTIFICATIONS: granted=true, flags=[ USER_SET ]

The granted=true flag confirms active permission, while granted=false indicates the app will encounter an authorization rejection unless requested.

Granting Runtime Permissions via ADB

To grant a specific runtime permission without prompting the user on-screen, use the pm grant command:

adb shell pm grant com.example.myapp android.permission.ACCESS_FINE_LOCATION

To grant camera and audio recording permissions simultaneously, run successive grant commands:

adb shell pm grant com.example.myapp android.permission.CAMERA
adb shell pm grant com.example.myapp android.permission.RECORD_AUDIO

The command executes silently and updates the system permission registry immediately. When the application next invokes ContextCompat.checkSelfPermission(), the Android framework reports PERMISSION_GRANTED without displaying a dialogue.

Revoking Runtime Permissions to Test App Error Handling

A resilient Android application must handle permission revocation gracefully, ensuring it does not crash if a user disables camera or location access from System Settings. Testing this behavior during development is simple using the pm revoke command:

adb shell pm revoke com.example.myapp android.permission.CAMERA

When a permission is revoked via ADB, the Android operating system terminates the application’s process immediately (mirroring what occurs when a user revokes permissions in System Settings). When the app is relaunched, it must request the permission again or degrade its UI gracefully.

Automatically Granting All Permissions During App Installation

During automated testing with frameworks like Espresso, Appium, or UI Automator, applications are frequently uninstalled and reinstalled between test runs. Rather than granting each permission individually after installation, ADB supports the -g flag to grant all declared runtime permissions during the install step:

adb install -g app-debug.apk

The -g switch automatically scans the APK’s manifest and grants every declared dangerous permission immediately upon deployment, saving time in test suites.

Managing Permissions Across Multiple User Profiles

If your device utilizes multiple user profiles (such as multi-user guest modes or Android Enterprise Work Profiles), permissions are maintained in isolated databases per user ID.

To grant a permission specifically to an application running inside a Work Profile (typically User 10), pass the --user parameter:

adb shell pm grant --user 10 com.example.myapp android.permission.ACCESS_FINE_LOCATION

To verify which user IDs currently exist on the device, run adb shell pm list users.

Resetting Permission States to Clean Factory Baselines

When testing first-time user onboarding and initial permission rationale dialogs, apps retain flags like USER_SET or “Don’t ask again”. To wipe all runtime permission decisions and return an app to a fresh, unprompted state, use the reset-permission-states command:

adb shell cmd permission reset-permission-states com.example.myapp

All previously granted permissions are cleared, allowing you to test initial onboarding workflows from a clean slate.

Mastering ADB permission commands gives developers and QA teams complete control over Android’s privacy framework, accelerating test automation and ensuring robust error handling.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.