Skip to content

A Kotlin Multiplatform wrapper for Android's Health Connect and Apple's HealthKit πŸ₯

License

Notifications You must be signed in to change notification settings

yschimke/KHealth

Β 
Β 

Repository files navigation

πŸ₯ KHealth πŸ₯

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.

Demo

Note

You can find the following app in the sample* directories (e.g. sampleAndroidApp and sampleAppleApps)

android.mp4
iOS.mp4
watchOS.mp4

πŸš€ Getting Started

Maven Central Version

Add the following to your shared module's build.gradle.kts:

implementation("io.github.shubhamsinghshubham777:khealth:1.0.0")

or add it to your version catalog:

[versions]
khealth = "1.0.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)
        }
    }
}

βš™οΈ Usage

  1. (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>
  2. (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
  3. 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
    }
  4. 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()
    }
  5. 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
     )
  6. 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
     )
  7. Check if permission was granted

    val caloriesPermResponse = permissionResponse.first { response ->
        response is KHPermission.ActiveCaloriesBurned
    }.writeStatus
    
    val wasWritePermissionGranted = caloriesPermResponse.write == true 
  8. 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 βœ…")
         }
    }
  9. Read records

     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 βœ… ❌
FloorsClimbed βœ… βœ…
HeartRate βœ… βœ…
HeartRateVariability βœ… βœ…
Height βœ… βœ…
Hydration βœ… βœ…
IntermenstrualBleeding βœ… βœ…
LeanBodyMass βœ… βœ…
MenstruationPeriod βœ… ❌
MenstruationFlow βœ… βœ…
Nutrition βœ… βœ…
OvulationTest βœ… βœ…
OxygenSaturation βœ… βœ…
Power βœ… βœ…
RespiratoryRate βœ… βœ…
RestingHeartRate βœ… βœ…
SexualActivity βœ… βœ…
SleepSession βœ… βœ…
Speed βœ… ❌
RunningSpeed ❌ βœ…
CyclingSpeed ❌ βœ…
StepCount βœ… βœ…
Vo2Max βœ… βœ…
Weight βœ… βœ…
WheelChairPushes βœ… βœ…

Note

The unsupported data 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 file for details.

About

A Kotlin Multiplatform wrapper for Android's Health Connect and Apple's HealthKit πŸ₯

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Kotlin 99.4%
  • Swift 0.6%