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
| Prop | Type | Purpose |
|---|---|---|
bleManager | BleManager | Native BLE manager owned by the app and used by the provider. |
acceptedDevices | readonly tuple of AcceptedDevice | Built-in IntegratedDevices values and/or custom declarations the manager should recognize. |
onAccessPermissionChanged | (granted: boolean) => void | Receives the current permission result after a request. |
permissionFallback | () => ReactNode | Replaces 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) => void | Receives compact device status transitions. |
onConnectionEvent | (event) => void | Receives pairing, bond, battery, and history-transfer events. |
onResult | (result) => void | Receives normalized measurement data and its stable result ID. |
onError | (event) => void | Receives Bluetooth and measurement errors. |
autoConnect | boolean | Connects the only candidate automatically after a scan settle window; multiple candidates are sent to onDeviceSelectionRequired. |
autoConnectDelayMs | number | Settle interval before the manager chooses or reports auto-connect candidates. |
onDeviceSelectionRequired | (selection) => void | Receives multiple candidates and a select(device) function when auto-connect finds more than one. |
oneReadingPerConnection | boolean | Enables the manager's one-reading-per-connection behavior. |
deliveredEcgFileNames | readonly string[] | Supplies known-delivered ECG file names to device handlers that support file history. |
resultPolicies | partial device-key map | Chooses result filtering policies for supported device keys. |
backgroundSync | BackgroundSyncOptions | Enables 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.