在 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
資料類型包含兩個部分:
- 整個時段,範圍涵蓋整個睡眠期間。
- 睡眠時段中的個別階段,例如淺層睡眠或深層睡眠。
以下說明如何插入不含睡眠階段的睡眠時段:
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
)
刪除運動時段
有兩種方法可以刪除運動時段:
- 依據時間範圍。
- 依據 UID。
以下說明如何根據時間範圍刪除子類型資料:
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()
)
}