Sitzungen

In Health Connect ist eine Sitzung ein Zeitintervall, in dem ein Nutzer eine Aktivität ausführt. Die Datentypen SleepSessionRecord und ExerciseSessionRecord sind beide Sitzungen.

Sitzungen ermöglichen es Nutzern, die zeitbasierte Leistung über einen bestimmten Zeitraum zu messen, z. B. kontinuierliche Herzfrequenz oder Standortdaten.

ExerciseSessionRecord-Trainingseinheiten umfassen eine Vielzahl von Aktivitäten, von Laufen bis Badminton.

SleepSessionRecord-Sitzungen enthalten Daten, in denen Schlafphasen aufgezeichnet werden, z. B. AWAKE, SLEEPING und DEEP.

Untertypdaten sind Daten, die zu einer Sitzung gehören und nur dann aussagekräftig sind, wenn sie mit einer übergeordneten Sitzung gelesen werden, z.B. die Schlafphase oder das Trainingssegment.

Verknüpfte Daten: Record-Daten können separat oder zusammen mit anderen Sitzungen gelesen werden, z.B. Schritte und Herzfrequenz.

Allgemeine Anleitung

Hier sind einige Best Practice-Richtlinien für die Arbeit mit Sitzungen in Health Connect.

  • Sitzungen sollten verwendet werden, um Daten eines bestimmten Trainings oder einer bestimmten Aktivität hinzuzufügen oder um zu schlafen:
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
            ),  
        )
    )
}
  • Sitzungen sollten nicht für allgemeine Messungen wie die tägliche Schrittzahl verwendet werden.
  • Subtypdaten enthalten keine UID, aber die zugehörigen Daten haben unterschiedliche UIDs.
  • Untertypdaten müssen in einer Sitzung mit sequenziellen Zeitstempeln ausgerichtet werden, die sich nicht überschneiden. Lücken sind jedoch zulässig.
  • Sitzungen sind nützlich, wenn der Nutzer möchte, dass Daten mit einer Sitzung verknüpft (und als Teil dieser erfasst) werden, anstatt kontinuierlich zu erfassen.

Schlafeinheiten

Du kannst Schlafdaten in Health Connect lesen oder schreiben. Schlafdaten werden als Sitzung angezeigt und lassen sich in 8 verschiedene Schlafphasen unterteilen:

  • UNKNOWN: Nicht angegeben oder unbekannt, wenn der Nutzer schläft.
  • AWAKE: Der Nutzer ist innerhalb eines Schlafzyklus wach, nicht tagsüber.
  • SLEEPING: allgemeine oder nicht detaillierte Schlafbeschreibung.
  • OUT_OF_BED: Der Nutzer steht mitten im Schlaf auf.
  • AWAKE_IN_BED: Der Nutzer ist wach im Bett.
  • LIGHT: Der Nutzer befindet sich in einem Leichtschlafzyklus.
  • DEEP: Der Nutzer befindet sich im Tiefschlafzyklus.
  • REM: Der Nutzer befindet sich in einem REM-Schlaf.

Diese Werte geben die Art des Schlafs an, den Nutzende innerhalb eines bestimmten Zeitraums erleben. Das Aufschreiben von Schlafphasen ist optional, wird aber empfohlen, sofern verfügbar.

Schlafeinheiten mit oder ohne Schlafphasen schreiben

Der Datentyp SleepSessionRecord besteht aus zwei Teilen:

  1. Die gesamte Sitzung, die die gesamte Schlafdauer umfasst.
  2. Einzelne Schlafphasen, wie der Leicht- oder Tiefschlaf.

So fügst du eine Schlafeinheit ohne Phasen ein:

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

So fügst du Phasen hinzu, die die gesamte Dauer einer Schlafeinheit abdecken:

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

Schlafeinheit lesen

Für jede zurückgegebene Schlafeinheit solltest du prüfen, ob auch Daten zu Schlafphasen vorhanden sind:

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

Schlafaufzeichnung löschen

So löschst du eine Sitzung. In diesem Beispiel haben wir eine Schlafeinheit verwendet:

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

Trainingseinheiten

Trainingseinheiten können alles von Laufen bis Badminton umfassen.

Übungseinheiten schreiben

So erstellen Sie eine Anzeigenauftragsanfrage, die eine Sitzung enthält:

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

Im vorherigen Beispiel wird ein Eintrag für Distance hinzugefügt, der die gesamte Dauer der Sitzung abdeckt. Daten können jedoch mit unterschiedlichem Detaillierungsgrad hinzugefügt werden.

Wenn die App während des Laufs regelmäßig die Entfernungen gemessen hätte, wäre ein anderer Ansatz, viele Distance-Datensätze einzubeziehen, die jeweils die in einem Teil des Laufs zurückgelegte Strecke darstellen.

Trainingseinheit lesen

Hier ist ein Beispiel dafür, wie eine Trainingseinheit zu lesen ist:

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

Untertypdaten schreiben

Sitzungen können auch aus nicht obligatorischen Untertypdaten bestehen, die die Sitzung mit zusätzlichen Informationen anreichern.

Trainingseinheiten können beispielsweise die Klassen ExerciseSegment, ExerciseLap und ExerciseRoute umfassen:

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
)

Trainingseinheit löschen

Es gibt zwei Möglichkeiten, eine Trainingseinheit zu löschen:

  1. Nach Zeitraum.
  2. Nach UID.

So löschen Sie Untertypdaten nach Zeitraum:

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

Sie können Untertypdaten auch nach UID löschen. Dadurch wird jedoch nur die Trainingseinheit gelöscht, nicht die zugehörigen Daten:

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