Runtime permissions

Prompt for camera, location, or contacts before using a gated feature.

Request a permission

Show the native OS permission prompt for one capability. Call it right before you use the feature. permission is one of "camera", "contacts", "record audio", "write to storage", or "location".

The resolved promise tells you the request was sent, not whether the user said yes — read the current state with permissions.status(), or listen for the permissions.changed event.

The grant/deny outcome arrives on the permissions.changed event. Read the current state with permissions.status().

import { createBdkNative } from "@bdk/native/browser";

const bdk = createBdkNative();

// Fires the native prompt. The resolved value is a dispatch
// receipt, NOT whether the user granted access.
await bdk.permissions.ask("camera");

Gate a feature behind a permission

Check the current status, prompt only if it isn't granted, then wait for the deviceInfo event to confirm before using the feature. Get the current snapshot from bdk.ready() or bdk.getDeviceInfo(); the deviceInfo event delivers the updated one after the user answers. To read the real OS authorization state, use status().

Status field names don't match the PermissionName strings:

  • "camera"cameraPermissionStatus
  • "contacts"contactsPermissionStatus
  • "record audio"audiorecordPermissionStatus
  • "write to storage"externalstoragePermissionStatus
  • "location"locationPermissionStatus
import { createBdkNative } from "@bdk/native/browser";

const bdk = createBdkNative();

async function openCamera() {
  const info = await bdk.ready();

  if (info?.cameraPermissionStatus === "granted") {
    bdk.media.capturePhoto();
    return;
  }

  // Ask, then wait for the refreshed deviceInfo to confirm.
  const off = bdk.on("deviceInfo", (next) => {
    if (next.cameraPermissionStatus === "granted") {
      off();
      bdk.media.capturePhoto();
    }
  });

  await bdk.permissions.ask("camera");
}

Check permission status

Read the current OS authorization map — the full set, or a filtered list via types. This reads state; it does not prompt.

Canonical types: push, location, camera, photos, microphone, contacts, and tracking (iOS). Each entry has status (granted, denied, notDetermined, limited, provisional, restricted, unsupported), canPrompt, and an optional detail with location precision (precise or approximate) and scope (whenInUse or always). Older permission names are aliased to their canonical keys on the device; the result's aliasesApplied map reports any renames.

This feature can be switched off in a given app build — check await bdk.capabilities.has("permissions") before showing the UI. See Detect features. When it's off, the call resolves ok: false with code: "common/feature_disabled".

PropertyTypeDescription
typesstring[]Subset to report. Omit for the full map.

A granted camera status is OS authorization only — it does not guarantee getUserMedia() will succeed.

import { createBdkNative } from "@bdk/native/browser";

const bdk = createBdkNative();

if (!(await bdk.capabilities.has("permissions"))) {
  // Feature isn't enabled in this build
}

const result = await bdk.permissions.status();

if (!result.ok) {
  console.error(result.code, result.message);
} else {
  console.log(result.platform, result.permissions.camera?.status);
}

React to changes

The permissions.changed event fires after a prompt and after the user returns from settings — not on the first snapshot. Subscribe before you ask or open settings. The payload has the changed type names and the full refreshed permissions map.

bdk.on("permissions.changed", ({ changed, permissions }) => {
  console.log(changed, permissions.camera?.status);
});

await bdk.permissions.ask("camera");

Open the settings screen

Open the OS settings page for this app (section: "app") or its notifications (section: "notifications"). The resolved call only means the screen opened — the outcome arrives on permissions.changed after the user returns. Subscribe before you call.

PropertyTypeDescription
sectionstringapp or notifications.
bdk.on("permissions.changed", ({ changed, permissions }) => {
  console.log("after settings", changed, permissions);
});

const result = await bdk.permissions.openSettings({ section: "notifications" });

if (!result.ok) {
  console.error(result.code, result.message);
}

App tracking (iOS)

Read or request Apple's tracking authorization, then read idfa when it is granted. iOS only — on Android the call resolves ok: false with code: "common/unsupported_platform".

Statuses: granted, denied, restricted, notDetermined. idfa is a string when authorized, otherwise null. A denial still resolves ok: true — it's an answer, not an error.

Check await bdk.capabilities.has("att") before showing the UI. When the feature is off, the call resolves ok: false with code: "common/feature_disabled". Subscribe to att.changed for later transitions.

Present a short explainer, then call request() when canPrompt is true. prompted: true means a request was issued, not that the system dialog appeared.

if (!(await bdk.capabilities.has("att"))) {
  // Feature isn't enabled in this build
}

const current = await bdk.att.status();

if (!current.ok) {
  console.error(current.code, current.message);
} else if (current.canPrompt) {
  const result = await bdk.att.request();
  if (result.ok) {
    // denied is still ok: true
    console.log(result.status, result.idfa);
  }
}