# Background sync APIs

Canonical page: https://docs.ovok.com/native-sdk/guide/components/background-sync

The `@ovok/native/background-sync` subpath exports Android background controls,
Health Connect headless task helpers, background-safe client storage, and local
notification helpers. Import from this subpath so an app can use these APIs without
loading the package's root UI barrel.

~~~ts
import {
  registerAndroidHealthConnectBackgroundTask,
  runAndroidHealthConnectSync,
  scheduleAndroidHealthConnectSync,
} from "@ovok/native/background-sync";
~~~

The full end-to-end setup, native configuration, and delivery behavior are in the
[background sync guide](/native-sdk/guide/modules/background-sync).

## Android Bluetooth foreground service [#android-bluetooth-foreground-service]

`AndroidBluetoothForegroundService` is a React wrapper for apps that own the BLE
manager and scan lifecycle outside `BTProvider`:

~~~tsx
import { AndroidBluetoothForegroundService } from "@ovok/native/background-sync";

<AndroidBluetoothForegroundService
  enabled={monitoring}
  options={{
    notificationTitle: "Bluetooth monitoring",
    notificationBody: "Listening for health measurements",
    requestBatteryOptimizationExemption: true,
  }}
  onError={({ error }) => reportBluetoothError(error)}
>
  <BluetoothScreen />
</AndroidBluetoothForegroundService>;
~~~

| Prop | Type | Description |
| --- | --- | --- |
| `enabled` | `boolean` | Starts the Android service while true; stops it on false or unmount. |
| `options` | `AndroidBluetoothForegroundServiceOptions` | Optional notification title/body and battery-optimization request. |
| `onError` | `(event: ErrorCallback) => void` | Receives service or permission request failures. |
| `children` | `ReactNode` | Content rendered inside the wrapper. |

This component is an alternative to the provider-managed foreground service. Do not
mount it for a scan already owned by `BTProvider.backgroundSync`; there should be one
service owner per scan. On non-Android platforms the wrapper renders its children and
does not start a native service.

The module also exports `startAndroidBluetoothForegroundService` and
`stopAndroidBluetoothForegroundService` for imperative lifecycle control. These
functions are Android-only and are no-ops on other platforms.

## Android Health Connect headless work [#android-health-connect-headless-work]

| API | Purpose |
| --- | --- |
| `registerAndroidHealthConnectBackgroundTask(task, taskName?)` | Register the JS entry point at app startup. The default task name is `ANDROID_HEALTH_CONNECT_BACKGROUND_TASK`. |
| `runAndroidHealthConnectSync(options)` | Run one import without mounting `AndroidHealthSync`. Requires a restored `client`, `patientId`, and `dataToSync` mapping. |
| `scheduleAndroidHealthConnectSync(options?)` | Schedule periodic WorkManager work. `intervalMinutes` defaults to 15 and values below 15 are raised to 15. |
| `cancelAndroidHealthConnectSync()` | Cancel scheduled periodic work. |
| `ANDROID_HEALTH_CONNECT_BACKGROUND_TASK` | Default task name: `OvokHealthConnectBackgroundSync`. |

The registered callback receives `{ reason?: string }`. If scheduling uses a custom
`taskName`, registration must use the same value. Calls are no-ops on non-Android
platforms. WorkManager may defer execution and requires network connectivity.

`AndroidHealthConnectBackgroundSyncOptions` contains `intervalMinutes`, `taskName`,
`notificationTitle`, and `notificationBody`. `AndroidHealthConnectSyncRunOptions`
contains `client`, `patientId`, `dataToSync`, and optional `chunkSize`, `onError`, and
`onProgress`. These types are exported from this subpath.

Use [`AndroidHealthSync`](/native-sdk/guide/components/data-sync/android/health-sync/) for a foreground React
import, and the [Health Connect authorization provider](/native-sdk/guide/components/data-sync/android/health-connect-authorization-provider/)
to request foreground and optional background-read access.

## Battery optimization helpers [#battery-optimization-helpers]

| API | Purpose |
| --- | --- |
| `isAndroidBatteryOptimizationIgnored()` | Read whether Android currently exempts the app from Doze optimizations. |
| `requestAndroidBatteryOptimizationExemption()` | Open Android's consent/settings flow when it can be shown. The result can be `false` while consent is pending or has not been granted; re-check after the app resumes. |

The request is explicit opt-in and does not grant an exemption itself. The helper
returns `true` on non-Android platforms.

## Background-safe client storage [#background-safe-client-storage]

`createBackgroundSafeClientStorage` adapts a SecureStore-compatible implementation
for hosts still using that standalone storage adapter. The native next `Ovok`
client accepts `secureStore` directly and uses `SecureStoreStorage` for its session
and account-scoped health cursors:

~~~ts
import { Ovok } from "@ovok/native/next";
import * as SecureStore from "expo-secure-store";

const client = new Ovok({
  baseUrl: "https://api.example.com",
  tenantCode: "your-tenant",
  secureStore: SecureStore,
  secureStoreOptions: { keychainAccessible: SecureStore.AFTER_FIRST_UNLOCK },
});
~~~

The legacy adapter remains available when an app explicitly needs its indexed
storage API:

~~~ts
const storage = createBackgroundSafeClientStorage({
  secureStore,
  keychainService: "com.example.app",
  keychainAccessible: SecureStore.AFTER_FIRST_UNLOCK,
});
~~~

`BackgroundSafeSecureStore` requires `getItemAsync` and `setItemAsync`, with optional
`deleteItemAsync`. The returned `BackgroundSafeClientStorage` exposes `getItem`,
`setItem`, `removeItem`, `clear`, and `reload`. `reload` re-reads the adapter's key
index after the device is unlocked. A protected read failure returns `null` without
deleting the stored value; retry after the OS makes the keychain available.

The adapter does not choose an app key, own credentials, or restore an authenticated
client. The host app remains responsible for that work in the Health Connect headless
task.

## Local notifications [#local-notifications]

The subpath exports `getPushNotificationPermission`,
`requestPushNotificationPermission`, and `showPushNotification`. They load the
optional `expo-notifications` peer only when called. Permission status is
`"granted"`, `"denied"`, or `"undetermined"`. Request permission in the foreground.

`showPushNotification` schedules an immediate local notification. It does not create
remote push tokens or schedule background execution. BLE queue notifications can
instead be configured through `BTProvider.backgroundSync.notifications`; see the
[background sync guide](/native-sdk/guide/modules/background-sync).

## Related component references [#related-component-references]

- [`BTProvider.backgroundSync`](/native-sdk/guide/components/bt-management/bt-provider/) — durable BLE result queue and scan integration.
- [`BackgroundSyncSetting`](/native-sdk/guide/components/ui/background-sync-setting) — UI toggle for background scan state.
- [`AndroidHealthSync`](/native-sdk/guide/components/data-sync/android/health-sync/) — foreground Health Connect import.
- [`AppleHealthSync`](/native-sdk/guide/components/data-sync/apple/health-sync/) — HealthKit observer delivery.
