Если вы хотите создать в своем приложении функцию отслеживания сна, вы можете использовать Health Connect для решения следующих задач:
- Опишите сеансы сна
- Запись данных о стадиях сна
- Запишите данные о сне, такие как частота сердечных сокращений, насыщение крови кислородом и частота дыхания.
- Считывайте данные о сне из других приложений.
В этом руководстве описывается, как создавать функции, позволяющие засыпать в фоновом режиме, рассматриваются типы данных, фоновое выполнение, права доступа, рекомендуемые рабочие процессы и лучшие практики.
Обзор: Создание комплексного трекера сна
Для создания комплексной системы отслеживания сна с помощью Health Connect выполните следующие основные шаги:
- Правильное распределение прав доступа на основе разрешений, связанных со здоровьем.
- Запись сеансов с помощью
SleepSessionRecord. - В течение всего сеанса необходимо последовательно записывать данные таких типов, как стадии сна, частота сердечных сокращений и насыщение крови кислородом.
- Надлежащее управление фоновым выполнением для обеспечения непрерывного сбора данных в течение ночи.
- Чтение данных сеансов для составления сводных отчетов и анализа после сна.
Этот рабочий процесс обеспечивает совместимость с другими приложениями Health Connect и подтверждает доступ к данным, контролируемый пользователем.
Прежде чем начать
Перед внедрением функций, отвечающих за сон:
- Интегрируйте Health Connect, используя соответствующую зависимость.
- Создайте экземпляр
HealthConnectClient. - Убедитесь, что ваше приложение реализует потоки разрешений во время выполнения на основе разрешений состояния здоровья .
Ключевые понятия
Health Connect представляет данные о сне с помощью нескольких основных компонентов. SleepSessionRecord служит центральной записью данных о сне, содержащей такие сведения, как время начала и окончания, а также стадии сна. Во время сеанса могут записываться различные типы данных, такие как HeartRateRecord или OxygenSaturationRecord .
Сеансы сна
Данные о сне представлены объектом SleepSessionRecord . Каждая запись содержит:
-
startTime -
endTime -
stages: Список стадий сна, содержащих данные из файлаSleepSessionRecord.Stage, включая глубокий, поверхностный, REM-сон и фазу бодрствования. - Дополнительные метаданные сессии (заголовок, примечания)
Приложения могут записывать несколько типов данных, связанных с одной сессией.
Типы данных
К распространенным типам данных, записываемых во время сеанса сна, относятся:
-
SleepSessionRecord: Записывает продолжительность и стадии сна, включая глубокий, поверхностный, REM-сон и фазу бодрствования. -
HeartRateRecord: Записывает частоту сердечных сокращений во время сна. -
OxygenSaturationRecord: Записывает уровень насыщения крови кислородом (SpO2) во время сна. -
RespiratoryRateRecord: Записывает частоту дыхания во время сна.
Каждый тип данных хранится в виде отдельной записи.
Вопросы развития
Приложения для отслеживания сна часто работают в течение длительного времени, зачастую в фоновом режиме, когда экран выключен. При разработке функций отслеживания сна важно учитывать, как управлять фоновым выполнением и запрашивать необходимые разрешения для доступа к данным о сне.
Фоновое выполнение
Приложения для отслеживания сна обычно работают всю ночь с выключенным экраном. В таком состоянии следует использовать:
- Сервисы переднего плана для сбора данных
-
WorkManagerдля отложенной записи или синхронизации - Стратегии пакетной обработки для регулярной записи детализированных данных, таких как частота сердечных сокращений.
Обеспечьте непрерывность, сохраняя идентификатор сессии неизменным при всех операциях записи.
Разрешения
Перед чтением или записью данных о сне ваше приложение должно запросить соответствующие разрешения Health Connect. Полный список типов данных см. в разделе «Типы данных Health Connect» . К распространенным разрешениям для данных о сне относятся сеансы сна и такие показатели, как частота сердечных сокращений или насыщение крови кислородом.
Доступ к сну защищен следующими разрешениями:
-
android.permission.health.READ_SLEEP -
android.permission.health.WRITE_SLEEP
Чтобы добавить в ваше приложение функцию отслеживания сна, для начала запросите разрешения на использование типа данных SleepSession .
Вот какие разрешения вам необходимо указать, чтобы иметь возможность записывать информацию о сне:
<application>
<uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>
Для чтения данных о сне необходимо запросить следующие разрешения:
<application>
<uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>
Ниже приведен пример того, как запросить разрешение на доступ к данным о сне, включая частоту сердечных сокращений, насыщение крови кислородом и частоту дыхания:
После создания экземпляра клиента ваше приложение должно запросить у пользователя разрешения. Пользователям должна быть предоставлена возможность в любое время предоставлять или отклонять разрешения.
Для этого создайте набор разрешений для необходимых типов данных. Убедитесь, что разрешения в этом наборе сначала объявлены в вашем Android-манифесте.
// Create a set of permissions for required data types
val PERMISSIONS =
setOf(
HealthPermission.getReadPermission(SleepSessionRecord::class),
HealthPermission.getWritePermission(SleepSessionRecord::class),
HealthPermission.getReadPermission(HeartRateRecord::class),
HealthPermission.getWritePermission(HeartRateRecord::class),
HealthPermission.getReadPermission(OxygenSaturationRecord::class),
HealthPermission.getWritePermission(OxygenSaturationRecord::class),
HealthPermission.getReadPermission(RespiratoryRateRecord::class),
HealthPermission.getWritePermission(RespiratoryRateRecord::class)
)
Используйте getGrantedPermissions , чтобы проверить, предоставлены ли вашему приложению уже необходимые разрешения. Если нет, используйте createRequestPermissionResultContract для запроса этих разрешений. После этого отобразится экран разрешений Health Connect.
// Create the permissions launcher
val requestPermissionActivityContract = PermissionController.createRequestPermissionResultContract()
val requestPermissions = registerForActivityResult(requestPermissionActivityContract) { granted ->
if (granted.containsAll(PERMISSIONS)) {
// Permissions successfully granted
} else {
// Lack of required permissions
}
}
suspend fun checkPermissionsAndRun(healthConnectClient: HealthConnectClient) {
val granted = healthConnectClient.permissionController.getGrantedPermissions()
if (granted.containsAll(PERMISSIONS)) {
// Permissions already granted; proceed with inserting or reading data
} else {
requestPermissions.launch(PERMISSIONS)
}
}
Поскольку пользователи могут предоставлять или отзывать разрешения в любое время, ваше приложение должно проверять наличие разрешений каждый раз перед их использованием и обрабатывать сценарии, в которых разрешение утрачивается.
Внедрить сеанс сна
В этом разделе описывается рекомендуемый порядок действий для записи данных о сне.
Чтобы сопоставить такие типы данных, как HeartRateRecord или OxygenSaturationRecord , с сеансом сна, запишите их с метками времени, которые находятся между startTime и endTime сеанса. Health Connect не использует идентификатор сеанса для связи сеансов сна с подробными данными. Вместо этого связь устанавливается неявно через перекрывающиеся временные интервалы. При чтении данных о сне вы можете использовать временной диапазон сеанса для запроса связанных типов данных, как показано в разделе «Чтение данных о сне» .
Напишите сессию
Хотя такие подробные данные, как частота сердечных сокращений, могут записываться на протяжении всего сеанса сна, сам объект SleepSessionRecord должен быть записан в Health Connect только после завершения сеанса, например, когда пользователь просыпается. Запись должна включать startTime сеанса (startTime), endTime ) и список объектов SleepSessionRecord.Stage , записанных во время сеанса, поскольку SleepSessionRecord требует, чтобы endTime был после startTime .
Чтобы написать запись о сеансе сна:
- Сгенерируйте уникальный идентификатор записи клиента.
- Когда пользователь просыпается или отслеживание сна прекращается, соберите все стадии сна и создайте запись
SleepSessionRecord. - Вставьте запись, используя
insertRecords.
Пример:
val clientRecordId = UUID.randomUUID().toString()
val sessionStartTime = LocalDateTime.of(2023, 10, 30, 22, 0).toInstant(ZoneOffset.UTC)
val sessionEndTime = LocalDateTime.of(2023, 10, 31, 7, 0).toInstant(ZoneOffset.UTC)
val stages = mutableListOf<SleepSessionRecord.Stage>()
// Add recorded stages, for example:
stages.add(SleepSessionRecord.Stage(
startTime = sessionStartTime.plusSeconds(3600),
endTime = sessionStartTime.plusSeconds(7200),
stage = SleepSessionRecord.STAGE_TYPE_LIGHT)
)
stages.add(SleepSessionRecord.Stage(
startTime = sessionStartTime.plusSeconds(7200),
endTime = sessionStartTime.plusSeconds(10800),
stage = SleepSessionRecord.STAGE_TYPE_DEEP)
)
// ... other stages
val session = SleepSessionRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
stages = stages,
metadata = Metadata(clientRecordId = clientRecordId)
)
healthConnectClient.insertRecords(listOf(session))
Чтение данных о сне
Приложения могут считывать данные о сеансах сна и связанные с ними данные, чтобы обобщать активность, предоставлять информацию о состоянии здоровья или синхронизировать данные с внешним сервером. Например, вы можете прочитать запись SleepSessionRecord , а затем запросить запись HeartRateRecord , которая произошла в тот же временной интервал.
Прочтение сессии с соответствующими данными.
Вы можете читать данные о сеансах сна, используя запрос ReadRecordsRequest с типом записи SleepSessionRecord , отфильтрованный по временному диапазону. Чтобы прочитать связанные данные для данного сеанса, выполните второй запрос для выбранного типа данных, например HeartRateRecord , отфильтровав данные по startTime и endTime сеанса сна.
В следующем примере показано, как считывать данные о сеансах сна с указанием частоты сердечных сокращений за заданный временной диапазон:
suspend fun readSleepSessionsWithAssociatedData(
healthConnectClient: HealthConnectClient,
startTime: Instant,
endTime: Instant
) {
val response = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = SleepSessionRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
for (sleepRecord in response.records) {
// Process each session
val stages = sleepRecord.stages
val notes = sleepRecord.notes
// To read specific granular data (like heart rate) that occurred during
// this session, use the session's startTime and endTime to filter
// the request for that data type.
val hrResponse = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = HeartRateRecord::class,
timeRangeFilter = TimeRangeFilter.between(
sleepRecord.startTime,
sleepRecord.endTime
)
)
)
for (heartRateRecord in hrResponse.records) {
for (sample in heartRateRecord.samples) {
val bpm = sample.beatsPerMinute
}
}
}
}
Передовые методы
Следуйте этим рекомендациям, чтобы повысить достоверность данных и удобство использования:
- Частота записи
- Активное отслеживание (в фоновом режиме): Для активного отслеживания сна данные записываются по мере их поступления или с максимальным интервалом в 15 минут.
- Фоновая синхронизация: используйте
WorkManagerдля отложенной записи. Старайтесь устанавливать интервал в 15 минут, чтобы найти баланс между передачей данных в реальном времени и экономией заряда батареи. - Пакетная обработка: Не записывайте каждое событие с датчика по отдельности. Разделите запросы на части. Health Connect обрабатывает до 1000 записей за один запрос на запись.
- Сохраняйте стабильность и уникальность идентификаторов сессий: используйте согласованные идентификаторы для ваших сессий. Если сессия редактируется или обновляется, использование того же идентификатора предотвратит ее обработку как новой, отдельной сессии сна.
- Используйте пакетную обработку для различных типов данных: чтобы уменьшить накладные расходы на ввод/вывод и продлить срок службы батареи, группируйте точки данных в один вызов
insertRecordsа не записывайте каждую точку по отдельности. Избегайте записи дублирующихся данных: используйте идентификаторы клиентов. При создании записей задайте параметр
metadata.clientRecordId. Health Connect использует его для идентификации уникальных записей. Если вы попытаетесь записать запись с уже существующимclientRecordId, Health Connect проигнорирует дубликат или обновит существующую запись, а не создаст новую. Установка параметраmetadata.clientRecordId— наиболее эффективный способ предотвратить дубликаты при повторных попытках синхронизации или переустановке приложения.val record = RespiratoryRateRecord( rate = 16.0, time = time, zoneOffset = ZoneOffset.UTC, metadata = Metadata( // Use a unique ID from your own database clientRecordId = "respiratory_rate_20231030_1" ) )Проверьте существующие данные: перед синхронизацией запросите временной диапазон, чтобы узнать, существуют ли уже записи из вашего приложения.
Убедитесь, что временные метки не перекрываются: проверьте, что новая сессия не начинается до окончания предыдущей. Перекрывающиеся сессии могут вызывать конфликты на панелях мониторинга фитнеса и в сводных расчетах.
Четко обоснуйте необходимость предоставления разрешения: используйте поток
Permission.createIntent, чтобы объяснить, почему вашему приложению необходим доступ к данным о здоровье, например: «Для анализа ваших моделей сна».Протестируйте длительные сеансы: отслеживайте расход заряда батареи во время сеансов, длящихся несколько часов, чтобы убедиться, что интервал пакетной обработки и использование датчиков не разряжают устройство.
Согласуйте временные метки с частотой работы датчиков: сопоставьте временные метки записей с фактической частотой работы датчиков, чтобы обеспечить высокую точность данных.
Тестирование
Для проверки корректности данных и обеспечения высокого качества пользовательского опыта следуйте этим стратегиям тестирования и обратитесь к официальной документации по основным вариантам использования тестирования .
инструменты проверки
- Health Connect Toolbox : Используйте это сопутствующее приложение для ручной проверки записей, удаления тестовых данных и имитации изменений в базе данных. Это лучший способ убедиться в правильности хранения ваших записей.
- Модульное тестирование с помощью
FakeHealthConnectClient: используйте библиотеку тестирования, чтобы проверить, как ваше приложение обрабатывает граничные случаи, такие как отзыв разрешений или исключения API, без необходимости использования физического устройства.
Контрольный список качества
Типичная архитектура
Обычно в систему отслеживания сна входят следующие компоненты:
| Компонент | Управляет |
|---|---|
| контроллер сессии | состояние сессии Таймер Логика пакетной обработки Контроллеры типов данных Сбор данных |
| Уровень репозитория (обертывает операции Health Connect): | Вставить сессию Вставьте типы данных Вставляет стадии сна Ознакомьтесь с краткими обзорами сессий. |
| Слой пользовательского интерфейса (дисплеи): | Продолжительность Типы данных в реальном времени Визуализация стадий сна |
Поиск неисправностей
| Симптом | Возможная причина | Разрешение |
|---|---|---|
| Отсутствующие типы данных (например, частота сердечных сокращений) | Отсутствуют права на запись или некорректно работают временные фильтры. | Убедитесь, что вы запросили разрешение на доступ к данным определенного типа, и пользователь его предоставил. Проверьте, что ваш ReadRecordsRequest использует TimeRangeFilter , соответствующий сессии. См. раздел «Разрешения» . |
| Сессия не записывается | Перекрывающиеся временные метки. | Приложение Health Connect может отклонять записи, которые частично совпадают с существующими данными из того же приложения. Убедитесь, что время startTime новой сессии позже времени endTime предыдущей. |
| Данные с датчиков во время сна не регистрировались. | Работа основной службы была прекращена или приостановлена. | Для сбора данных с датчиков в течение ночи при выключенном экране можно использовать службу переднего плана с foregroundServiceType="health" . |
| Появляются повторяющиеся записи. | Отсутствует clientRecordId . | Присвойте каждой записи уникальный clientRecordId в Metadata . Это позволит Health Connect выполнить дедупликацию, если одни и те же данные будут записаны дважды во время повторной попытки синхронизации. См. раздел «Рекомендации» . |
Типичные шаги отладки
| Проверьте состояние прав доступа. | Перед выполнением операции чтения или записи всегда вызывайте getPermissionStatus() . Пользователи могут в любой момент отозвать разрешения в системных настройках. |
| Проверьте режим выполнения. | Если ваше приложение не собирает данные в фоновом режиме, убедитесь, что вы указали правильные разрешения в файле AndroidManifest.xml и что пользователь не перевел приложение в режим "Ограничение использования батареи". |