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

Это руководство совместимо с платформой "Здоровье и спорт" версии 1.1.0 и более поздних.

Если вы хотите создать приложение, которое управляет жизненно важными показателями пользователя, вы можете использовать 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))
}

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

Приложения могут считывать данные о жизненных показателях, чтобы показывать измерения, анализировать тенденции или синхронизировать данные с внешним сервером. Чтобы прочитать показатели, используйте 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
    }
}

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

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

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

  • Пакетные запросы на запись. Чтобы снизить нагрузку на ввод-вывод и продлить время работы от батареи, группируйте элементы данных в один вызов insertRecords с пакетами до 1000 записей, а не записывайте каждый элемент отдельно.
  • Часто записывайте данные во время отслеживания в реальном времени. Если вы часто получаете данные от датчиков, например непрерывных мониторов глюкозы или пульсометров, записывайте их пакетами с интервалом до 15 минут. Это позволит соблюсти баланс между обновлением в реальном времени и эффективным использованием батареи.
  • Используйте WorkManager для фоновой синхронизации. Используйте WorkManager для отложенной записи, например синхронизации данных с дополнительного устройства или бэкенд-службы. Рекомендуемый интервал для пакетной записи – 15 минут.
  • Используйте идентификаторы клиентов, чтобы избежать дублирования данных. При создании записей задайте 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.

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

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

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

  • Инструменты Здоровья и спорта: Это сопутствующее приложение позволяет вручную проверять записи, удалять тестовые данные и симулировать изменения в базе данных. Это лучший способ убедиться, что ваши записи хранятся правильно.
  • Модульное тестирование с помощью FakeHealthConnectClient. Используйте библиотеку тестирования, чтобы проверить, как приложение обрабатывает пограничные случаи, например отзыв разрешений или исключения API, без физического устройства.

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

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

Обычно реализация включает:

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

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

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

Общие рекомендации по отладке

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