Theo dõi các phiên giấc ngủ

Hướng dẫn này tương thích với Health Connect phiên bản 1.1.0-alpha11.

Health Connect cung cấp một loại dữ liệu phiên ngủ để lưu trữ thông tin về giấc ngủ của người dùng, chẳng hạn như phiên ngủ vào ban đêm hoặc giấc ngủ ngắn vào ban ngày. Kiểu dữ liệu SleepSessionRecord được dùng để biểu thị các phiên này.

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 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ủ.

Kiểm tra phạm vi sử dụng Health Connect

Trước khi cố gắng sử dụng Health Connect, ứng dụng của bạn phải xác minh rằng Health Connect có trên thiết bị của người dùng. Health Connect có thể chưa được cài đặt sẵn trên một số thiết bị hoặc có thể đã bị tắt. Bạn có thể kiểm tra phạm vi cung cấp bằng phương thức HealthConnectClient.getSdkStatus().

Cách kiểm tra phạm vi sử dụng Health Connect

fun checkHealthConnectAvailability(context: Context) {
    val providerPackageName = "com.google.android.apps.healthdata" // Or get from HealthConnectClient.DEFAULT_PROVIDER_PACKAGE_NAME
    val availabilityStatus = HealthConnectClient.getSdkStatus(context, providerPackageName)

    if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE) {
      // Health Connect is not available. Guide the user to install/enable it.
      // For example, show a dialog.
      return // early return as there is no viable integration
    }
    if (availabilityStatus == HealthConnectClient.SDK_UNAVAILABLE_PROVIDER_UPDATE_REQUIRED) {
      // Health Connect is available but requires an update.
      // Optionally redirect to package installer to find a provider, for example:
      val uriString = "market://details?id=$providerPackageName&url=healthconnect%3A%2F%2Fonboarding"
      context.startActivity(
        Intent(Intent.ACTION_VIEW).apply {
          setPackage("com.android.vending")
          data = Uri.parse(uriString)
          putExtra("overlay", true)
          putExtra("callerId", context.packageName)
        }
      )
      return
    }
    // Health Connect is available, obtain a HealthConnectClient instance
    val healthConnectClient = HealthConnectClient.getOrCreate(context)
    // Issue operations with healthConnectClient
}

Tuỳ thuộc vào trạng thái mà getSdkStatus() trả về, bạn có thể hướng dẫn người dùng cài đặt hoặc cập nhật Health Connect từ Cửa hàng Google Play nếu cần.

Phạm vi cung cấp tính năng

Không có cờ về tính năng cho kiểu dữ liệu này.

Các quyền bắt buộc

Quyền truy cập vào phiên ngủ được bảo vệ bằng các quyền sau:

  • android.permission.health.READ_SLEEP
  • android.permission.health.WRITE_SLEEP

Để thêm chức năng phiên ngủ vào ứng dụng của bạn, hãy bắt đầu bằng cách yêu cầu quyền ghi cho kiểu dữ liệu SleepSession.

Dưới đây là quyền bạn cần khai báo để có thể ghi phiên ngủ:

<application>
  <uses-permission
android:name="android.permission.health.WRITE_SLEEP" />
...
</application>

Để đọc phiên ngủ, bạn cần yêu cầu các quyền sau:

<application>
  <uses-permission
android:name="android.permission.health.READ_SLEEP" />
...
</application>

Yêu cầu người dùng cấp quyền

Sau khi tạo một phiên bản ứng dụng, ứng dụng của bạn cần yêu cầu người dùng cấp quyền. Người dùng phải được phép cấp hoặc từ chối cấp quyền bất cứ lúc nào.

Để thực hiện việc này, hãy tạo một tập hợp quyền cho các kiểu dữ liệu bắt buộc. Trước tiên, bạn cần khai báo các quyền trong tập hợp này ở tệp kê khai Android.

// Create a set of permissions for required data types
val PERMISSIONS =
    setOf(
  HealthPermission.getReadPermission(SleepSessionRecord::class),
  HealthPermission.getWritePermission(SleepSessionRecord::class)
)

Hãy sử dụng getGrantedPermissions để xem ứng dụng của bạn đã được cấp các quyền cần thiết chưa. Nếu chưa, hãy sử dụng createRequestPermissionResultContract để yêu cầu các quyền đó. Thao tác này sẽ hiện màn hình các quyền của 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)
  }
}

Vì người dùng có thể cấp hoặc thu hồi quyền bất cứ lúc nào, nên ứng dụng của bạn cần kiểm tra định kỳ các quyền đã cấp và xử lý các tình huống khi mất quyền.

Các phép tổng hợp được hỗ trợ

Bạn có thể sử dụng các giá trị tổng hợp sau đây cho SleepSessionRecord:

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 ngủ trong Health Connect.

  • Bạn nên sử dụng phiên hoạt động để thêm dữ liệu từ một phiên giấc ngủ cụ thể, cho giấc ngủ:
suspend fun writeSleepSession(healthConnectClient: HealthConnectClient) {
    healthConnectClient.insertRecords(
        listOf(
            SleepSessionRecord(
                startTime = Instant.parse("2022-05-10T23:00:00.000Z"),
                startZoneOffset = ZoneOffset.of("-08:00"),
                endTime = Instant.parse("2022-05-11T07:00:00.000Z"),
                endZoneOffset = ZoneOffset.of("-08:00"),
                title = "My Sleep"
            ),
        )
    )
}
  • 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ủ

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