KHealth (short for Kotlin Health) is a simple Kotlin Multiplatform wrapper over Android's Health Connect and Apple's HealthKit APIs. It provides a simple and effective way to consume these native APIs in a Kotlin/Compose Multiplatform environment.
Note
You can find the following app in the sample* directories (e.g. sampleAndroidApp and
sampleAppleApps)
android.mp4
iOS.mp4
watchOS.mp4
Add the following to your shared module's build.gradle.kts:
implementation("io.github.shubhamsinghshubham777:khealth:1.1.0")or add it to your version catalog:
[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 {
sourceSets {
commonMain.dependencies {
implementation(libs.khealth)
}
}
}-
(Apple Only) Add the following code in your
Info.plistfile:<plist> <dict> ... ... ... <key>NSHealthUpdateUsageDescription</key> <string>We will sync your data with the Apple Health app to give you better insights</string> <key>NSHealthShareUsageDescription</key> <string>We will sync your data with the Apple Health app to give you better insights</string> </dict> </plist> -
(Android only) Add the following code in your
AndroidManifest.xml:<uses-permission android:name="..." /> <!-- Check if Health Connect is installed --> <queries> <package android:name="com.google.android.apps.healthdata" /> </queries> <application ...> <!-- For supported versions through Android 13, create an activity to show the rationale of Health Connect permissions once users click the privacy policy link. --> <activity android:name=".PermissionsRationaleActivity" android:exported="true"> <intent-filter> <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" /> </intent-filter> </activity> <!-- For versions starting Android 14, create an activity alias to show the rationale of Health Connect permissions once users click the privacy policy link. --> <activity-alias android:name="ViewPermissionUsageActivity" android:exported="true" android:permission="android.permission.START_VIEW_PERMISSION_USAGE" android:targetActivity=".PermissionsRationaleActivity"> <intent-filter> <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" /> <category android:name="android.intent.category.HEALTH_PERMISSIONS" /> </intent-filter> </activity-alias> </application>
-
(Android only) Add the dependencies you require to use in
AndroidManifest.xmlType Permissions ACTIVE_CALORIES_BURNED android.permission.health.READ_ACTIVE_CALORIES_BURNEDandroid.permission.health.WRITE_ACTIVE_CALORIES_BURNEDBASAL_METABOLIC_RATE android.permission.health.READ_BASAL_METABOLIC_RATEandroid.permission.health.WRITE_BASAL_METABOLIC_RATEBLOOD_GLUCOSE android.permission.health.READ_BLOOD_GLUCOSEandroid.permission.health.WRITE_BLOOD_GLUCOSEBLOOD_PRESSURE android.permission.health.READ_BLOOD_PRESSUREandroid.permission.health.WRITE_BLOOD_PRESSUREBODY_FAT android.permission.health.READ_BODY_FATandroid.permission.health.WRITE_BODY_FATBODY_TEMPERATURE android.permission.health.READ_BODY_TEMPERATUREandroid.permission.health.WRITE_BODY_TEMPERATUREBODY_WATER_MASS android.permission.health.READ_BODY_WATER_MASSandroid.permission.health.WRITE_BODY_WATER_MASSBONE_MASS android.permission.health.READ_BONE_MASSandroid.permission.health.WRITE_BONE_MASSCERVICAL_MUCUS android.permission.health.READ_CERVICAL_MUCUSandroid.permission.health.WRITE_CERVICAL_MUCUSDISTANCE android.permission.health.READ_DISTANCEandroid.permission.health.WRITE_DISTANCEELEVATION_GAINED android.permission.health.READ_ELEVATION_GAINEDandroid.permission.health.WRITE_ELEVATION_GAINEDEXERCISE android.permission.health.READ_EXERCISEandroid.permission.health.WRITE_EXERCISEFLOORS_CLIMBED android.permission.health.READ_FLOORS_CLIMBEDandroid.permission.health.WRITE_FLOORS_CLIMBEDHEART_RATE android.permission.health.READ_HEART_RATEandroid.permission.health.WRITE_HEART_RATEHEART_RATE_VARIABILITY android.permission.health.READ_HEART_RATE_VARIABILITYandroid.permission.health.WRITE_HEART_RATE_VARIABILITYHEIGHT android.permission.health.READ_HEIGHTandroid.permission.health.WRITE_HEIGHTHYDRATION android.permission.health.READ_HYDRATIONandroid.permission.health.WRITE_HYDRATIONINTERMENSTRUAL_BLEEDING android.permission.health.READ_INTERMENSTRUAL_BLEEDINGandroid.permission.health.WRITE_INTERMENSTRUAL_BLEEDINGLEAN_BODY_MASS android.permission.health.READ_LEAN_BODY_MASSandroid.permission.health.WRITE_LEAN_BODY_MASSMENSTRUATION android.permission.health.READ_MENSTRUATIONandroid.permission.health.WRITE_MENSTRUATIONMENSTRUATION android.permission.health.READ_MENSTRUATIONandroid.permission.health.WRITE_MENSTRUATIONNUTRITION android.permission.health.READ_NUTRITIONandroid.permission.health.WRITE_NUTRITIONOVULATION_TEST android.permission.health.READ_OVULATION_TESTandroid.permission.health.WRITE_OVULATION_TESTOXYGEN_SATURATION android.permission.health.READ_OXYGEN_SATURATIONandroid.permission.health.WRITE_OXYGEN_SATURATIONPOWER android.permission.health.READ_POWERandroid.permission.health.WRITE_POWERRESPIRATORY_RATE android.permission.health.READ_RESPIRATORY_RATEandroid.permission.health.WRITE_RESPIRATORY_RATERESTING_HEART_RATE android.permission.health.READ_RESTING_HEART_RATEandroid.permission.health.WRITE_RESTING_HEART_RATESEXUAL_ACTIVITY android.permission.health.READ_SEXUAL_ACTIVITYandroid.permission.health.WRITE_SEXUAL_ACTIVITYSLEEP android.permission.health.READ_SLEEPandroid.permission.health.WRITE_SLEEPSPEED android.permission.health.READ_SPEEDandroid.permission.health.WRITE_SPEEDSTEPS android.permission.health.READ_STEPSandroid.permission.health.WRITE_STEPSVO2_MAX android.permission.health.READ_VO2_MAXandroid.permission.health.WRITE_VO2_MAXWEIGHT android.permission.health.READ_WEIGHTandroid.permission.health.WRITE_WEIGHTWHEELCHAIR_PUSHES android.permission.health.READ_WHEELCHAIR_PUSHESandroid.permission.health.WRITE_WHEELCHAIR_PUSHES -
Instantiate
// On Apple (iOS, watchOS) val kHealth = KHealth() // On Android (inside a ComponentActivity) class MainActivity : ComponentActivity() { private val kHealth = KHealth(this) // Rest of your code }
-
Initialise (only required on Android)
// Inside a `ComponentActivity` override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Initialise (only on Android, on Apple, this function is no-op) kHealth.initialise() }
-
Check Permission Status
val permissionResponse: Set<KHPermission> = kHealth.checkPermissions( KHPermission.ActiveCaloriesBurned(read = true, write = true), KHPermission.HeartRate(read = true, write = false), // Add as many requests as you want )
-
Request Permissions
// Same syntax as `checkPermissions` val permissionResponse: Set<KHPermission> = kHealth.requestPermissions( KHPermission.ActiveCaloriesBurned(read = true, write = true), KHPermission.HeartRate(read = true, write = false), // Add as many requests as you want )
-
Check if permission was granted
val caloriesPermResponse = permissionResponse.first { response -> response is KHPermission.ActiveCaloriesBurned }.writeStatus val wasWritePermissionGranted = caloriesPermResponse.write == true
-
Write records
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 β ") } }
-
Read records
val heartRateRecords = kHealth.readRecords(
KHReadRequest.HeartRate(
startTime = Clock.System.now().minus(1.days),
endTime = Clock.System.now()
)
)
println("Heart Rate records: $heartRateRecords")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 | β | β |
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.
Contributions are welcome! Please feel free to submit a Pull Request.
This library is licensed under the Apache 2.0 License. See the LICENSE file for details.