AppleHealthSync
A React component that manages the synchronization of health data from Apple HealthKit to a FHIR-compliant backend, featuring real-time change detection and network-aware syncing.
Overview
The AppleHealthSync component handles the complex process of reading health data from Apple HealthKit and synchronizing it with a FHIR backend. It provides intelligent syncing with real-time change detection, network awareness, automatic retry mechanisms, and comprehensive progress tracking.
Features
- FHIR Integration: Converts HealthKit data to FHIR Observation resources
- Real-time Sync: Automatically syncs when new data is added to HealthKit
- Change Detection: Subscribes to HealthKit data changes and triggers sync
- Network Awareness: Pauses/resumes sync based on network conditions
- Progress Tracking: Real-time progress updates for each measurement type
- Chunked Processing: Handles large datasets efficiently through batched operations
- Background Sync: Maintains sync operations in the background
- Debounced Updates: Prevents excessive sync operations with intelligent debouncing
Basic Example
import { ObservationCode } from "@ovok/core";
import { AndroidHealthSyncProps, DataSync } from "@ovok/native";
import React from "react";
const dataToSync: AndroidHealthSyncProps["dataToSync"] = {
"body-temperature": {
typeIdentifiers: [
{
typeIdentifier: "BodyTemperature",
code: ObservationCode.BODY_TEMPERATURE,
},
],
minDate: new Date("2025-01-01"),
},
};
const HealthDataSync = () => {
// This component is wrapped in the AndroidHealthConnectAuthorizationProvider
// to handle the authorization process
return (
<DataSync.AndroidHealthConnectAuthorizationProvider
readIdentifiers={["BodyTemperature"]}
>
{/* You have to be authorized to sync the health data */}
<DataSync.AndroidHealthSync dataToSync={dataToSync} />
</DataSync.AndroidHealthConnectAuthorizationProvider>
);
};
export default HealthDataSync;
Props
| Prop | Type | Default | Description |
|---|---|---|---|
dataToSync | Record<HealthSyncKeys, { typeIdentifiers: TypeIdentifier[], minDate?: Date }> | required | Configuration of data types to sync with their identifiers |
chunkSize | number | 5000 | Number of samples to process in each sync batch |
onError | (error: Bundle<Resource> | Error | null) => void | undefined | Callback for sync errors |
onProgress | (progress: Record<MeasurementTypeKey, SyncProgress>) => void | undefined | Callback for real-time progress updates |
Data Configuration
The dataToSync prop defines which health data types to synchronize:
type DataToSync = {
[key in HealthSyncKeys]?: {
typeIdentifiers: {
typeIdentifier: HKQuantityTypeIdentifier; // HealthKit identifier
code: ObservationCode; // FHIR observation code
}[];
minDate?: Date; // Optional start date for sync
};
};
Change Detection Features
- Background Updates: Detects changes even when app is in background (if configured)
- Debounced Sync: Prevents excessive sync operations with 400ms debouncing
- Selective Sync: Only syncs the specific data types that changed
- Memory Efficient: Automatically manages subscriptions and cleanup
Network Behavior
The component automatically manages sync operations based on network conditions:
- WiFi Connection: Full sync operations enabled
- Mobile Data: Sync operations paused (configurable)
- No Connection: All sync operations paused
- Connection Restored: Sync automatically resumes
Progress Tracking
The component provides detailed progress information:
interface SyncProgress {
measurementTypeKey: MeasurementTypeKey;
status: "started" | "completed" | "idle" | "syncing" | "paused";
progress?: {
done: number; // Samples processed
total: number; // Total samples to process
};
}
Progress States
idle: Sync not yet startedstarted: Sync initialization in progresssyncing: Actively processing HealthKit datapaused: Sync paused (network or system reasons)completed: All data successfully synced
Error Handling
Handle various sync error scenarios:
Network-related Errors
const handleSyncError = (error: Error) => {
if (error.message.includes("network")) {
showNotification("Sync paused - waiting for WiFi connection");
}
};
HealthKit Permission Errors
const handleSyncError = (error: Error) => {
if (error.message.includes("authorization")) {
// Guide user to check HealthKit permissions
showHealthKitPermissionGuide();
}
};
Performance Considerations
- Change Subscriptions: Efficiently manages HealthKit change subscriptions
- Debounced Updates: Prevents excessive sync operations with 400ms debouncing
- Chunked Processing: Processes large datasets in configurable chunks
- Memory Management: Automatically cleans up subscriptions and resources
- Network Optimization: Only syncs on WiFi by default
- Background Processing: Supports background sync when properly configured
Background Sync Configuration
To enable background health data sync, configure your app properly:
// app.config.ts
plugins: [
[
"@kingstinct/react-native-healthkit",
{
background: true, // Enable background processing
NSHealthShareUsageDescription: "Background health data sync",
NSHealthUpdateUsageDescription: "Update health data in background",
},
],
];
Platform Requirements
- iOS Only: Exclusive to iOS devices
- HealthKit: Requires device with HealthKit support
- iOS Version: Requires iOS 14.0+ for optimal functionality
- Network: Requires internet connectivity for FHIR backend
- Permissions: Requires appropriate HealthKit permissions
Dependencies
@ovok/core: FHIR client and patient management@kingstinct/react-native-healthkit: iOS HealthKit integration@react-native-community/netinfo: Network status monitoring
Related Components
AppleHealthAuthorizationProvider: Permission managementSyncProgressList: UI component for displaying sync progressAndroid Health Sync: Android equivalent component