Phiên

Trong ứng dụng Health Connect, phiên hoạt động là khoảng thời gian mà người dùng thực hiện một hoạt động. Kiểu dữ liệu của SleepSessionRecordExerciseSessionRecord đều là phiên hoạt động.

Phiên hoạt động cho phép người dùng đo lường hiệu suất hoạt động (tính theo thời gian) trong một khoảng thời gian nhất định, chẳng hạn như nhịp tim liên tục hoặc dữ liệu vị trí.

Phiên hoạt động ExerciseSessionRecord gồm nhiều hoạt động khác nhau, từ chạy bộ đến chơi cầu lông.

Phiên hoạt động SleepSessionRecord chứa dữ liệu ghi lại các giai đoạn ngủ, chẳng hạn như AWAKE, SLEEPINGDEEP.

Dữ liệu loại phụ là dữ liệu "thuộc về" một phiên hoạt động và chỉ có nghĩa khi được đọc bằng phiên hoạt động gốc, ví dụ: giai đoạn ngủ, phân đoạn tập thể dục.

Dữ liệu liên quan là dữ liệu Record có thể được đọc độc lập hoặc kết hợp cùng các phiên hoạt động khác, ví dụ: số bước, nhịp tim.

Hướng dẫn chung

Dưới đây là một số nguyên tắc dành cho các phương pháp hay nhất về cách sử dụng phiên hoạt động trong ứng dụng Health Connect.

  • Bạn nên sử dụng phiên hoạt động để thêm dữ liệu từ một bài tập thể dục hoặc hoạt động cụ thể hay cho giấc ngủ:
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
            ),  
        )
    )
}
  • Bạn không nên sử dụng phiên hoạt động cho các phép đo chung, chẳng hạn như số bước mỗi ngày.
  • Dữ liệu loại phụ không chứa UID, nhưng dữ liệu liên quan sẽ có UID riêng biệt.
  • Dữ liệu loại phụ cần được sắp xếp trong một phiên hoạt động có dấu thời gian tuần tự không chồng chéo lên nhau. Dù vậy, dữ liệu đứt quãng vẫn được chấp nhận.
  • Phiên hoạt động vẫn hữu ích nếu người dùng muốn liên kết dữ liệu và theo dõi dưới dạng một phần của phiên hoạt động thay vì được ghi liên tục.

Phiên giấc ngủ

Bạn có thể đọc hoặc ghi dữ liệu giấc ngủ trong Health Connect. Dữ liệu giấc ngủ được hiển thị dưới dạng một phiên hoạt động và có thể chia thành 8 giai đoạn ngủ riêng biệt:

  • UNKNOWN: Chưa xác định hoặc không xác định được người dùng có đang ngủ hay không.
  • AWAKE: Người dùng thức giấc (trong một chu kỳ ngủ, không phải ban ngày).
  • SLEEPING : Mô tả chung hoặc không chi tiết về giấc ngủ.
  • OUT_OF_BED : Người dùng ra khỏi giường vào giữa giấc ngủ.
  • AWAKE_IN_BED: Người dùng thức dậy trên giường.
  • LIGHT: Người dùng đang trong chu kỳ ngủ chập chờn.
  • DEEP: Người dùng đang trong chu kỳ ngủ sâu.
  • REM: Người dùng đang ở chu kỳ ngủ mắt chuyển động nhanh (REM).

Những giá trị này thể hiện chu kỳ giấc ngủ của người dùng trong một khoảng thời gian. Không bắt buộc ghi lại các giai đoạn ngủ, nhưng bạn nên ghi khi có thể.

Ghi phiên giấc ngủ có hoặc không có giai đoạn ngủ

Loại dữ liệu SleepSessionRecord gồm hai phần:

  1. Giấc ngủ tổng thể, kéo dài toàn bộ thời lượng giấc ngủ.
  2. Các giai đoạn riêng lẻ trong phiên giấc ngủ như giấc ngủ chập chờn hoặc sâu.

Dưới đây là cách bạn chèn một phiên giấc ngủ không có đủ giai đoạn ngủ:

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

Dưới đây là cách thêm các giai đoạn ngủ bao gồm toàn bộ một phiên một giấc ngủ:

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,
      )
  }

Đọc dữ liệu về phiên giấc ngủ

Đối với mỗi phiên giấc ngủ được trả về, bạn nên kiểm tra xem dữ liệu giai đoạn ngủ có hiện lên hay không:

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
    }
}

Xoá phiên giấc ngủ

Đây là cách xoá một phiên giấc ngủ. Trong ví dụ này, chúng tôi sử dụng phiên giấc ngủ:

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

Phiên hoạt động tập thể dục

Phiên hoạt động tập thể dục có thể gồm mọi hoạt động từ chạy bộ đến chơi cầu lông.

Ghi phiên hoạt động tập thể dục

Dưới đây là cách tạo yêu cầu chèn kèm theo dữ liệu trong phiên hoạt động:

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
        )
    )
}

Lưu ý: Trong ví dụ trước, cách bản ghi được thêm vào Distance, trong toàn bộ thời lượng của phiên hoạt động. Tuy nhiên, độ chi tiết của dữ liệu được thêm vào có thể khác nhau.

Nếu ứng dụng thường xuyên đo lường khoảng cách trong quá trình chạy, thì phương pháp khác sẽ bao gồm nhiều bản ghi Distance (Khoảng cách), mỗi bản ghi tương ứng với khoảng cách trong một phần chạy.

Đọc phiên hoạt động tập thể dục

Dưới đây là ví dụ về cách đọc một phiên hoạt động tập thể dục:

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
    }
}

Ghi dữ liệu loại phụ

Phiên hoạt động cũng có thể có dữ liệu loại phụ không bắt buộc, làm phiên phong phú thêm bằng thông tin bổ sung.

Ví dụ: các phiên hoạt động tập thể dục có thể có các lớp ExerciseSegment, ExerciseLapExerciseRoute:

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
)

Xoá phiên hoạt động tập thể dục

Có hai cách để xoá phiên hoạt động tập thể dục:

  1. Theo phạm vi thời gian.
  2. Bằng UID.

Dưới đây là cách xoá dữ liệu loại phụ theo phạm vi thời gian:

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)
}

Bạn cũng có thể xoá dữ liệu loại phụ bằng UID. Tuy nhiên, nếu làm như vậy, bạn sẽ chỉ xoá phiên hoạt động tập thể dục mà không xoá được dữ liệu liên quan:

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