[go: up one dir, main page]

open_wearables_health_sdk 0.0.10 copy "open_wearables_health_sdk: ^0.0.10" to clipboard
open_wearables_health_sdk: ^0.0.10 copied to clipboard

Flutter SDK for secure background health data synchronization from Apple HealthKit (iOS) and Samsung Health / Health Connect (Android) to the Open Wearables platform.

Open Wearables Health SDK (Flutter) #

A Flutter plugin for secure background health data synchronization from Apple HealthKit (iOS), Samsung Health, and Health Connect (Android) to your backend.

Part of Open Wearables - a self-hosted platform to unify wearable health data through one AI-ready API.

Features #

  • Token Authentication - Sign in with accessToken + refreshToken, SDK handles refresh automatically
  • Background Sync - Health data syncs even when app is in background
  • Incremental Updates - Only syncs new data using anchored queries
  • Secure Storage - Credentials stored in iOS Keychain / Android EncryptedSharedPreferences
  • Wide Data Support - Steps, heart rate, workouts, sleep, and more
  • Custom Host - Point the SDK at any compatible backend
  • Multi-Provider (Android) - Samsung Health and Health Connect supported

Installation #

1. Add Dependency #

dependencies:
  open_wearables_health_sdk: ^0.1.0

2. iOS Configuration #

Add to Info.plist:

<key>NSHealthShareUsageDescription</key>
<string>This app syncs your health data to your account.</string>

<key>UIBackgroundModes</key>
<array>
    <string>fetch</string>
    <string>processing</string>
</array>

<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
    <string>com.openwearables.healthsdk.task.refresh</string>
    <string>com.openwearables.healthsdk.task.process</string>
</array>

Enable HealthKit in Xcode: Target > Signing & Capabilities > + HealthKit.

3. Android Configuration #

Set minSdk to 29

In android/app/build.gradle.kts:

android {
    defaultConfig {
        minSdk = 29
    }
}

Add Health Connect permission aliases to AndroidManifest.xml

In android/app/src/main/AndroidManifest.xml, inside the <application> tag:

<!-- Health Connect: permissions rationale (Android 14+) -->
<activity-alias
    android:name="ViewPermissionUsageActivity"
    android:exported="true"
    android:targetActivity=".MainActivity"
    android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
    <intent-filter>
        <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
        <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
    </intent-filter>
</activity-alias>

<!-- Health Connect: permissions rationale (Android 12-13) -->
<activity-alias
    android:name="ShowPermissionRationaleActivity"
    android:exported="true"
    android:targetActivity=".MainActivity">
    <intent-filter>
        <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
    </intent-filter>
</activity-alias>

Use FlutterFragmentActivity

In your MainActivity.kt, extend FlutterFragmentActivity instead of FlutterActivity:

import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity : FlutterFragmentActivity()

This is required for Health Connect permission dialogs to work.

Samsung Health

Samsung Health is supported out of the box - the Samsung Health Data SDK is bundled in the Android SDK repository. No extra download needed.

For testing on Samsung devices, enable Developer Mode in Samsung Health: Settings > About Samsung Health > tap version 10 times.


SDK Usage #

1. Configure (once at app start) #

await OpenWearablesHealthSdk.configure(
  host: 'https://api.example.com',
);

// Session is automatically restored if user was previously signed in
if (OpenWearablesHealthSdk.isSignedIn) {
  print('Welcome back, ${OpenWearablesHealthSdk.currentUser?.userId}!');
}

2. Sign In #

// Sign in with tokens (supports automatic token refresh)
try {
  final user = await OpenWearablesHealthSdk.signIn(
    userId: 'user-id',
    accessToken: 'Bearer access-token',
    refreshToken: 'refresh-token',
  );
  print('Connected: ${user.userId}');
} on SignInException catch (e) {
  print('Failed: ${e.message}');
}

// Or with API key (simpler, no automatic token refresh):
final user = await OpenWearablesHealthSdk.signIn(
  userId: 'your-user-id',
  apiKey: 'your-api-key',
);

3. Select Provider (Android only) #

On Android, multiple health data providers may be available. Let the user choose:

import 'dart:io';

if (Platform.isAndroid) {
  final providers = await OpenWearablesHealthSdk.getAvailableProviders();
  // Show UI to let user pick a provider
  // providers = [AvailableProvider(samsung, Samsung Health), AvailableProvider(google, Health Connect)]

  await OpenWearablesHealthSdk.setProvider(AndroidHealthProvider.healthConnect);
  // or: await OpenWearablesHealthSdk.setProvider(AndroidHealthProvider.samsungHealth);
}

4. Request Permissions #

final authorized = await OpenWearablesHealthSdk.requestAuthorization(
  types: [
    HealthDataType.steps,
    HealthDataType.heartRate,
    HealthDataType.sleep,
    HealthDataType.workout,
  ],
);

5. Start Background Sync #

await OpenWearablesHealthSdk.startBackgroundSync();

6. Listen to Logs and Auth Errors (optional) #

OpenWearablesHealthSdk.logStream.listen((message) {
  print('[SDK] $message');
});

OpenWearablesHealthSdk.authErrorStream.listen((error) {
  print('Auth error: ${error['statusCode']} - ${error['message']}');
  // Handle token expiration - redirect to login, etc.
});

7. Sign Out #

await OpenWearablesHealthSdk.signOut();

URL Structure #

When you provide a host (e.g. https://api.example.com), the SDK constructs endpoints automatically:

Endpoint URL
Health data sync {host}/api/v1/sdk/users/{userId}/sync
Token refresh {host}/api/v1/token/refresh

You can also provide a customSyncUrl during configure() to override the sync endpoint.


Complete Example #

class HealthService {
  final String host;

  HealthService({required this.host});

  Future<void> connect({
    required String userId,
    required String accessToken,
    required String refreshToken,
  }) async {
    // 1. Configure SDK
    await OpenWearablesHealthSdk.configure(host: host);

    // 2. Check existing session
    if (OpenWearablesHealthSdk.isSignedIn) {
      if (!OpenWearablesHealthSdk.isSyncActive) {
        await _startSync();
      }
      return;
    }

    // 3. Sign in
    await OpenWearablesHealthSdk.signIn(
      userId: userId,
      accessToken: accessToken,
      refreshToken: refreshToken,
    );

    // 4. Select provider on Android
    if (Platform.isAndroid) {
      await OpenWearablesHealthSdk.setProvider(
        AndroidHealthProvider.healthConnect,
      );
    }

    // 5. Start syncing
    await _startSync();
  }

  Future<void> _startSync() async {
    await OpenWearablesHealthSdk.requestAuthorization(
      types: HealthDataType.values,
    );
    await OpenWearablesHealthSdk.startBackgroundSync();
  }

  Future<void> disconnect() async {
    await OpenWearablesHealthSdk.stopBackgroundSync();
    await OpenWearablesHealthSdk.signOut();
  }
}

Supported Health Data Types #

Supported on all platforms #

Category Types
Activity steps, distanceWalkingRunning, flightsClimbed
Energy activeEnergy, basalEnergy
Heart heartRate, restingHeartRate, heartRateVariabilitySDNN, vo2Max, oxygenSaturation
Respiratory respiratoryRate
Body bodyMass, height, bodyFatPercentage, leanBodyMass, bodyTemperature
Blood bloodGlucose, bloodPressure, bloodPressureSystolic, bloodPressureDiastolic
Nutrition dietaryWater
Sleep sleep
Workouts workout

iOS only #

Category Types
Activity distanceCycling, walkingSpeed, walkingStepLength, walkingAsymmetryPercentage, walkingDoubleSupportPercentage, sixMinuteWalkTestDistance
Body bmi, waistCircumference (iOS 16+)
Glucose insulinDelivery (iOS 16+)
Nutrition dietaryEnergyConsumed, dietaryCarbohydrates, dietaryProtein, dietaryFatTotal
Sleep mindfulSession
Reproductive menstrualFlow, cervicalMucusQuality, ovulationTestResult, sexualActivity

Android only #

Category Types
Activity distanceCycling (Health Connect)

Types not supported on the current platform are silently ignored during sync.


API Reference #

OpenWearablesHealthSdk #

Method Description
configure({required host, customSyncUrl?}) Initialize SDK with host URL and restore session
signIn({userId, accessToken?, refreshToken?, apiKey?}) Sign in with tokens or API key
signOut() Sign out and clear all credentials
updateTokens({accessToken, refreshToken?}) Update tokens without re-signing in
requestAuthorization({types}) Request health data permissions
startBackgroundSync() Enable background sync
stopBackgroundSync() Disable background sync
syncNow() Trigger immediate sync
resetAnchors() Reset sync state (forces full re-export)
getStoredCredentials() Get stored credentials for debugging
getSyncStatus() Get current sync session status
resumeSync() Manually resume interrupted sync
clearSyncSession() Clear interrupted sync without resuming
setProvider(AndroidHealthProvider) Set health data provider (Android only)
getAvailableProviders() Get available providers on device (Android only)

Properties #

Property Type Description
isConfigured bool SDK is configured
isSignedIn bool User is signed in
isSyncActive bool Background sync is active
currentUser OpenWearablesHealthSdkUser? Current user info
config OpenWearablesHealthSdkConfig? Current configuration
status OpenWearablesHealthSdkStatus Current SDK status
logStream Stream<String> SDK log messages
authErrorStream Stream<Map> Auth error events

Exceptions #

Exception When Thrown
NotConfiguredException configure() was not called
NotSignedInException No user signed in
SignInException Sign-in failed

Architecture #

┌──────────────────────────────────────────────────┐
│ Flutter App (Dart)                                │
│  OpenWearablesHealthSdk → MethodChannel           │
└──────────────────┬───────────────────────────────┘
                   │
┌──────────────────▼───────────────────────────────┐
│ Flutter Plugin (thin wrapper)                     │
│  OpenWearablesHealthSdkPlugin.kt                  │
│    └── delegates to ↓                             │
│                                                   │
│ Open Wearables Android SDK (native library)       │
│  OpenWearablesHealthSDK (facade)                  │
│    ├── SamsungHealthManager → Samsung Health       │
│    ├── HealthConnectManager → Health Connect       │
│    └── SyncManager → WorkManager background sync  │
└───────────────────────────────────────────────────┘

On Android, the Flutter plugin is a thin wrapper around the Open Wearables Android SDK (com.openwearables.health:sdk), which can also be used independently in native Android apps.


License #

MIT License

0
likes
150
points
439
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter SDK for secure background health data synchronization from Apple HealthKit (iOS) and Samsung Health / Health Connect (Android) to the Open Wearables platform.

Homepage
Repository (GitHub)
View/report issues

Topics

#health #healthkit #wearables #android #background-sync

Documentation

API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on open_wearables_health_sdk

Packages that implement open_wearables_health_sdk