Інтеграція Health Connect для доступу до даних здоров'я в Android
Health Connect — централізоване сховище даних здоров'я для Android, відповідь Google на HealthKit в iOS. З'явився як standalone-приложення в 2022 році, вбудований в Android 14 як системний компонент. Правильна архітектура від старту заощадить тижні роботи при додаванні нових типів даних або підтримці Wear OS.
Вимоги Google Play та ліцензійна угода
Це перше, з чого надо починати — не з коду. Приложення, які читають дані з Health Connect, обов'язані:
- Підписати Health Connect Permissions Policy та відправити форму в Google до публікації
- Мати екран політики конфіденціальності, явно описуючий використання медичних даних
- Не передавати дані здоров'я третім сторонам без явної згоди користувача (включаючи аналітику)
- При запиті дозволів показувати обґрунтування кожного типу даних
Порушення цих вимог — гарантоване видалення з Play Market. Проходимо review Health Connect ще до релізу.
Підключення та дозволи
// build.gradle
implementation("androidx.health.connect:connect-client:1.1.0")
Мінімальна версія: minSdk = 26, але Health Connect як приложення працює на Android 9+, а вбудований — в Android 14. На Android 9–13 користувач повинен установити Health Connect з Play Store.
val healthConnectClient = HealthConnectClient.getOrCreate(context)
// Перевірка доступності
when (HealthConnectClient.getSdkStatus(context)) {
HealthConnectClient.SDK_AVAILABLE -> { /* працюємо */ }
HealthConnectClient.SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED -> {
// Показуємо кнопку установки/оновлення Health Connect
val intent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("market://details?id=com.google.android.apps.healthdata")
}
startActivity(intent)
}
HealthConnectClient.SDK_UNAVAILABLE -> { /* Android < 9, Health Connect не підтримується */ }
}
Запит дозволів:
val permissions = setOf(
HealthPermission.getReadPermission(StepsRecord::class),
HealthPermission.getReadPermission(HeartRateRecord::class),
HealthPermission.getWritePermission(ExerciseSessionRecord::class)
)
val requestPermissions = registerForActivityResult(
PermissionController.createRequestPermissionResultContract()
) { granted ->
if (granted.containsAll(permissions)) {
// всі дозволи отримані
}
}
// Перевірка перед запитом
val granted = healthConnectClient.permissionController.getGrantedPermissions()
if (!granted.containsAll(permissions)) {
requestPermissions.launch(permissions)
}
Читання даних: Records та запити
Кожний тип даних — окремий Record-класс: StepsRecord, HeartRateRecord, SleepSessionRecord, ExerciseSessionRecord та ін. Типів більш 40.
// Кроки за період
val response = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = StepsRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
val totalSteps = response.records.sumOf { it.count }
Для агрегації — aggregateGroupByDuration або aggregateGroupByPeriod:
val aggregateRequest = AggregateGroupByPeriodRequest(
metrics = setOf(StepsRecord.COUNT_TOTAL),
timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
timeRangeSlicer = Period.ofDays(1)
)
val result = healthConnectClient.aggregateGroupByPeriod(aggregateRequest)
result.forEach { bucket ->
val steps = bucket.result[StepsRecord.COUNT_TOTAL] ?: 0L
// кроки за один день
}
Запис тренувань
val exerciseSession = ExerciseSessionRecord(
startTime = workoutStart,
startZoneOffset = ZoneOffset.UTC,
endTime = workoutEnd,
endZoneOffset = ZoneOffset.UTC,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
title = "Утренняя пробежка"
)
val distanceRecord = DistanceRecord(
startTime = workoutStart,
startZoneOffset = ZoneOffset.UTC,
endTime = workoutEnd,
endZoneOffset = ZoneOffset.UTC,
distance = Length.meters(5200.0)
)
healthConnectClient.insertRecords(listOf(exerciseSession, distanceRecord))
Фонове читання та зміни
changesToken — механізм інкрементальних оновлень, аналог HKAnchoredObjectQuery в HealthKit:
// Отримуємо початковий токен
val token = healthConnectClient.getChangesToken(
ChangesTokenRequest(setOf(StepsRecord::class))
)
// При наступній синхронізації
val changes = healthConnectClient.getChanges(token)
changes.changes.filterIsInstance<UpsertionChange>().forEach { change ->
// нова або обновлена запись
}
val newToken = changes.nextChangesToken // зберігаємо для наступного разу
Сумісність з Google Fit
Health Connect не читає історичні дані Google Fit автоматично. Користувач повинен вручну включити синхронізацію в налаштуваннях Health Connect. Якщо приложення мігрує з Google Fit — інформуємо користувачів, що старі дані можуть відображатися не одразу.
Терміни
Базова інтеграція Health Connect (читання кроків, ЧСС, сну) — 5–8 робочих днів. З записом тренувань, інкрементальною синхронізацією з сервером та fallback на Google Fit — 2–3 тижні.







