> ## Documentation Index
> Fetch the complete documentation index at: https://openwearables.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Flutter Health SDK Troubleshooting

> Fix common Flutter SDK issues on iOS and Android: HealthKit permissions not showing, Health Connect unavailable, and background sync not triggering.

## Common Issues

<AccordionGroup>
  <Accordion title="HealthKit permissions not showing (iOS)">
    **Symptoms:** The health permissions dialog doesn't appear when calling `requestAuthorization()`.

    **Solutions:**

    1. **Verify Info.plist configuration:**
       ```xml theme={null}
       <key>NSHealthShareUsageDescription</key>
       <string>This app syncs your health data to your account.</string>
       ```

    2. **Check HealthKit capability in Xcode:**
       * Open `ios/Runner.xcworkspace`
       * Select target → Signing & Capabilities
       * Ensure HealthKit is listed

    3. **Run on physical device:**
       HealthKit doesn't work in the iOS Simulator. Always test on a real device.

    4. **Check provisioning profile:**
       Your Apple Developer account must have HealthKit capability enabled for the App ID.
  </Accordion>

  <Accordion title="Health Connect permissions not showing (Android)">
    **Symptoms:** Permission dialog doesn't appear on Android.

    **Solutions:**

    1. **Ensure Health Connect is installed:**
       Health Connect must be installed on the device. It's pre-installed on Android 14+ but may need to be installed from Play Store on older versions.

    2. **Set provider before requesting authorization:**
       ```dart theme={null}
       await OpenWearablesHealthSdk.setProvider(AndroidHealthProvider.healthConnect);
       final authorized = await OpenWearablesHealthSdk.requestAuthorization(
         types: [
           HealthDataType.steps,
           HealthDataType.heartRate,
           HealthDataType.sleep,
         ],
       );
       // authorized == true  → permissions dialog was shown and accepted
       // authorized == false → user denied or dialog failed to appear
       print('Permissions granted: $authorized');
       ```

    3. **Check minSdk version:**
       Your `android/app/build.gradle` must have `minSdk 29` or higher.

    4. **Verify the Activity is set (if using native Android directly):**
       The Flutter plugin handles this automatically, but if you see permission launcher issues, try rebuilding the app.
  </Accordion>

  <Accordion title="Background sync not working (iOS)">
    **Symptoms:** Data only syncs when the app is in the foreground.

    **Solutions:**

    1. **Verify background modes in Info.plist:**
       ```xml theme={null}
       <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>
       ```

    2. **Check Background App Refresh setting:**
       * Go to iOS Settings → Your App → Background App Refresh
       * Ensure it's enabled

    3. **Check Low Power Mode:**
       Background tasks are suspended when Low Power Mode is active.

    4. **Wait for system scheduling:**
       iOS controls when background tasks run. Initial syncs may take 15+ minutes to trigger.
  </Accordion>

  <Accordion title="Background sync not working (Android)">
    **Symptoms:** Data only syncs when the app is in the foreground on Android.

    **Solutions:**

    1. **Check battery optimization:**
       Some Android manufacturers aggressively kill background services. Ask users to disable battery optimization for your app in Settings.

    2. **Verify notification permissions:**
       On Android 13+, the SDK uses a foreground service notification during sync. Ensure `POST_NOTIFICATIONS` permission is granted.

    3. **Check provider connection:**
       Verify the health provider is properly connected:
       ```dart theme={null}
       final providers = await OpenWearablesHealthSdk.getAvailableProviders();
       print(providers);
       ```
  </Accordion>

  <Accordion title="Sign-in fails with error">
    **Symptoms:** `SignInException` when calling `signIn()`.

    **Solutions:**

    1. **Check token expiration:**
       Access tokens expire. Ensure your backend generates fresh tokens.

    2. **Verify credentials:**
       Ensure you're providing either (`accessToken` + `refreshToken`) or `apiKey`:
       ```dart theme={null}
       // Token-based (recommended)
       await OpenWearablesHealthSdk.signIn(
         userId: userId,
         accessToken: accessToken,
         refreshToken: refreshToken,
       );

       // OR API key-based
       await OpenWearablesHealthSdk.signIn(
         userId: userId,
         apiKey: apiKey,
       );
       ```

    3. **Check network connectivity:**
       Ensure the device can reach your Open Wearables host.

    4. **Check SignInException details:**
       ```dart theme={null}
       try {
         final user = await OpenWearablesHealthSdk.signIn(
           userId: 'usr_abc123',
           accessToken: accessToken,
           refreshToken: refreshToken,
         );
         print('Signed in as ${user.userId}');
       } on SignInException catch (e) {
         // Example output: "Message: Unauthorized" / "Status code: 401"
         print('Message: ${e.message}');
         print('Status code: ${e.statusCode}');
       }
       ```
  </Accordion>

  <Accordion title="Data not appearing in Open Wearables">
    **Symptoms:** Sync completes but data doesn't show up in the API.

    **Solutions:**

    1. **Check sync status:**
       ```dart theme={null}
       final status = await OpenWearablesHealthSdk.getSyncStatus();
       print('Sent count: ${status['sentCount']}');
       ```

    2. **Verify health data exists:**
       Open Apple Health or Health Connect and confirm data exists for the requested types.

    3. **Check date range:**
       The SDK syncs data incrementally. New data may not exist yet.

    4. **Reset anchors for full sync:**
       ```dart theme={null}
       await OpenWearablesHealthSdk.resetAnchors();
       await OpenWearablesHealthSdk.syncNow();
       ```

    5. **Check permissions:**
       Users may have denied specific data types even if they approved the overall request.
  </Accordion>

  <Accordion title="NotConfiguredException thrown">
    **Symptoms:** Exception when calling SDK methods.

    **Solution:**
    Ensure `configure()` is called before any other SDK methods:

    ```dart theme={null}
    // ✅ Correct order
    await OpenWearablesHealthSdk.configure(host: 'https://api.openwearables.io');
    await OpenWearablesHealthSdk.signIn(
      userId: 'usr_abc123',
      accessToken: accessToken,
      refreshToken: refreshToken,
    );
    await OpenWearablesHealthSdk.startBackgroundSync();

    // ❌ Wrong - signIn before configure
    await OpenWearablesHealthSdk.signIn(
      userId: 'usr_abc123',
      accessToken: accessToken,
      refreshToken: refreshToken,
    ); // Throws NotConfiguredException
    ```
  </Accordion>

  <Accordion title="NotSignedInException thrown">
    **Symptoms:** Exception when starting sync without signing in.

    **Solution:**
    Check sign-in status before sync operations:

    ```dart theme={null}
    if (!OpenWearablesHealthSdk.isSignedIn) {
      await OpenWearablesHealthSdk.signIn(
        userId: 'usr_abc123',
        accessToken: accessToken,
        refreshToken: refreshToken,
      );
    }
    await OpenWearablesHealthSdk.startBackgroundSync();
    ```
  </Accordion>

  <Accordion title="Samsung Health not available">
    **Symptoms:** Samsung Health provider not found on `getAvailableProviders()`.

    **Solutions:**

    1. **Samsung Health must be installed** on the device.
    2. **Samsung devices only** - Samsung Health is typically only available on Samsung devices.
    3. **Try Health Connect instead** as it works on all Android 10+ devices:
       ```dart theme={null}
       await OpenWearablesHealthSdk.setProvider(AndroidHealthProvider.healthConnect);
       ```
  </Accordion>
</AccordionGroup>

## HealthKit Entitlement Issues (iOS)

If you see "Missing HealthKit entitlement" errors:

1. **In Xcode:**
   * Target → Signing & Capabilities → Add HealthKit
   * Check "Background Delivery" for background updates

2. **In Apple Developer Portal:**
   * App IDs → Your App → Capabilities
   * Enable HealthKit

3. **Regenerate provisioning profiles** after making changes

### Background Delivery Limitations (iOS)

iOS has strict limits on background execution:

| Factor         | Impact                                                    |
| -------------- | --------------------------------------------------------- |
| Battery Level  | Background tasks paused below 20%                         |
| Low Power Mode | All background tasks suspended                            |
| User Behavior  | iOS learns when you use the app and schedules accordingly |
| Network        | Background tasks require network connectivity             |

<Tip>
  For critical sync operations, prompt users to open the app and trigger `syncNow()` manually.
</Tip>

## Testing Background Sync

### iOS

To test background sync during development:

1. Run app on device
2. Navigate to home screen
3. Wait 15+ minutes (or use Xcode's debug menu)
4. Check logs for sync activity

In Xcode, you can simulate background fetch:

* Debug → Simulate Background Fetch

### Android

1. Run app on device or emulator
2. Minimize the app
3. The SDK uses WorkManager which should trigger relatively quickly
4. Check logs via `MethodChannelOpenWearablesHealthSdk.logStream`

## Debugging Tips

### Enable Debug Logging

```dart theme={null}
import 'package:open_wearables_health_sdk/open_wearables_health_sdk_method_channel.dart';

// Listen to SDK logs
MethodChannelOpenWearablesHealthSdk.logStream.listen((message) {
  print('[HealthSDK] $message');
});

// Listen to auth errors
MethodChannelOpenWearablesHealthSdk.authErrorStream.listen((error) {
  print('[HealthSDK] Auth error: ${error['statusCode']} - ${error['message']}');
});

// Log current state
print('Status: ${OpenWearablesHealthSdk.status}');
print('Is signed in: ${OpenWearablesHealthSdk.isSignedIn}');
print('Is sync active: ${OpenWearablesHealthSdk.isSyncActive}');
print('User: ${OpenWearablesHealthSdk.currentUser?.userId}');
```

### Check Stored Credentials

```dart theme={null}
final creds = await OpenWearablesHealthSdk.getStoredCredentials();
print('Stored credentials: $creds');
```

### Monitor Sync Progress

```dart theme={null}
final status = await OpenWearablesHealthSdk.getSyncStatus();
print('Has resumable session: ${status['hasResumableSession']}');
print('Sent count: ${status['sentCount']}');
print('Is full export: ${status['isFullExport']}');
print('Created at: ${status['createdAt']}');
```

### Force Fresh Start

If things are in a bad state:

```dart theme={null}
// Clear everything and start fresh
await OpenWearablesHealthSdk.stopBackgroundSync();
await OpenWearablesHealthSdk.signOut();
await OpenWearablesHealthSdk.clearSyncSession();
await OpenWearablesHealthSdk.resetAnchors();

// Re-initialize
await OpenWearablesHealthSdk.configure(host: 'https://api.openwearables.io');
```

## Getting Help

If you're still experiencing issues:

<CardGroup cols={2}>
  <Card title="GitHub Issues" icon="github" href="https://github.com/the-momentum/open_wearables_health_sdk/issues">
    Report bugs or request features on the SDK repository.
  </Card>

  <Card title="Discussions" icon="comments" href="https://github.com/the-momentum/open-wearables/discussions">
    Ask questions and get help from the community.
  </Card>
</CardGroup>

When reporting issues, please include:

* Flutter version (`flutter --version`)
* SDK version (from `pubspec.lock`)
* Platform (iOS/Android) and OS version
* Device model
* Relevant logs and error messages
* Steps to reproduce
