Skip to main content

BTProvider

BTProvider is the React boundary for an SDK-managed Bluetooth session. It requests runtime permissions, starts discovery for the device declarations you accept, exposes the runtime to Bluetooth hooks and UI, and releases managed devices when the provider unmounts.

Import it from @ovok/native/bt-management.

Minimal setup​

import { BleManager } from "react-native-ble-plx";
import { BTProvider, IntegratedDevices } from "@ovok/native/bt-management";

const bleManager = new BleManager();
const acceptedDevices = [IntegratedDevices.BP2] as const;

<BTProvider
bleManager={bleManager}
acceptedDevices={acceptedDevices}
onDeviceFound={(device) => device.connect()}
onResult={(result) => saveMeasurement(result)}
>
<MeasurementScreen />
</BTProvider>;

Keep bleManager and acceptedDevices stable. A new array on each render changes the provider's manager configuration and restarts the session.

Props​

PropTypePurpose
bleManagerBleManagerNative BLE manager owned by the app and used by the provider.
acceptedDevicesreadonly tuple of AcceptedDeviceBuilt-in IntegratedDevices values and/or custom declarations the manager should recognize.
onAccessPermissionChanged(granted: boolean) => voidReceives the current permission result after a request.
permissionFallback() => ReactNodeReplaces the default settings prompt while permission is missing.
onDeviceFound(device, manager) => Promise<void>Called after an accepted device is discovered. Connect or apply app policy here.
onDeviceStatusChanged(event) => voidReceives compact device status transitions.
onConnectionEvent(event) => voidReceives pairing, bond, battery, and history-transfer events.
onResult(result) => voidReceives normalized measurement data and its stable result ID.
onError(event) => voidReceives Bluetooth and measurement errors.
autoConnectbooleanConnects the only candidate automatically after a scan settle window; multiple candidates are sent to onDeviceSelectionRequired.
autoConnectDelayMsnumberSettle interval before the manager chooses or reports auto-connect candidates.
onDeviceSelectionRequired(selection) => voidReceives multiple candidates and a select(device) function when auto-connect finds more than one.
oneReadingPerConnectionbooleanEnables the manager's one-reading-per-connection behavior.
deliveredEcgFileNamesreadonly string[]Supplies known-delivered ECG file names to device handlers that support file history.
resultPoliciespartial device-key mapChooses result filtering policies for supported device keys.
backgroundSyncBackgroundSyncOptionsEnables the opt-in durable queue and background scan configuration. See Background sync.

The precise callback event shapes are documented under provider callbacks.

Background result delivery​

backgroundSync is opt-in. It enables background scan behavior, creates a durable result queue, and starts the provider-managed Android connected-device foreground service. The queue configuration requires persistent storage and an asynchronous delivery callback:

<BTProvider
bleManager={bleManager}
acceptedDevices={acceptedDevices}
backgroundSync={{
enabled: true,
storage: {
getItem: (key) => measurementStore.getItem(key),
setItem: (key, value) => measurementStore.setItem(key, value),
},
onResult: async (result) => {
await uploadMeasurement(result, { idempotencyKey: result.id });
},
android: {
foregroundService: {
notificationTitle: "Bluetooth monitoring",
notificationBody: "Listening for health measurements",
},
},
}}
>
<MeasurementScreen />
</BTProvider>

storage must survive process restarts. The queue writes the result before invoking onResult and removes it after that promise resolves. Delivery is at least once, so deduplicate server writes by result.id. The result also includes queueId, queuedAt, and attempt. Failed items remain queued for automatic retry; default retry settings are three attempts with a 30-second exponential backoff base.

The provider's separate onResult prop remains an immediate measurement callback. It is not the queue acknowledgement and its return value is not awaited. Use backgroundSync.onResult for app-owned delivery that must complete before an item is removed from the queue.

backgroundSync.android.foregroundService controls the provider-managed Android service notification and optional battery-optimization request. If the app owns the BLE scan outside this provider, use the standalone AndroidBluetoothForegroundService instead. Do not start both service owners for the same scan.

For the iOS restoration identifier, service UUID filters, Android native setup, and HealthKit or Health Connect background paths, see the background sync guide.

Permission behavior​

On mount, the provider requests Bluetooth permissions for the current platform. Android 12 and later requests BLUETOOTH_CONNECT and BLUETOOTH_SCAN; earlier Android versions request fine location. iOS requests Bluetooth access. It checks again when the app becomes active. Configure the corresponding native declarations in the installation guide.

While the first request is unresolved, the provider renders a loading indicator. If access is denied, it calls permissionFallback when supplied; otherwise it renders DefaultPermissionFallback, which opens the app settings.

Runtime lifetime​

The provider creates its manager only when acceptedDevices has at least one entry. It starts scanning after callback subscriptions are installed. On teardown it stops the scan, removes listeners, and destroys the manager. Place the provider at the lowest stable tree level that should keep the scan active.

Bluetooth hooks and PairingFlow must render beneath this provider. A route may read runtime data while the provider is mounted, but it should not create a competing manager of its own.