Как создавать функции для отслеживания жизненных показателей с помощью платформы "Здоровье и спорт"

Если вы хотите создать приложение для отслеживания показателей здоровья, с помощью Health Connect вы сможете:

  • Чтение данных о жизненных показателях, таких как артериальное давление, пульс и температура тела, из других приложений.
  • Записывать данные о показателях жизнедеятельности, полученные от вашего приложения или подключенных устройств.
  • Отслеживать тенденции и предоставлять информацию о здоровье на основе данных о жизненно важных показателях.

В этом руководстве рассказывается, как работать с типами данных о жизненно важных показателях, включая разрешения, рабочие процессы чтения и записи, а также рекомендации.

Обзор: создание комплексного трекера жизненных показателей

Чтобы создать комплексную систему отслеживания жизненных показателей с помощью платформы "Здоровье и спорт", выполните следующие основные действия:

  • Запрашивать необходимые разрешения для типов данных о показателях жизнедеятельности.
  • Запись данных о жизненно важных показателях с помощью таких записей, как BloodPressureRecord, HeartRateRecord и других.
  • Чтение данных о жизненных показателях для отображения, анализа или синхронизации.
  • Использование пакетной обработки для эффективной записи и чтения данных.

Этот процесс обеспечивает совместимость с другими приложениями, использующими платформу "Здоровье и спорт", и позволяет пользователю контролировать доступ к данным.

Подготовка

Перед тем как внедрять функции жизненных показателей, сделайте следующее:

Основные понятия

Данные о жизненных показателях в сервисе "Здоровье и спорт" представлены в виде записей разных типов, каждая из которых соответствует определенному физиологическому показателю. В отличие от тренировок, показатели жизнедеятельности часто записываются как данные, относящиеся к определенному моменту времени или интервалу.

Типы данных о жизненных показателях

Данные о жизненно важных показателях представлены в виде отдельных типов записей. Вот некоторые из них:

  • BloodPressureRecord – запись об измерении артериального давления, включая систолическое и диастолическое давление, а также положение тела.
  • HeartRateRecord – серия измерений пульса.
  • RestingHeartRateRecord – одно измерение частоты сердечных сокращений в покое.
  • BodyTemperatureRecord: представляет собой одно измерение температуры тела, включая место измерения.
  • BloodGlucoseRecord: представляет собой одно измерение уровня глюкозы в крови, включая информацию о связи с приемом пищи и источнике образца.
  • OxygenSaturationRecord – одно измерение насыщения крови кислородом.
  • RespiratoryRateRecord – одно измерение частоты дыхания.

Полный список типов данных приведен в статье Типы данных в приложении "Здоровье и спорт".

Рекомендации по разработке

Данные о жизненных показателях могут быть конфиденциальными, и приложениям может потребоваться записывать их в ответ на показания датчиков или ввод данных пользователем, а также синхронизировать с бэкендом. Разрешения необходимы для работы с данными о показателях жизнедеятельности.

Разрешения

Чтобы читать или записывать данные о показателях жизнедеятельности, ваше приложение должно запросить соответствующие разрешения для платформы "Здоровье и спорт". К распространенным разрешениям для жизненно важных показателей относятся артериальное давление, частота пульса, температура тела, уровень глюкозы в крови, насыщение крови кислородом и частота дыхания. Примеры:

  • Давление. Разрешения на чтение и запись для BloodPressureRecord.
  • Пульс. Разрешения на чтение и запись для HeartRateRecord.
  • Пульс в покое. Разрешения на чтение и запись для RestingHeartRateRecord.
  • Температура тела. Разрешения на чтение и запись для BodyTemperatureRecord.
  • Уровень глюкозы в крови. Разрешения на чтение и запись для BloodGlucoseRecord.
  • Уровень кислорода в крови: разрешения на чтение и запись для OxygenSaturationRecord.
  • Частота дыхания. Разрешения на чтение и запись для RespiratoryRateRecord.

Ниже приведен пример того, как запросить разрешения на доступ к данным об артериальном давлении, пульсе и температуре тела:

После создания экземпляра клиента приложению необходимо запросить у пользователя разрешения. Пользователи должны иметь возможность в любой момент предоставить или отклонить разрешения. Для этого создайте набор разрешений для нужных типов данных. Убедитесь, что разрешения из набора объявлены в манифесте Android.

val permissions =
    setOf(
        HealthPermission.getReadPermission(BloodPressureRecord::class),
        HealthPermission.getWritePermission(BloodPressureRecord::class),
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class),
        HealthPermission.getReadPermission(BodyTemperatureRecord::class),
        HealthPermission.getWritePermission(BodyTemperatureRecord::class)
    )
Используйте getGrantedPermissions, чтобы проверить, есть ли у вашего приложения необходимые разрешения. Если нет, используйте createRequestPermissionResultContract, чтобы запросить эти разрешения. Откроется экран с разрешениями для сервиса "Здоровье и спорт".
val permissions = setOf(
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class),
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class)
    )

val requestPermissionsLauncher = rememberLauncherForActivityResult(
    contract = PermissionController.createRequestPermissionResultContract()
) { grantedPermissions ->
    if (grantedPermissions.containsAll(permissions)) {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions granted!") }
    } else {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions denied.") }
    }
}
Поскольку пользователи могут в любой момент предоставить или отозвать разрешения, ваше приложение должно проверять их каждый раз перед использованием и обрабатывать ситуации, когда разрешение теряется.

Чтобы запросить разрешения, вызовите функцию checkPermissionsAndRun:

if (!granted.containsAll(permissions)) {
    // Check if required permissions are not granted, and return
    return emptySet()
}
// Permissions already granted; proceed with inserting or reading data

Если вам нужно запросить разрешения только для одного типа данных, например для измерения артериального давления, включите в набор разрешений только этот тип данных:

Доступ к данным об артериальном давлении защищен следующими разрешениями:

  • android.permission.health.READ_BLOOD_PRESSURE
  • android.permission.health.WRITE_BLOOD_PRESSURE

Чтобы добавить в приложение возможность отслеживать артериальное давление, сначала запросите разрешения для типа данных BloodPressureRecord.

Чтобы записывать данные об артериальном давлении, необходимо объявить следующее разрешение:

<application>
  <uses-permission
android:name="android.permission.health.WRITE_BLOOD_PRESSURE" />
...
</application>

Чтобы считывать данные о кровяном давлении, необходимо запросить следующие разрешения:

<application>
  <uses-permission
android:name="android.permission.health.READ_BLOOD_PRESSURE" />
...
</application>

Запись данных о жизненных показателях

В этом разделе рассказывается, как записывать данные о жизненных показателях на платформу "Здоровье и спорт". Данные о жизненных показателях обычно записываются в виде отдельных записей. Если вы записываете несколько объектов одновременно, например синхронизируете данные с датчика или серверной части, используйте пакетную обработку.

Пример использования BloodPressureRecord:

suspend fun writeBloodPressureRecord(healthConnectClient: HealthConnectClient) {
    val record = BloodPressureRecord(
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
        systolic = Pressure.millimetersOfMercury(120.0),
        diastolic = Pressure.millimetersOfMercury(80.0),
        bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN,
        measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST
    )
    healthConnectClient.insertRecords(listOf(record))
}

Пакетная запись

Если приложению нужно записать несколько точек данных, например при синхронизации данных с подключенного устройства или бэкенд-службы, объедините операции записи в пакеты, чтобы повысить эффективность и снизить расход батареи. Платформа "Здоровье и спорт" может обрабатывать до 1000 записей в одном запросе на запись.

В следующем фрагменте кода показано, как записать несколько записей одновременно:

suspend fun writeBatchRecords(healthConnectClient: HealthConnectClient) {
    val bloodPressureRecord = BloodPressureRecord(
        time = Instant.now(),
        zoneOffset = ZoneOffset.UTC,
        systolic = Pressure.millimetersOfMercury(120.0),
        diastolic = Pressure.millimetersOfMercury(80.0),
        bodyPosition = BloodPressureRecord.BODY_POSITION_SITTING_DOWN,
        measurementLocation = BloodPressureRecord.MEASUREMENT_LOCATION_LEFT_WRIST
    )
    val heartRateRecord = HeartRateRecord(
        startTime = Instant.now().minusSeconds(60),
        startZoneOffset = ZoneOffset.UTC,
        endTime = Instant.now(),
        endZoneOffset = ZoneOffset.UTC,
        samples = listOf(HeartRateRecord.Sample(time = Instant.now().minusSeconds(30), beatsPerMinute = 80))
    )
    healthConnectClient.insertRecords(listOf(bloodPressureRecord, heartRateRecord))
}

Чтение данных о жизненных показателях

Приложения могут считывать данные Vitals, чтобы показывать измерения, анализировать тенденции или синхронизировать данные с внешним сервером. Чтобы прочитать жизненно важные показатели, используйте ReadRecordsRequest с определенным типом записи и отфильтруйте данные по диапазону времени.

Пример чтения данных BloodPressureRecord:

suspend fun readBloodPressureRecords(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    val response = healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = BloodPressureRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
        )
    )

    for (record in response.records) {
        // Process each blood pressure record
        val systolic = record.systolic
        val diastolic = record.diastolic
    }
}

Если вам нужно синхронизировать данные о жизненных показателях с бэкенд-сервером или поддерживать актуальность хранилища данных приложения с помощью Здоровья и спорта, используйте журналы изменений. Это позволяет получать список добавленных, измененных или удаленных записей за определенный период времени, что эффективнее, чем отслеживать изменения вручную или постоянно считывать все данные. Подробнее о синхронизации данных с платформой "Здоровье и спорт"…

Рекомендации

Чтобы повысить надежность данных и удобство использования, следуйте приведенным ниже рекомендациям.

  • Пакетные запросы на запись. Чтобы снизить нагрузку на ввод-вывод и продлить срок службы батареи, группируйте точки данных в один вызов insertRecords с пакетами до 1000 записей, а не записывайте каждую точку отдельно.
  • Часто записывайте данные во время отслеживания в реальном времени. Если датчики (например, устройства непрерывного мониторинга уровня глюкозы или пульсометры) часто отправляют обновления, записывайте данные пакетами с интервалом до 15 минут, чтобы обеспечить баланс между обновлениями в реальном времени и эффективным использованием батареи.
  • Используйте WorkManager для фоновой синхронизации. Используйте WorkManager для отложенной записи, например для синхронизации данных с дополнительного устройства или бэкенд-службы. Рекомендуем выполнять пакетную запись каждые 15 минут.
  • Не записывайте дублирующиеся данные. Используйте идентификаторы Client-ID. При создании записей задайте значение metadata.clientRecordId. Платформа "Здоровье и спорт" использует его для идентификации уникальных записей. Если вы попытаетесь записать данные с clientRecordId, который уже существует, Здоровье и спорт проигнорирует дубликат или обновит существующую запись, а не создаст новую. Установка значения metadata.clientRecordId – самый эффективный способ предотвратить появление дубликатов при повторных попытках синхронизации или переустановке приложения.
    val record = StepsRecord(
        count = 100,
        startTime = startTime,
        endTime = endTime,
        startZoneOffset = ZoneOffset.UTC,
        endZoneOffset = ZoneOffset.UTC,
        metadata = Metadata(
            // Use a unique ID from your own database
            clientRecordId = "daily_steps_2023_10_27_user_123"
        )
    )
  • Проверьте существующие данные. Перед синхронизацией данных запросите у сервиса "Здоровье и спорт" записи в пределах диапазона времени синхронизации, чтобы узнать, существуют ли уже данные из вашего приложения, и избежать дублирования или перезаписи более новых данных.
  • Четко объясняйте, зачем нужны разрешения. В процессе Permission.createIntent объясните, почему приложению нужен доступ к данным о здоровье. Например: "Чтобы отслеживать тенденции изменения артериального давления и предоставлять вам статистику".
  • Сопоставьте временные метки с данными измерений. Убедитесь, что временные метки записей точно отражают время, когда были выполнены измерения. Для данных интервала, например HeartRateRecord, проверьте, правильно ли указаны значения startTime и endTime.

Тестирование

Чтобы проверить правильность данных и удобство для пользователей, следуйте этим стратегиям тестирования и ознакомьтесь с официальной документацией по тестированию основных вариантов использования.

Инструменты проверки

Контрольный список по качеству

Типичная архитектура

Реализация жизненных показателей обычно включает:

Компонент Управляет
Контроллер жизненных показателей Считывание данных с датчиков/входных устройств
Логика пакетной обработки
Уровень хранилища (обертка для операций с Здоровьем и спортом): Вставка записей о жизненных показателях
Чтение записей о жизненных показателях
Уровень интерфейса (экраны): Показатели в реальном времени
Исторические данные
Диаграммы и тенденции

Устранение неполадок

Проблема Возможные причины Разрешение
Отсутствующие типы данных (например, "Артериальное давление") Отсутствуют разрешения на запись или неправильно настроены временные фильтры. Убедитесь, что вы запросили разрешение на доступ к определенному типу данных и пользователь его предоставил. Убедитесь, что в ReadRecordsRequest используется TimeRangeFilter, охватывающий время измерения. Подробнее о разрешениях…
Появляются дублирующиеся записи Не указан атрибут "clientRecordId". Присвойте уникальный clientRecordId в Metadata каждой записи. Это позволяет сервису "Здоровье и спорт" удалять дубликаты, если одни и те же данные записываются дважды при повторной попытке синхронизации. Ознакомьтесь с рекомендациями.
Не удается записать записи Неправильные единицы измерения или значения за пределами допустимого диапазона. Платформа "Здоровье и спорт" проверяет значения записей. Например, значения артериального давления должны быть в физиологически допустимом диапазоне. Допустимые диапазоны и единицы измерения указаны в документации по типам данных.

Распространенные способы отладки

Проверьте статус разрешения. Перед каждой операцией чтения или записи вызывайте функцию getPermissionStatus(). Пользователи могут в любое время отозвать разрешения в системных настройках.