https://github.com/shubhamsinghshubham777/khealth
A Kotlin Multiplatform wrapper for Android's Health Connect and Apple's HealthKit 🏥
https://github.com/shubhamsinghshubham777/khealth
android apple health health-connect healthkit ios kmm kmp kotlin-library kotlin-multiplatform watchos
Last synced: about 2 months ago
JSON representation
A Kotlin Multiplatform wrapper for Android's Health Connect and Apple's HealthKit 🏥
- Host: GitHub
- URL: https://github.com/shubhamsinghshubham777/khealth
- Owner: shubhamsinghshubham777
- License: apache-2.0
- Created: 2024-11-09T09:53:41.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-03-14T03:26:42.000Z (about 2 months ago)
- Last Synced: 2025-03-17T16:09:59.445Z (about 2 months ago)
- Topics: android, apple, health, health-connect, healthkit, ios, kmm, kmp, kotlin-library, kotlin-multiplatform, watchos
- Language: Kotlin
- Homepage: https://shubhamsinghshubham777.github.io/KHealth/
- Size: 1.32 MB
- Stars: 66
- Watchers: 1
- Forks: 1
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
🏥 KHealth 🏥
![]()
**KHealth** (_short for Kotlin Health_) is a simple Kotlin Multiplatform wrapper over
Android's [Health Connect](https://developer.android.com/health-and-fitness/guides/health-connect)
and Apple's [HealthKit](https://developer.apple.com/documentation/healthkit) APIs. It provides a
simple and effective way to consume these native APIs in a Kotlin/Compose Multiplatform environment.## Demo
> [!NOTE]
> You can find the following app in the `sample*` directories (e.g. `sampleAndroidApp` and
`sampleAppleApps`)## 🚀 Getting Started

Add the following to your shared module's `build.gradle.kts`:
```kotlin
implementation("io.github.shubhamsinghshubham777:khealth:1.1.0")
```or add it to your version catalog:
```toml
[versions]
khealth = "1.1.0"[libraries]
khealth = { module = "io.github.shubhamsinghshubham777:khealth", version.ref = "khealth" }[plugins]
```and use it in your `build.gradle.kts`:
```kotlin
kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.khealth)
}
}
}
```## ⚙️ Usage
1. (Apple Only) Add the following code in your `Info.plist` file:
```
...
...
...
NSHealthUpdateUsageDescription
We will sync your data with the Apple Health app to give you better insights
NSHealthShareUsageDescription
We will sync your data with the Apple Health app to give you better insights
```2. (Android only) Add the following code in your `AndroidManifest.xml`:
```xml
```3. (Android only) Add the dependencies you require to use in `AndroidManifest.xml`
| Type | Permissions |
|-------------------------|------------------------------------------------------------------------------------------------------------------------|
| ACTIVE_CALORIES_BURNED | `android.permission.health.READ_ACTIVE_CALORIES_BURNED`
`android.permission.health.WRITE_ACTIVE_CALORIES_BURNED` |
| BASAL_METABOLIC_RATE | `android.permission.health.READ_BASAL_METABOLIC_RATE`
`android.permission.health.WRITE_BASAL_METABOLIC_RATE` |
| BLOOD_GLUCOSE | `android.permission.health.READ_BLOOD_GLUCOSE`
`android.permission.health.WRITE_BLOOD_GLUCOSE` |
| BLOOD_PRESSURE | `android.permission.health.READ_BLOOD_PRESSURE`
`android.permission.health.WRITE_BLOOD_PRESSURE` |
| BODY_FAT | `android.permission.health.READ_BODY_FAT`
`android.permission.health.WRITE_BODY_FAT` |
| BODY_TEMPERATURE | `android.permission.health.READ_BODY_TEMPERATURE`
`android.permission.health.WRITE_BODY_TEMPERATURE` |
| BODY_WATER_MASS | `android.permission.health.READ_BODY_WATER_MASS`
`android.permission.health.WRITE_BODY_WATER_MASS` |
| BONE_MASS | `android.permission.health.READ_BONE_MASS`
`android.permission.health.WRITE_BONE_MASS` |
| CERVICAL_MUCUS | `android.permission.health.READ_CERVICAL_MUCUS`
`android.permission.health.WRITE_CERVICAL_MUCUS` |
| DISTANCE | `android.permission.health.READ_DISTANCE`
`android.permission.health.WRITE_DISTANCE` |
| ELEVATION_GAINED | `android.permission.health.READ_ELEVATION_GAINED`
`android.permission.health.WRITE_ELEVATION_GAINED` |
| EXERCISE | `android.permission.health.READ_EXERCISE`
`android.permission.health.WRITE_EXERCISE` |
| FLOORS_CLIMBED | `android.permission.health.READ_FLOORS_CLIMBED`
`android.permission.health.WRITE_FLOORS_CLIMBED` |
| HEART_RATE | `android.permission.health.READ_HEART_RATE`
`android.permission.health.WRITE_HEART_RATE` |
| HEART_RATE_VARIABILITY | `android.permission.health.READ_HEART_RATE_VARIABILITY`
`android.permission.health.WRITE_HEART_RATE_VARIABILITY` |
| HEIGHT | `android.permission.health.READ_HEIGHT`
`android.permission.health.WRITE_HEIGHT` |
| HYDRATION | `android.permission.health.READ_HYDRATION`
`android.permission.health.WRITE_HYDRATION` |
| INTERMENSTRUAL_BLEEDING | `android.permission.health.READ_INTERMENSTRUAL_BLEEDING`
`android.permission.health.WRITE_INTERMENSTRUAL_BLEEDING` |
| LEAN_BODY_MASS | `android.permission.health.READ_LEAN_BODY_MASS`
`android.permission.health.WRITE_LEAN_BODY_MASS` |
| MENSTRUATION | `android.permission.health.READ_MENSTRUATION`
`android.permission.health.WRITE_MENSTRUATION` |
| MENSTRUATION | `android.permission.health.READ_MENSTRUATION`
`android.permission.health.WRITE_MENSTRUATION` |
| NUTRITION | `android.permission.health.READ_NUTRITION`
`android.permission.health.WRITE_NUTRITION` |
| OVULATION_TEST | `android.permission.health.READ_OVULATION_TEST`
`android.permission.health.WRITE_OVULATION_TEST` |
| OXYGEN_SATURATION | `android.permission.health.READ_OXYGEN_SATURATION`
`android.permission.health.WRITE_OXYGEN_SATURATION` |
| POWER | `android.permission.health.READ_POWER`
`android.permission.health.WRITE_POWER` |
| RESPIRATORY_RATE | `android.permission.health.READ_RESPIRATORY_RATE`
`android.permission.health.WRITE_RESPIRATORY_RATE` |
| RESTING_HEART_RATE | `android.permission.health.READ_RESTING_HEART_RATE`
`android.permission.health.WRITE_RESTING_HEART_RATE` |
| SEXUAL_ACTIVITY | `android.permission.health.READ_SEXUAL_ACTIVITY`
`android.permission.health.WRITE_SEXUAL_ACTIVITY` |
| SLEEP | `android.permission.health.READ_SLEEP`
`android.permission.health.WRITE_SLEEP` |
| SPEED | `android.permission.health.READ_SPEED`
`android.permission.health.WRITE_SPEED` |
| STEPS | `android.permission.health.READ_STEPS`
`android.permission.health.WRITE_STEPS` |
| VO2_MAX | `android.permission.health.READ_VO2_MAX`
`android.permission.health.WRITE_VO2_MAX` |
| WEIGHT | `android.permission.health.READ_WEIGHT`
`android.permission.health.WRITE_WEIGHT` |
| WHEELCHAIR_PUSHES | `android.permission.health.READ_WHEELCHAIR_PUSHES`
`android.permission.health.WRITE_WHEELCHAIR_PUSHES` |4. Instantiate
```kotlin
// On Apple (iOS, watchOS)
val kHealth = KHealth()
// On Android (inside a ComponentActivity)
class MainActivity : ComponentActivity() {
private val kHealth = KHealth(this)
// Rest of your code
}
```5. Initialise (only required on Android)
```kotlin
// Inside a `ComponentActivity`
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Initialise (only on Android, on Apple, this function is no-op)
kHealth.initialise()
}
```6. Check Permission Status
```kotlin
val permissionResponse: Set = kHealth.checkPermissions(
KHPermission.ActiveCaloriesBurned(read = true, write = true),
KHPermission.HeartRate(read = true, write = false),
// Add as many requests as you want
)
```7. Request Permissions
```kotlin
// Same syntax as `checkPermissions`
val permissionResponse: Set = kHealth.requestPermissions(
KHPermission.ActiveCaloriesBurned(read = true, write = true),
KHPermission.HeartRate(read = true, write = false),
// Add as many requests as you want
)
```8. Check if permission was granted
```kotlin
val caloriesPermResponse = permissionResponse.first { response ->
response is KHPermission.ActiveCaloriesBurned
}.writeStatusval wasWritePermissionGranted = caloriesPermResponse.write == true
```9. Write records
```kotlin
if (wasWritePermissionGranted) {
val insertResponse: KHWriteResponse = kHealth.writeRecords(
KHRecord.ActiveCaloriesBurned(
unit = KHUnit.Energy.KiloCalorie,
value = 3.4,
startTime = Clock.System.now().minus(10.minutes),
endTime = Clock.System.now(),
),
KHRecord.HeartRate(
samples = listOf(
KHHeartRateSample(
beatsPerMinute = 126,
time = Clock.System.now().minus(10.minutes)
)
),
),
// Add as many records as you want
)when (insertResponse) {
is KHWriteResponse.Failed -> {
println("Records insertion failed ❌ Reason: ${insertResponse.throwable}")
}KHWriteResponse.SomeFailed -> println("Some records were not inserted ⚠️")
KHWriteResponse.Success -> println("Records inserted ✅")
}
}
```10. Read records
```kotlin
val heartRateRecords = kHealth.readRecords(
KHReadRequest.HeartRate(
startTime = Clock.System.now().minus(1.days),
endTime = Clock.System.now()
)
)
println("Heart Rate records: $heartRateRecords")
```## Supported Data Types (based on platforms)
KHealth supports reading and writing the following data types on the following platforms:
| Type | Android | Apple (iOS & watchOS) |
|------------------------|---------|-----------------------|
| ActiveCaloriesBurned | ✅ | ✅ |
| BasalMetabolicRate | ✅ | ✅ |
| BloodGlucose | ✅ | ✅ |
| BloodPressure | ✅ | ✅ |
| BodyFat | ✅ | ✅ |
| BodyTemperature | ✅ | ✅ |
| BodyWaterMass | ✅ | |
| BoneMass | ✅ | |
| CervicalMucus | ✅ | ✅ |
| CyclingPedalingCadence | ✅ | |
| Distance | ✅ | ✅ |
| ElevationGained | ✅ | |
| Exercise | ✅ | ✅ |
| FloorsClimbed | ✅ | ✅ |
| HeartRate | ✅ | ✅ |
| HeartRateVariability | ✅ | ✅ |
| Height | ✅ | ✅ |
| Hydration | ✅ | ✅ |
| IntermenstrualBleeding | ✅ | ✅ |
| LeanBodyMass | ✅ | ✅ |
| MenstruationPeriod | ✅ | |
| MenstruationFlow | ✅ | ✅ |
| Nutrition | ✅ | ✅ |
| OvulationTest | ✅ | ✅ |
| OxygenSaturation | ✅ | ✅ |
| Power | ✅ | ✅ |
| RespiratoryRate | ✅ | ✅ |
| RestingHeartRate | ✅ | ✅ |
| SexualActivity | ✅ | ✅ |
| SleepSession | ✅ | ✅ |
| Speed | ✅ | |
| RunningSpeed | | ✅ |
| CyclingSpeed | | ✅ |
| StepCount | ✅ | ✅ |
| Vo2Max | ✅ | ✅ |
| Weight | ✅ | ✅ |
| WheelChairPushes | ✅ | ✅ |## Supported Exercise Types (based on platforms)
KHealth supports reading and writing the following exercise/workout types on the following
platforms:| Type | Android | Apple (iOS & watchOS) |
|-------------------------------|---------|------------------------|
| AmericanFootball | ✅ | ✅ |
| Archery | | ✅ |
| AustralianFootball | ✅ | ✅ |
| Badminton | ✅ | ✅ |
| Barre | | ✅ |
| Baseball | ✅ | ✅ |
| Basketball | ✅ | ✅ |
| Biking | ✅ | ✅ |
| BikingStationary | ✅ | ✅ |
| BootCamp | ✅ | ✅ |
| Bowling | | ✅ |
| Boxing | ✅ | ✅ |
| Calisthenics | ✅ | ✅ |
| CardioDance | | ✅ |
| Climbing | | ✅ |
| Cooldown | | ✅ |
| CoreTraining | | ✅ |
| Cricket | ✅ | ✅ |
| CrossCountrySkiing | | ✅ |
| CrossTraining | | ✅ |
| Curling | | ✅ |
| Cycling | | ✅ |
| Dance | | ✅ |
| DanceInspiredTraining | | ✅ |
| Dancing | ✅ | ✅ |
| DiscSports | | ✅ |
| DownhillSkiing | | ✅ |
| Elliptical | ✅ | ✅ |
| EquestrianSports | | ✅ |
| ExerciseClass | ✅ | ✅ |
| Fencing | ✅ | ✅ |
| Fishing | | ✅ |
| FitnessGaming | | ✅ |
| Flexibility | | ✅ |
| FrisbeeDisc | | ✅ |
| FunctionalStrengthTraining | | ✅ |
| Golf | ✅ | ✅ |
| GuidedBreathing | ✅ | ✅ |
| Gymnastics | ✅ | ✅ |
| HandCycling | | ✅ |
| Handball | ✅ | ✅ |
| HighIntensityIntervalTraining | ✅ | ✅ |
| Hiking | ✅ | ✅ |
| Hockey | | ✅ |
| Hunting | | ✅ |
| IceHockey | ✅ | ✅ |
| IceSkating | ✅ | ✅ |
| JumpRope | | ✅ |
| Kickboxing | | ✅ |
| Lacrosse | | ✅ |
| MartialArts | ✅ | ✅ |
| MindAndBody | | ✅ |
| MixedCardio | | ✅ |
| MixedMetabolicCardioTraining | | ✅ |
| Other | ✅ | ✅ |
| PaddleSports | | ✅ |
| Paddling | ✅ | ✅ |
| Paragliding | ✅ | ✅ |
| Pickleball | | ✅ |
| Pilates | ✅ | ✅ |
| Play | | ✅ |
| PreparationAndRecovery | | ✅ |
| Racquetball | ✅ | ✅ |
| RockClimbing | ✅ | ✅ |
| RollerHockey | ✅ | ✅ |
| Rowing | ✅ | ✅ |
| RowingMachine | ✅ | ✅ |
| Rugby | ✅ | ✅ |
| Running | ✅ | ✅ |
| RunningTreadmill | ✅ | ✅ |
| Sailing | ✅ | ✅ |
| ScubaDiving | ✅ | ✅ |
| Skating | ✅ | ✅ |
| SkatingSports | | ✅ |
| Skiing | ✅ | ✅ |
| SnowSports | | ✅ |
| Snowboarding | ✅ | ✅ |
| Snowshoeing | ✅ | ✅ |
| Soccer | ✅ | ✅ |
| SocialDance | | ✅ |
| Softball | ✅ | ✅ |
| Squash | ✅ | ✅ |
| StairClimbing | ✅ | ✅ |
| StairClimbingMachine | ✅ | ✅ |
| Stairs | | ✅ |
| StepTraining | | ✅ |
| StrengthTraining | ✅ | ✅ |
| Stretching | ✅ | ✅ |
| Surfing | ✅ | ✅ |
| SurfingSports | | ✅ |
| SwimBikeRun | | ✅ |
| Swimming | | ✅ |
| SwimmingOpenWater | ✅ | |
| SwimmingPool | ✅ | |
| TableTennis | ✅ | ✅ |
| TaiChi | | ✅ |
| Tennis | ✅ | ✅ |
| TrackAndField | | ✅ |
| TraditionalStrengthTraining | | ✅ |
| Transition | | ✅ |
| UnderwaterDiving | | ✅ |
| Volleyball | ✅ | ✅ |
| Walking | ✅ | ✅ |
| WaterFitness | | ✅ |
| WaterPolo | ✅ | ✅ |
| WaterSports | | ✅ |
| Weightlifting | ✅ | ✅ |
| Wheelchair | ✅ | ✅ |
| WheelchairRunPace | | ✅ |
| WheelchairWalkPace | | ✅ |
| Wrestling | | ✅ |
| Yoga | ✅ | ✅ |> [!NOTE]
> The unsupported types will simply be ignored by all platforms.## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## 📄 License
This library is licensed under the Apache 2.0 License. See the [LICENSE](LICENSE) file for details.