Интеграция 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
// steps за один день
}
Запись тренировок
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 недели.







