セッション数

ヘルスコネクトでのセッションとは、ユーザーがアクティビティを実行する期間です。SleepSessionRecord データ型と ExerciseSessionRecord データ型はどちらもセッションです。

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

ExerciseSessionRecord セッションには、ランニングからバドミントンまでさまざまなアクティビティが含まれます。

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

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

関連データは Record データで、個別または他のセッション(歩数、心拍数など)と一緒に読み取られます。

一般的なガイドライン

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

  • セッションは特定のワークアウトやアクティビティのデータ、または睡眠のデータを追加する場合に使用します。
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
            ),  
        )
    )
}
  • セッションは、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)
}

エクササイズ セッション

エクササイズ セッションには、ランニングからバドミントンまでさまざまなものがあります。

エクササイズ セッションを作成する

セッションを含む挿入リクエストの作成方法は以下のとおりです。

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 のレコードが追加されていますが、さまざまな粒度でデータを追加できます。

ランニング中にアプリで定期的に距離を測定していた場合には、複数の 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
)

エクササイズ セッションを削除する

エクササイズ セッションを削除する方法には次の 2 つがあります。

  1. 期間別
  2. 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()
    )
}