Сеансы

В Health Connect сеанс — это интервал времени, в течение которого пользователь выполняет какое-либо действие. Оба типа данных SleepSessionRecord и ExerciseSessionRecord являются сеансами.

Сеансы позволяют пользователям измерять производительность на основе времени за определенный период времени, например, непрерывную частоту пульса или данные о местоположении.

Сеансы ExerciseSessionRecord включают в себя различные виды деятельности, от бега до бадминтона.

Сеансы SleepSessionRecord содержат данные, записывающие стадии сна, такие как AWAKE , SLEEPING и DEEP .

Данные подтипа — это данные, которые «принадлежат» сеансу и имеют смысл только тогда, когда они читаются с помощью родительского сеанса, например, этап сна, сегмент упражнений.

Связанные данные — это данные Record , которые можно считывать отдельно или вместе с другими сеансами, например, шаги, частота сердечных сокращений.

Общее руководство

Вот несколько рекомендаций по работе с сеансами в Health Connect.

  • Сеансы следует использовать для добавления данных о конкретной тренировке или занятии или о сне:
suspend fun writeExerciseSession(healthConnectClient: HealthConnectClient) {
    healthConnectClient.insertRecords(
        listOf(
            ExerciseSessionRecord(
                startTime = Instant.parse("2022-05-10T10:00:00.000Z"),
                startZoneOffset = ZoneOffset.of("-08:00"),
                endTime = Instant.parse("2022-05-10T11:00:00.000Z"),
                endZoneOffset = ZoneOffset.of("-08:00"),
                exerciseType = ExerciseSessionRecord.ExerciseType.WALKING,
                title = "My Walk"
            ),
            StepsRecord(
                startTime = Instant.parse("2022-05-10T10:00:00.000Z"),
                startZoneOffset = ZoneOffset.of("-08:00"),
                endTime = Instant.parse("2022-05-10T10:30:00.000Z"),
                endZoneOffset = ZoneOffset.of("-08:00"),
                count = 2800
            ),
StepsRecord(
                startTime = Instant.parse("2022-05-10T10:30:00.000Z"),
                startZoneOffset = ZoneOffset.of("-08:00"),
                endTime = Instant.parse("2022-05-10T11:00:00.000Z"),
                endZoneOffset = ZoneOffset.of("-08:00"),
                count = 3200
            ),  
        )
    )
}
  • Сеансы не следует использовать для общих измерений, таких как ежедневный подсчет шагов.
  • Данные подтипа не содержат UID, но связанные данные имеют отдельные UID.
  • Данные подтипа должны быть выровнены в сеансе с последовательными метками времени, которые не перекрываются. Однако пробелы допускаются.
  • Сеансы полезны, если пользователь хочет, чтобы данные были связаны с сеансом (и отслеживались как его часть), а не записывались непрерывно.

Сеансы сна

Вы можете читать или записывать данные о сне в Health Connect. Данные сна отображаются в виде сеанса и могут быть разделены на 8 отдельных стадий сна:

  • UNKNOWN : Не указано или неизвестно, если пользователь спит.
  • AWAKE : пользователь бодрствует во время цикла сна, а не в течение дня.
  • SLEEPING : общее или недетализированное описание сна.
  • OUT_OF_BED : пользователь встает с постели в середине сеанса сна.
  • AWAKE_IN_BED : пользователь не спит в постели.
  • LIGHT : пользователь находится в состоянии легкого сна.
  • DEEP : Пользователь находится в цикле глубокого сна.
  • REM : пользователь находится в фазе быстрого сна.

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

Напишите сеансы сна со стадиями сна или без них.

Тип данных SleepSessionRecord состоит из двух частей:

  1. Общий сеанс, охватывающий всю продолжительность сна.
  2. Отдельные стадии во время сеанса сна, такие как легкий сон или глубокий сон.

Вот как можно вставить сеанс сна без этапов:

      SleepSessionRecord(
        title = "weekend sleep",
        startTime = startTime,
        endTime = endTime,
        startZoneOffset = ZoneOffset.UTC,
        endZoneOffset = ZoneOffset.UTC,
      )

Вот как можно добавить этапы, охватывающие весь период сеанса сна:

val stages = listOf(
    SleepSessionRecord.Stage(
        startTime = START_TIME
        endTime = END_TIME,
        stage = SleepSessionRecord.STAGE_TYPE_SLEEPING,
    )
)

SleepSessionRecord(
        title = "weekend sleep",
        startTime = START_TIME,
        endTime = END_TIME,
        startZoneOffset = START_ZONE_OFFSET,
        endZoneOffset = END_ZONE_OFFSET,
        stages = stages,
      )
  }

Читать сеанс сна

Для каждого возвращенного сеанса сна вы должны проверить, присутствуют ли также данные о стадии сна:

suspend fun readSleepSessions(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    val response =
        healthConnectClient.readRecords(
            ReadRecordsRequest(
                SleepSessionRecord::class,
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
    for (sleepRecord in response.records) {
        // Retrieve relevant sleep stages from each sleep record
        val sleepStages = sleepRecord.stages
    }
}

Удаление сеанса сна

Вот как удалить сеанс. В этом примере мы использовали сеанс сна:

suspend fun deleteSleepSession(
    healthConnectClient: HealthConnectClient,
    sleepRecord: SleepSessionRecord,
) {
    val timeRangeFilter = TimeRangeFilter.between(sleepRecord.startTime, sleepRecord.endTime)
    healthConnectClient.deleteRecords(SleepSessionRecord::class, timeRangeFilter)
}

Упражнения

Тренировки могут включать в себя что угодно: от бега до бадминтона.

Напишите упражнения

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

suspend fun writeExerciseSession(healthConnectClient: HealthConnectClient) {
    healthConnectClient.insertRecords(
        listOf(
            ExerciseSessionRecord(
                startTime = START_TIME,
                startZoneOffset = START_ZONE_OFFSET,
                endTime = END_TIME,
                endZoneOffset = END_ZONE_OFFSET,
                exerciseType = ExerciseSessionRecord.ExerciseType.RUNNING,
                title = "My Run"
            ),
            DistanceRecord(
                startTime = START_TIME,
                startZoneOffset = START_ZONE_OFFSET,
                endTime = END_TIME,
                endZoneOffset = END_ZONE_OFFSET,
                distance = 5000.meters
            ),
            // ... other records
        )
    )
}

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

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

Прочитать упражнение

Вот пример того, как читать упражнение:

suspend fun readExerciseSessions(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    val response =
        healthConnectClient.readRecords(
            ReadRecordsRequest(
                ExerciseSessionRecord::class,
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
    for (exerciseRecord in response.records) {
        // Process each exercise record
        // Optionally pull in with other data sources of the same time range.
        val distanceRecord =
            healthConnectClient
                .readRecords(
                    ReadRecordsRequest(
                        DistanceRecord::class,
                        timeRangeFilter =
                            TimeRangeFilter.between(
                                exerciseRecord.startTime,
                                exerciseRecord.endTime
                            )
                    )
                )
                .records
    }
}

Запись данных подтипа

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

Например, сеансы упражнений могут включать классы ExerciseSegment , ExerciseLap и ExerciseRoute :

val segments = listOf(
  ExerciseSegment(
    startTime = Instant.parse("2022-01-02T10:10:10Z"),
    endTime = Instant.parse("2022-01-02T10:10:13Z"),
    segmentType = ActivitySegmentType.BENCH_PRESS,
    repetitions = 373
  )
)

val laps = listOf(
  ExerciseLap(
    startTime = Instant.parse("2022-01-02T10:10:10Z"),
    endTime = Instant.parse("2022-01-02T10:10:13Z"),
    length = 0.meters
  )
)

ExerciseSessionRecord(
  exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_CALISTHENICS,
    startTime = Instant.parse("2022-01-02T10:10:10Z"),
    endTime = Instant.parse("2022-01-02T10:10:13Z"),
  startZoneOffset = ZoneOffset.UTC,
  endZoneOffset = ZoneOffset.UTC,
  segments = segments,
  laps = laps,
  route = route
)

Удаление тренировки

Есть два способа удалить тренировку:

  1. По временному диапазону.
  2. По ЮИД.

Вот как можно удалить данные подтипа в соответствии с диапазоном времени:

suspend fun deleteExerciseSession(
    healthConnectClient: HealthConnectClient,
    exerciseRecord: ExerciseSessionRecord,
) {
    val timeRangeFilter = TimeRangeFilter.between(sleepRecord.startTime, sleepRecord.endTime)
    healthConnectClient.deleteRecords(SleepSessionRecord::class, timeRangeFilter)
    // delete the associated distance record
    healthConnectClient.deleteRecords(DistanceRecord::class, timeRangeFilter)
}

Вы также можете удалить данные подтипа по UID. Однако при этом будет удалена только сессия тренировки, а не связанные с ней данные:

suspend fun deleteExerciseSession(
    healthConnectClient: HealthConnectClient,
    exerciseRecord: ExerciseSessionRecord,
) {
    healthConnectClient.deleteRecords(
        ExerciseSessionRecord::class,
        recordIdsList = listOf(exerciseRecord.metadata.id),
        clientRecordIdsList = emptyList()
    )
}