睡眠セッションを記録する

このガイドは、Health Connect バージョン 1.1.0-alpha11 に対応しています。

ヘルスコネクトは、睡眠セッションのデータ型を提供し、ユーザーの睡眠に関する情報(夜間の睡眠や昼間の昼寝など)を保存します。これらのセッションを表すために SleepSessionRecord データ型が使用されます。

セッションにより、ユーザーは継続的な心拍数や位置情報など、時間ベースのパフォーマンスを一定期間にわたり測定できます。

SleepSessionRecord セッションには、睡眠ステージを記録するデータ(AWAKESLEEPINGDEEP など)が含まれます。

サブタイプ データはセッションに「属する」データで、親セッションと一緒に読み取られた場合にのみ意味のあるデータとなります。たとえば、睡眠ステージなどです。

ヘルスコネクトの可用性を確認する

ヘルスコネクトを使用する前に、アプリはユーザーのデバイスでヘルスコネクトが利用可能であることを確認する必要があります。ヘルスコネクトは、一部のデバイスにプリインストールされていない場合や、無効になっている場合があります。HealthConnectClient.getSdkStatus() メソッドを使用して、利用可能かどうかを確認できます。

ヘルスコネクトの可用性を確認する方法

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
}

getSdkStatus() から返されたステータスに応じて、必要に応じて Google Play ストアからヘルスコネクトをインストールまたは更新するようユーザーに案内できます。

機能の提供状況

このデータ型には機能の可用性フラグがありません。

必要な権限

睡眠セッションへのアクセスは、次の権限によって保護されています。

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

getGrantedPermissions を使用して、アプリが必要な権限をすでに持っているかどうかを確認します。持っていない場合は、createRequestPermissionResultContract を使用して権限をリクエストします。ヘルスコネクトの権限画面が表示されます。

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

ユーザーはいつでも権限を付与または取り消すことができるため、アプリは許可されている権限を定期的に確認し、権限がなくなっている場合に対処できるようにする必要があります。

サポートされている集計

SleepSessionRecord で使用できる集計値は次のとおりです。

一般的なガイドライン

以下はヘルスコネクトで睡眠セッションを使用する際のベスト プラクティスです。

  • セッションは特定の睡眠セッションのデータ、または睡眠のデータを追加する場合に使用します。
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"
            ),
        )
    )
}
  • セッションは、1 日の歩数などの一般的な測定には使用しないでください。
  • サブタイプ データには UID は含まれていませんが、関連データには区別できる UID が含まれています。
  • サブタイプ データはセッションの重複していない連続したタイムスタンプに沿っている必要があります。ただし、空白期間は許容されます。
  • セッションはデータを連続して記録するのではなく、データをセッションに関連付ける(およびセッションの一部としてトラッキングする)場合に便利です。

睡眠セッション

ヘルスコネクトで睡眠データの読み取りと書き込みができます。睡眠データはセッションとして表示され、8 つの異なる睡眠ステージに分類できます。

  • UNKNOWN: 未指定、または眠っているかどうか不明な状態。
  • AWAKE: 日中ではない睡眠サイクル中に起きている状態。
  • SLEEPING: 細かく分類されていない一般的な睡眠の状態。
  • OUT_OF_BED: 睡眠セッションの途中でベッドから出た状態。
  • AWAKE_IN_BED: ベッドの中で起きている状態。
  • LIGHT: 浅い睡眠サイクルに入っている状態。
  • DEEP: 深い睡眠サイクルに入っている状態。
  • REM: レム睡眠サイクルに入っている状態。

これらの値は一定期間内にユーザーがどのような睡眠状態にあったのかを表しています。睡眠ステージの作成は任意ですが、可能であれば作成することをおすすめします。

睡眠セッションを書き込む

SleepSessionRecord データ型には 2 つの要素があります。

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