Sessioni

In Connessione Salute, una sessione è un intervallo di tempo durante il quale un utente esegue un'attività. I tipi di dati SleepSessionRecord e ExerciseSessionRecord sono entrambi sessioni.

Le sessioni consentono agli utenti di misurare le prestazioni basate sul tempo su un determinato periodo di tempo, ad esempio i dati sulla posizione o il battito cardiaco continui.

Le sessioni ExerciseSessionRecord includono una serie di attività, dalla corsa al badminton.

Le sessioni SleepSessionRecord contengono dati che registrano le fasi del sonno, come AWAKE, SLEEPING e DEEP.

I dati di sottotipo sono dati che "appartengono" a una sessione e sono significativi solo quando vengono letti con una sessione genitore, ad esempio fase del sonno o segmento di allenamento.

I dati associati si riferiscono a Record che possono essere letti separatamente o insieme ad altre sessioni, ad esempio passi e frequenza cardiaca.

Indicazioni generali

Ecco alcune linee guida sulle best practice su come gestire le sessioni in Connessione Salute.

  • Le sessioni devono essere utilizzate per aggiungere dati di un esercizio o un'attività specifica, oppure per il sonno:
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
            ),  
        )
    )
}
  • Le sessioni non devono essere utilizzate per misurazioni generali, come il conteggio dei passi giornaliero.
  • I dati di sottotipo non contengono un UID, ma i dati associati hanno UID distinti.
  • I dati di sottotipo devono essere allineati in una sessione con timestamp sequenziali che non si sovrappongono. Tuttavia, gli intervalli vuoti sono consentiti.
  • Le sessioni sono utili se l'utente desidera che i dati vengano associati a (e monitorati come parte di) una sessione, anziché essere registrati continuamente.

Sessioni di sonno

Puoi leggere o scrivere dati relativi al sonno in Connessione Salute. I dati sul sonno vengono visualizzati come sessione e possono essere suddivisi in 8 diverse fasi del sonno:

  • UNKNOWN: valore non specificato o sconosciuto se l'utente sta dormendo.
  • AWAKE: l'utente è sveglio durante un ciclo del sonno, non durante il giorno.
  • SLEEPING: descrizione generica o non granulare del sonno.
  • OUT_OF_BED: l'utente si alza dal letto durante una sessione di sonno.
  • AWAKE_IN_BED: l'utente è sveglio nel letto.
  • LIGHT: l'utente si trova in un ciclo di sonno leggero.
  • DEEP: l'utente si trova in un ciclo di sonno profondo.
  • REM: l'utente si trova in un ciclo di sonno REM.

Questi valori rappresentano il tipo di sonno che un utente prova in un intervallo di tempo. Scrivere le fasi del sonno è facoltativa, ma consigliata se disponibile.

Scrittura delle sessioni di sonno con o senza fasi del sonno

Il tipo di dati SleepSessionRecord è costituito da due parti:

  1. La sessione complessiva, che copre l'intera durata del sonno.
  2. Singoli fasi durante la sessione di sonno, come sonno leggero o sonno profondo.

Ecco come inserire una sessione di sonno senza fasi:

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

Ecco come aggiungere fasi che coprono l'intero periodo di una sessione di sonno:

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

Lettura di una sessione di sonno

Per ogni sessione di sonno restituita, devi controllare se sono presenti anche i dati sulla fase del sonno:

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

Eliminare una sessione di sonno

Ecco come eliminare una sessione. Per questo esempio, abbiamo utilizzato una sessione di sonno:

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

Sessioni di allenamento

Le sessioni di allenamento possono includere qualsiasi attività, dalla corsa al badminton.

Scrittura delle sessioni di allenamento

Ecco come creare una richiesta di inserzione che include una sessione:

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

Nota come nell'esempio precedente viene aggiunto un record per Distance, che copre l'intera durata della sessione, ma i dati possono essere aggiunti con granularità diversa.

Se l'app misurasse regolarmente la distanza durante l'esecuzione, un altro approccio sarebbe includere molti record sulla distanza, ciascuno dei quali rappresenta la distanza percorsa in una parte dell'esecuzione.

Lettura di una sessione di allenamento

Di seguito è riportato un esempio di come leggere una sessione di allenamento:

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

Scrivere dati di sottotipo

Le sessioni possono anche essere composte da dati di sottotipo non obbligatori, che arricchiscono la sessione con informazioni aggiuntive.

Ad esempio, le sessioni di allenamento possono includere i corsi ExerciseSegment, ExerciseLap e 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
)

Eliminare una sessione di allenamento

Esistono due modi per eliminare una sessione di allenamento:

  1. Per intervallo di tempo.
  2. Tramite UID.

Per eliminare i dati di sottotipo in base all'intervallo di tempo, procedi nel seguente modo:

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

Puoi anche eliminare i dati del sottotipo in base all'UID. Tuttavia, così facendo, eliminerai solo la sessione di allenamento, non i dati associati:

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