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

# Synheart Wear - Kotlin/Android SDK

> Native Android SDK with Health Connect integration

## Overview

The Synheart Wear Kotlin SDK provides native Android support for streaming biometric data from wearables via Health Connect, vendor cloud APIs (WHOOP, Garmin, Fitbit, Oura), and direct BLE heart-rate sensors.

## Installation

### Gradle (Kotlin DSL)

Published to **Maven Central** as `ai.synheart:synheart-wear`:

```kotlin theme={null}
dependencies {
    implementation("ai.synheart:synheart-wear:0.4.0")
}
```

### Requirements

* Android SDK API 21+ (target SDK 34+)
* Kotlin 2.3+
* Android Gradle Plugin 9.0+ (Gradle 9.2+)
* Health Connect installed on device (built-in on Android 14+, otherwise via Play Store)

## Quick Start

### Initialize SDK

```kotlin theme={null}
import ai.synheart.wear.SynheartWear
import ai.synheart.wear.config.SynheartWearConfig
import ai.synheart.wear.models.DeviceAdapter

val synheartWear = SynheartWear(
    context = this,
    config = SynheartWearConfig(
        enabledAdapters = setOf(DeviceAdapter.HEALTH_CONNECT)
    )
)
```

### Request Permissions & Initialize

```kotlin theme={null}
lifecycleScope.launch {
    val permissions = setOf(
        PermissionType.HEART_RATE,
        PermissionType.STEPS,
        PermissionType.CALORIES
    )

    val result = synheartWear.requestPermissions(permissions)

    if (result[PermissionType.HEART_RATE] == true) {
        synheartWear.initialize()
        val metrics = synheartWear.readMetrics()
        Log.d(TAG, "HR: ${metrics.getMetric(MetricType.HR)} bpm")
    }
}
```

### Real-Time Streaming

```kotlin theme={null}
lifecycleScope.launch {
    synheartWear.streamHR(intervalMs = 5000L).collect { metrics ->
        val hr = metrics.getMetric(MetricType.HR)
        Log.d(TAG, "Current HR: $hr bpm")
    }
}
```

## Health Connect

Reads from any wearable companion app that syncs to Jetpack Health Connect — Fitbit, Garmin Connect, Samsung Health, Google Fit, Polar Flow, etc. (Apple Watch is **not** supported on Android — it only syncs to Apple Health on iOS.)

### AndroidManifest.xml

The SDK ships its own `AndroidManifest.xml` declaring all 17 Health Connect read permissions plus the `<queries>` block for the Health Connect app, so the consumer app inherits them automatically. If your app needs a privacy-policy intent (required by the Play Store policy for Health Connect apps), add this in your own manifest:

```xml theme={null}
<activity-alias
    android:name="ViewPermissionUsageActivity"
    android:exported="true"
    android:targetActivity=".MainActivity"
    android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
    <intent-filter>
        <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
    </intent-filter>
</activity-alias>
```

### Supported record types

`HealthConnectAdapter` reads: `HeartRateRecord`, `HeartRateVariabilityRmssdRecord`, `RestingHeartRateRecord`, `StepsRecord`, `TotalCaloriesBurnedRecord`, `ActiveCaloriesBurnedRecord`, `DistanceRecord`, `ExerciseSessionRecord`, `SleepSessionRecord`, `OxygenSaturationRecord`, `RespiratoryRateRecord`, `BodyTemperatureRecord`, `WeightRecord`, `HeightRecord`, `BodyFatRecord`.

### Caveats

* On devices below Android 14 without the Play Store Health Connect app, the adapter returns an empty snapshot rather than throwing. Check `HealthConnectAdapter.getAvailabilityStatus()` to detect this case.
* Per-record retention is platform-controlled (typically \~30 days for HR, longer for sleep). For older data use a cloud OAuth provider.

## Cloud providers (WHOOP / Garmin / Fitbit / Oura)

Each cloud vendor is exposed via a typed accessor on `SynheartWear` plus the generic `getProvider()` lookup:

```kotlin theme={null}
val whoop:  WhoopProvider?  = synheartWear.whoop
val garmin: GarminProvider? = synheartWear.garmin
val fitbit: FitbitProvider? = synheartWear.fitbit
val oura:   OuraProvider?   = synheartWear.oura
```

OAuth is mediated by the Synheart Wear API; the device never sees vendor access tokens. Call `provider.connect()` to get an authorization URL, open it in a browser, then call `provider.connectWithCode(code, state, redirectUri)` from your deep-link handler. Full code sample in the SDK [README's Cloud Wearables section](https://github.com/synheart-ai/synheart-wear-kotlin#%EF%B8%8F-cloud-wearables-integration).

## BLE Heart Rate Monitor

Connect directly to any standard Bluetooth LE heart rate monitor for real-time HR streaming.

### Setup

Add to `AndroidManifest.xml`:

```xml theme={null}
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
```

### Usage

```kotlin theme={null}
import ai.synheart.wear.SynheartWear
import ai.synheart.wear.config.SynheartWearConfig
import ai.synheart.wear.models.DeviceAdapter

val synheartWear = SynheartWear(
    context = this,
    config = SynheartWearConfig(
        enabledAdapters = setOf(DeviceAdapter.BLE_HRM)
    )
)

val bleHrm = synheartWear.bleHrm ?: return

// Scan for nearby HR monitors
val devices = bleHrm.scan(timeoutMs = 10000, namePrefix = "WHOOP")

// Connect to a device
bleHrm.connect(deviceId = devices.first().deviceId, sessionId = "my-session")

// Collect heart rate samples
bleHrm.heartRateFlow.collect { sample ->
    Log.d(TAG, "BPM: ${sample.bpm}")
    sample.rrIntervalsMs?.let { rr ->
        Log.d(TAG, "RR: $rr")
    }
}

// Disconnect
bleHrm.disconnect()
```

### Supported Devices

Works with any BLE device implementing the standard Heart Rate Profile (0x180D):

* WHOOP (Broadcast HR mode)
* Polar H10, OH1
* Wahoo TICKR
* Garmin HRM-Pro / HRM-Dual

## Garmin Health SDK (Native RTS)

The `GarminHealth` facade provides native Garmin device integration for scanning, pairing, and real-time streaming using generic SDK-owned types.

> **Important:** The Garmin Health SDK Real-Time Streaming (RTS) capability requires a separate license from Garmin. This facade is available on demand for licensed integrations. The underlying Garmin Health SDK code is proprietary to Garmin and is not distributed as open source.

```kotlin theme={null}
import ai.synheart.wear.adapters.GarminHealth

val garmin = GarminHealth(licenseKey = "your-garmin-sdk-key")
garmin.initialize()

// Scan for devices
garmin.scannedDevicesFlow.collect { devices ->
    println("Found ${devices.size} devices")
}

// Pair and read metrics
val paired = garmin.pairDevice(scannedDevice)
val metrics = garmin.readMetrics()
```

For cloud-based Garmin data (OAuth + webhooks), use `GarminProvider` instead.

## Resources

* **Repository**: [synheart-wear-kotlin](https://github.com/synheart-ai/synheart-wear-kotlin)
* **Full README**: [View on GitHub](https://github.com/synheart-ai/synheart-wear-kotlin#readme)
* **Issues**: [GitHub Issues](https://github.com/synheart-ai/synheart-wear-kotlin/issues)

For comprehensive documentation, see the [full README on GitHub](https://github.com/synheart-ai/synheart-wear-kotlin#readme).
