Camera & media

Take photos, capture a screenshot, record audio, and scan barcodes from the device.

Take a photo

Open the camera to take a photo. The image arrives on the photoCaptured event, so subscribe before you call, and ask for camera permission first.

capturePhoto emits photoCaptured; pickPhoto emits photoSelected. They are not interchangeable.

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

const bdk = createBdkNative();

bdk.on("photoCaptured", (photo) => {
  console.log(photo.fileUrl, photo.contentType); // MediaResult
});

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

Use the photo result

The photoCaptured listener receives a MediaResult. Use dataUri to preview inline and fileUrl to upload. bdk.on(...) returns an unsubscribe function.

PropertyTypeDescription
fileUrlstring | nullHosted URL of the file — use this to upload.
dataUristring | nullData URI — use this to preview inline.
contentTypestring | nullThe file's MIME type.
dataThe raw file data from the device.
const off = bdk.on("photoCaptured", (photo) => {
  if (photo.dataUri) {
    (document.querySelector("#preview") as HTMLImageElement).src = photo.dataUri;
  }
  if (photo.fileUrl) {
    void uploadAvatar(photo.fileUrl);
  }
});

await bdk.media.capturePhoto();

off(); // when done

Pick from the photo library

Open the photo library instead of the camera. Results arrive on the photoSelected event, not photoCaptured.

bdk.on("photoSelected", (photo) => console.log("picked", photo.fileUrl));

await bdk.media.pickPhoto();

Take a screenshot

Capture a screenshot of the current screen. The image arrives on the screenshot event.

bdk.on("screenshot", (image) => console.log("captured", image));

await bdk.media.captureScreenshot();

Record audio

Open the native audio recorder. The recording arrives on the audioRecorded event as a MediaResult — use fileUrl to upload it.

bdk.on("audioRecorded", (audio) => {
  if (audio.fileUrl) void uploadClip(audio.fileUrl); // MediaResult
});

await bdk.media.recordAudio();

Scan a barcode

Open the scanner for QR codes and barcodes. The decoded value arrives on the barcodeScanned event.

bdk.on("barcodeScanned", (code) => console.log("scanned", code));

await bdk.media.scanBarcode();

Fall back on the web

Outside the app the call resolves with triggered: false and photoCaptured never fires. Detect this and show a standard <input type="file" capture> instead.

const result = await bdk.media.capturePhoto();

if (!result.triggered) {
  document.querySelector("#file-input")?.removeAttribute("hidden");
}

Pick multiple photos

Open the system photo picker so the user can select more than one image. Unlike the helpers above, the photos arrive on the awaited call — there is no event.

PropertyTypeDescription
limitnumberMax photos to select. Native accepts 1–30.
resultstringHow to return each photo: base64 or fileUrl.
maxDimensionPxnumberLongest edge in pixels.
jpegQualitynumberJPEG quality from 0.1 through 1.0.

Success is { ok: true, selectedCount, succeededCount, failedCount, items } — each item is a JPEG BdkMediaItem. If the user cancels, the call resolves ok: false with code: "common/cancelled"; treat that as a normal outcome.

This feature can be switched off in a given app build. Check await bdk.capabilities.has("media") before showing the UI — see Detect features. When it's off, the call resolves ok: false with code: "common/feature_disabled". Builds can cap the limit and disable file URLs.

if (!(await bdk.capabilities.has("media"))) return;

const result = await bdk.media.pickPhotos({
  limit: 5,
  result: "base64",
  maxDimensionPx: 2048,
  jpegQuality: 0.8
});

if (!result.ok) {
  if (result.code === "common/cancelled") return; // user dismissed the picker
  console.error(result.code, result.message);
  return;
}

console.log(result.selectedCount, result.succeededCount, result.failedCount);
for (const item of result.items) {
  console.log(item.width, item.height, item.name); // BdkMediaItem
}

Take a photo from the camera

Open the system camera and take one photo. The image arrives on the awaited call as a single BdkMediaItem — no event. camera is back or front; on Android it is a best-effort hint.

The same result, maxDimensionPx, and jpegQuality options as Pick multiple photos apply.

const result = await bdk.media.takePhoto({ camera: "front" });

if (!result.ok) {
  if (result.code === "common/cancelled") return;
  console.error(result.code, result.message);
  return;
}

console.log(result.item.width, result.item.height); // BdkMediaItem

Show a photo

Turn a picked or captured item into a data URI you can put in an <img>. The call is synchronous and returns null when the item is file-URL-only.

const uri = bdk.media.toDataUri(item);

if (uri) {
  (document.querySelector("#preview") as HTMLImageElement).src = uri;
}