@capgo/capacitor-uwb

July 2, 2026 ยท View on GitHub

Capgo - Instant updates for Capacitor

โžก๏ธ Get Instant updates for your App with Capgo

Missing a feature? We'll build the plugin for you ๐Ÿ’ช

Capacitor plugin for Ultra-Wideband (UWB) ranging on iOS and Android.

Why this plugin

This plugin wraps the native UWB ranging APIs on iOS and Android so a Capacitor app can:

  • Check whether the current device supports UWB ranging.
  • Run peer-to-peer ranging on iOS with Apple's Nearby Interaction framework.
  • Run controller/controlee ranging sessions on Android with Jetpack androidx.core.uwb.
  • Receive distance, direction, and session lifecycle updates through plugin listeners.

On iOS, peers exchange NIDiscoveryToken values out-of-band, then call startPeerSession(). On Android, the controller shares ranging parameters out-of-band before the controlee starts its session.

Platform support

PlatformSupport
iOSโœ… Nearby Interaction peer ranging with distance and direction
Androidโœ… Jetpack UWB controller/controlee sessions (Android 12+, UWB hardware)
WebโŒ Not available

Compatibility

Plugin versionCapacitor compatibilityMaintained
v8..v8..โœ…
v7..v7..On demand
v6..v6..On demand

The plugin major version follows the Capacitor major version.

Install

You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command:

npx skills add https://github.com/cap-go/capacitor-skills --skill capacitor-plugins

Then use the following prompt:

Use the `capacitor-plugins` skill from `cap-go/capacitor-skills` to install the `@capgo/capacitor-uwb` plugin in my project.

If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:

bun add @capgo/capacitor-uwb
bunx cap sync

Usage

import { CapacitorUwb } from '@capgo/capacitor-uwb';

const availability = await CapacitorUwb.isAvailable();
if (!availability.available) {
  return;
}

await CapacitorUwb.addListener('rangingUpdate', (update) => {
  console.log(update.distanceMeters, update.direction);
});

// iOS: exchange discovery tokens out-of-band, then start ranging
const { discoveryToken } = await CapacitorUwb.getDiscoveryToken();
await CapacitorUwb.startPeerSession({ peerDiscoveryToken: '<peer-token-base64>' });

// Android: controller shares ranging parameters out-of-band
const controller = await CapacitorUwb.startControllerSession();
await CapacitorUwb.startControleeSession({
  rangingParameters: {
    ...controller.rangingParameters,
    peerAddress: controller.localAddress,
  },
});

await CapacitorUwb.stopSession();

Notes

  • Test on real UWB hardware. Simulators and most desktop browsers do not expose UWB radios.
  • iOS: Add the Nearby Interaction capability in Xcode and set NSNearbyInteractionUsageDescription in Info.plist.
  • Android: The plugin declares android.permission.UWB_RANGING. Exchange ranging parameters out-of-band between controller and controlee before starting sessions.
  • Web: isAvailable() returns supported: false.

Full setup guides: capgo.app/docs/plugins/uwb

Example app

The example-app/ folder contains a small Vite demo for checking availability, exchanging session parameters, listening for ranging updates, and stopping sessions.

API

Capacitor plugin for Ultra-Wideband (UWB) ranging on iOS and Android.

iOS uses Apple's Nearby Interaction framework for peer-to-peer ranging. Android uses Jetpack androidx.core.uwb for controller/controlee sessions.

Both platforms require exchanging discovery tokens or ranging parameters out-of-band (for example over Bluetooth LE or a backend).

isAvailable()

isAvailable() => Promise<UwbAvailabilityResult>

Check whether UWB is supported and currently available on the device.

Returns: Promise<UwbAvailabilityResult>

Since: 8.0.0


getDiscoveryToken()

getDiscoveryToken() => Promise<DiscoveryTokenResult>

Get the local Nearby Interaction discovery token on iOS.

Share the returned token with a peer out-of-band, then call startPeerSession() with the peer token.

Returns: Promise<DiscoveryTokenResult>

Since: 8.0.0


startPeerSession(...)

startPeerSession(options: StartPeerSessionOptions) => Promise<void>

Start a Nearby Interaction peer session on iOS.

ParamType
optionsStartPeerSessionOptions

Since: 8.0.0


startControllerSession(...)

startControllerSession(options?: StartControllerSessionOptions | undefined) => Promise<AndroidControllerSessionResult>

Start an Android UWB controller session and return shareable parameters.

ParamType
optionsStartControllerSessionOptions

Returns: Promise<AndroidControllerSessionResult>

Since: 8.0.0


startControleeSession(...)

startControleeSession(options: StartControleeSessionOptions) => Promise<void>

Start an Android UWB controlee session with parameters from the controller.

ParamType
optionsStartControleeSessionOptions

Since: 8.0.0


stopSession()

stopSession() => Promise<void>

Stop the active UWB ranging session.

Since: 8.0.0


addListener('rangingUpdate', ...)

addListener(eventName: 'rangingUpdate', listenerFunc: (event: RangingUpdateEvent) => void) => Promise<PluginListenerHandle>

Listen for distance and direction updates from an active session.

ParamType
eventName'rangingUpdate'
listenerFunc(event: RangingUpdateEvent) => void

Returns: Promise<PluginListenerHandle>

Since: 8.0.0


addListener('sessionStateChanged', ...)

addListener(eventName: 'sessionStateChanged', listenerFunc: (event: SessionStateChangedEvent) => void) => Promise<PluginListenerHandle>

Listen for session lifecycle changes.

ParamType
eventName'sessionStateChanged'
listenerFunc(event: SessionStateChangedEvent) => void

Returns: Promise<PluginListenerHandle>

Since: 8.0.0


removeAllListeners()

removeAllListeners() => Promise<void>

Remove all registered listeners for this plugin.

Since: 8.0.0


getPluginVersion()

getPluginVersion() => Promise<PluginVersionResult>

Get the current native plugin version.

Returns: Promise<PluginVersionResult>

Since: 8.0.0


Interfaces

UwbAvailabilityResult

Result returned by isAvailable().

PropTypeDescriptionSince
supportedbooleanWhether the device hardware supports UWB ranging.8.0.0
availablebooleanWhether UWB is currently available and ready for a ranging session.8.0.0
platform'ios' | 'android' | 'web'Platform label returned by the native or web implementation.8.0.0

DiscoveryTokenResult

Result returned by getDiscoveryToken() on iOS.

PropTypeDescriptionSince
discoveryTokenstringBase64-encoded NIDiscoveryToken to share with a peer out-of-band.8.0.0

StartPeerSessionOptions

Options for startPeerSession() on iOS.

PropTypeDescriptionSince
peerDiscoveryTokenstringBase64-encoded peer NIDiscoveryToken.8.0.0
isCameraAssistanceEnabledbooleanWhether to enable camera assistance when supported (iOS 16+).8.0.0

AndroidControllerSessionResult

Parameters returned when starting an Android controller session.

PropTypeDescriptionSince
rangingParametersAndroidRangingParametersRanging parameters to share with the controlee out-of-band.8.0.0
localAddressstringLocal UWB address as a base64-encoded byte array.8.0.0

AndroidRangingParameters

Android ranging parameters exchanged out-of-band between controller and controlee.

PropTypeDescriptionSince
sessionIdnumberSession identifier shared by both peers.8.0.0
sessionKeyInfostringOptional base64-encoded session key info.8.0.0
subSessionIdnumberOptional sub-session identifier for provisioned STS.8.0.0
subSessionKeyInfostringOptional base64-encoded sub-session key info.8.0.0
complexChannelUwbComplexChannelChannel configuration for the ranging session.8.0.0
peerAddressstringPeer UWB address as a base64-encoded byte array.8.0.0
uwbConfigTypenumberUWB config type. Defaults to unicast DS-TWR on Android.8.0.0
slotDurationMillisnumberSlot duration in milliseconds.8.0.0
updateRateTypenumberRanging update rate type from RangingParameters on Android.8.0.0

UwbComplexChannel

Android UWB complex channel exchanged out-of-band with a peer.

PropTypeDescriptionSince
channelnumberUWB channel number.8.0.0
preambleIndexnumberPreamble index used for the ranging session.8.0.0

StartControllerSessionOptions

Options for startControllerSession() on Android.

PropTypeDescriptionSince
sessionIdnumberSession identifier shared with the controlee.8.0.0
sessionKeyInfostringOptional base64-encoded session key info.8.0.0
subSessionIdnumberOptional sub-session identifier.8.0.0
subSessionKeyInfostringOptional base64-encoded sub-session key info.8.0.0
complexChannelUwbComplexChannelUWB channel configuration.8.0.0
uwbConfigTypenumberUWB config type. Defaults to unicast DS-TWR.8.0.0
slotDurationMillisnumberSlot duration in milliseconds.8.0.0
updateRateTypenumberRanging update rate type from RangingParameters on Android.8.0.0
peerAddressstringOptional controlee UWB address. When provided, ranging starts immediately.8.0.0

StartControleeSessionOptions

Options for startControleeSession() on Android.

PropTypeDescriptionSince
rangingParametersAndroidRangingParametersRanging parameters received from the controller out-of-band.8.0.0

PluginListenerHandle

PropType
remove() => Promise<void>

RangingUpdateEvent

Payload emitted by the rangingUpdate listener.

PropTypeDescriptionSince
distanceMetersnumberEstimated distance to the peer in meters.8.0.0
directionUwbDirectionDirection vector toward the peer when available.8.0.0
azimuthRadiansnumberAzimuth angle in radians when available.8.0.0
elevationRadiansnumberElevation angle in radians when available.8.0.0
horizontalAngleRadiansnumberHorizontal angle in radians when available.8.0.0
timestampnumberUnix timestamp in milliseconds when the update was received.8.0.0

UwbDirection

3D direction vector reported by UWB ranging.

PropTypeDescriptionSince
xnumberX component of the direction vector.8.0.0
ynumberY component of the direction vector.8.0.0
znumberZ component of the direction vector.8.0.0

SessionStateChangedEvent

Payload emitted by the sessionStateChanged listener.

PropTypeDescriptionSince
stateUwbSessionStateCurrent session state.8.0.0
reasonstringOptional human-readable reason or error description.8.0.0

PluginVersionResult

Result returned when requesting the plugin version.

PropTypeDescriptionSince
versionstringNative plugin version string.8.0.0

Type Aliases

UwbSessionState

Session lifecycle states reported by the plugin.

'initialized' | 'running' | 'suspended' | 'resumed' | 'invalidated' | 'stopped' | 'peerDisconnected'