Runtime Permissions

Requesting and Checking Runtime Permissions

Android grants "dangerous" permissions such as location at run time. Every plugin that needs one has checkPermissions(), which reads the state without asking, and requestPermissions(), which may show the system dialog. Both return one PermissionState per alias:

The four permission states Capacitor 243,123 plugins report
State Meaning What to do
prompt Never asked Explain the feature, then request
prompt-with-rationale Refused once; Android may ask again Explain why before requesting again
granted Allowed Use the feature
denied Refused for good, or blocked Point to the app's settings

A fresh install of BookNest, checked from the DevTools console:

Checking two plugins' permissions without askingJavaScript
const { Geolocation, Camera } = Capacitor.Plugins;
console.log(JSON.stringify(await Geolocation.checkPermissions()));
console.log(JSON.stringify(await Camera.checkPermissions()));
Output
{"coarseLocation":"prompt","location":"prompt"}
{"saveGallery":"prompt","readExternalStorage":"prompt","camera":"granted","photos":"granted"}

Camera reports camera as granted because the manifest does not declare the CAMERA permission: the plugin only needs it when you do, and otherwise delegates to the camera app (Camera). Tapping "Don't allow" in the location dialog of Geolocation made where() log "location":"prompt-with-rationale", and a second request showed the dialog again.

Since Android 11, a second refusal counts as "don't ask again": requestPermissions() then returns denied without a dialog, and only the app's system settings can change it. So ask in context, when the reader taps Where, not at launch, and explain before a second request. For testing, adb shell pm revoke and pm grant flip a runtime permission without the dialog. Plugins you write declare their aliases in @CapacitorPlugin(permissions = ...) (Custom Plugins).