Questa guida è compatibile con la versione 1.1.0-alpha11 di Connessione Salute.
Connessione Salute fornisce un tipo di dato allenamento pianificato per consentire alle app di allenamento di scrivere piani di allenamento e alle app di allenamento di leggerli. Gli esercizi registrati (allenamenti) possono essere letti per un'analisi del rendimento personalizzata al fine di aiutare gli utenti a raggiungere i loro obiettivi di allenamento.
Disponibilità della funzionalità
Per determinare se il dispositivo di un utente supporta i piani di allenamento su Health Connect,
controlla la disponibilità di FEATURE_PLANNED_EXERCISE
sul client:
if (healthConnectClient
.features
.getFeatureStatus(
HealthConnectFeatures.FEATURE_PLANNED_EXERCISE
) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {
// Feature is available
} else {
// Feature isn't available
}
Per saperne di più, consulta Verificare la disponibilità delle funzionalità.
Autorizzazioni richieste
L'accesso ai piani di formazione è protetto dalle seguenti autorizzazioni:
android.permission.health.READ_PLANNED_EXERCISE
android.permission.health.WRITE_PLANNED_EXERCISE
Dichiara queste autorizzazioni in Play Console per la tua app, nonché nel file manifest dell'app:
<application>
<uses-permission
android:name="android.permission.health.READ_PLANNED_EXERCISE" />
<uses-permission
android:name="android.permission.health.WRITE_PLANNED_EXERCISE" />
...
</application>
Sei responsabile della dichiarazione di tutte le autorizzazioni appropriate che intendi utilizzare sui tuoi dispositivi e nelle tue app. Prima dell'utilizzo, devi anche verificare che ogni autorizzazione sia stata concessa dall'utente.
Autorizzazioni correlate
I piani di allenamento sono collegati alle sessioni di allenamento. Pertanto, per utilizzare completamente questa funzionalità di Connessione Salute, l'utente deve dare l'autorizzazione all'utilizzo di ogni tipo di record relativo a un piano di allenamento.
Ad esempio, se un piano di allenamento misura la frequenza cardiaca di un utente durante una serie di corse, lo sviluppatore potrebbe dover dichiarare le seguenti autorizzazioni e l'utente potrebbe doverle concedere per scrivere la sessione di allenamento e leggere i risultati per una valutazione successiva:
android.permission.health.READ_EXERCISE
android.permission.health.READ_EXERCISE_ROUTE
android.permission.health.READ_HEART_RATE
android.permission.health.WRITE_EXERCISE
android.permission.health.WRITE_EXERCISE_ROUTE
android.permission.health.WRITE_HEART_RATE
Tuttavia, spesso l'app che crea i piani di allenamento e valuta il rendimento rispetto ai piani non è la stessa che utilizza i piani di allenamento e scrive i dati effettivi dell'allenamento. A seconda del tipo di app, non sono necessarie tutte le autorizzazioni di lettura e scrittura. Ad esempio, potresti aver bisogno solo di queste autorizzazioni per ogni tipo di app:
App per i piani di allenamento | App Allenamento |
---|---|
WRITE_PLANNED_EXERCISE |
READ_PLANNED_EXERCISE |
READ_EXERCISE |
WRITE_EXERCISE |
READ_EXERCISE_ROUTE |
WRITE_EXERCISE_ROUTE |
READ_HEART_RATE |
WRITE_HEART_RATE |
Informazioni incluse in un record della sessione di allenamento pianificata
- Titolo della sessione.
- Un elenco di blocchi di esercizi pianificati.
- Ora di inizio e di fine della sessione.
- Tipo di esercizio.
- Note per l'attività.
- Metadati.
- ID sessione di allenamento completata: viene scritto automaticamente al termine di una sessione di allenamento correlata a questa sessione pianificata.
Informazioni incluse in un record del blocco di esercizi pianificato
Un blocco di esercizi pianificato contiene un elenco di passaggi di esercizi per supportare la ripetizione di diversi gruppi di passaggi (ad esempio, eseguire una sequenza di curl per i tricipiti, burpee e crunch cinque volte di seguito).
- Descrizione del blocco.
- Un elenco di passaggi dell'allenamento pianificato.
- Numero di ripetizioni.
Informazioni incluse in un record della fase di allenamento pianificata
- Descrizione del passaggio.
- Categoria di allenamento.
- Tipo di esercizio.
- Un elenco di obiettivi di rendimento.
- Obiettivo di completamento.
Aggregazioni supportate
Non sono supportate aggregazioni per questo tipo di dati.
Esempio di utilizzo
Supponiamo che un utente pianifichi una corsa di 90 minuti tra due giorni. Questa corsa prevede tre giri intorno a un lago con una frequenza cardiaca target compresa tra 90 e 110 bpm.
- Una sessione di allenamento pianificata con quanto segue è definita dall'utente in un'app di piano di allenamento:
- Inizio e fine pianificati dell'esecuzione
- Il tipo di esercizio (corsa)
- Numero di vasche (ripetizioni)
- Obiettivo di rendimento per il battito cardiaco (tra 90 e 110 bpm)
- Queste informazioni vengono raggruppate in blocchi di esercizi e passaggi e scritte in Connessione Salute dall'app del piano di allenamento come
PlannedExerciseSessionRecord
. - L'utente esegue la sessione pianificata (in esecuzione).
- I dati sull'allenamento relativi alla sessione vengono registrati:
- Da un dispositivo indossabile durante la sessione. Ad esempio, il battito cardiaco.
Questi dati vengono scritti in Connessione Salute come tipo di record per l'attività. In questo caso,
HeartRateRecord
. - Manualmente dall'utente dopo la sessione. Ad esempio, indicando
l'inizio e la fine dell'esecuzione effettiva. Questi dati vengono scritti in Connessione
Salute come
ExerciseSessionRecord
.
- Da un dispositivo indossabile durante la sessione. Ad esempio, il battito cardiaco.
Questi dati vengono scritti in Connessione Salute come tipo di record per l'attività. In questo caso,
- In un secondo momento, l'app del piano di allenamento legge i dati di Connessione Salute per valutare il rendimento effettivo rispetto ai target impostati dall'utente nella sessione di allenamento pianificata.
Pianificare gli esercizi e impostare i target
Un utente può pianificare l'allenamento in futuro e impostare obiettivi. Scrivi questa informazione in Connessione Salute come sessione di allenamento pianificata.
Nell'esempio descritto in Esempio di utilizzo, l'utente pianifica una corsa di 90 minuti tra due giorni. Questa corsa prevede tre giri intorno a un lago con un battito cardiaco target compreso tra 90 e 110 bpm.
Uno snippet come questo può essere trovato nel gestore dei moduli di un'app che registra le sessioni di allenamento pianificate in Connessione Salute. Potrebbe essere presente anche nel punto di importazione per le integrazioni, ad esempio con un servizio che offre formazione.
// Ensure the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(PlannedExerciseSessionRecord::class))) {
// The user hasn't granted the app permission to write planned exercise session data.
return
}
val plannedDuration = Duration.ofMinutes(90)
val plannedStartDate = LocalDate.now().plusDays(2)
val plannedExerciseSessionRecord = PlannedExerciseSessionRecord(
startDate = plannedStartDate,
duration = plannedDuration,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
blocks = listOf(
PlannedExerciseBlock(
repetitions = 1, steps = listOf(
PlannedExerciseStep(
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
exercisePhase = PlannedExerciseStep.EXERCISE_PHASE_ACTIVE,
completionGoal = ExerciseCompletionGoal.RepetitionsGoal(repetitions = 3),
performanceTargets = listOf(
ExercisePerformanceTarget.HeartRateTarget(
minHeartRate = 90.0, maxHeartRate = 110.0
)
)
),
), description = "Three laps around the lake"
)
),
title = "Run at lake",
notes = null
)
val insertedPlannedExerciseSessions =
healthConnectClient.insertRecords(listOf(plannedExerciseSessionRecord)).recordIdsList
val insertedPlannedExerciseSessionId = insertedPlannedExerciseSessions.first()
Registrare i dati relativi a esercizi e attività
Due giorni dopo, l'utente registra la sessione di allenamento effettiva. Scrivi questo dato in Connessione Salute come sessione di allenamento.
In questo esempio, la durata della sessione dell'utente corrisponde esattamente alla durata pianificata.
Il seguente snippet potrebbe essere trovato nell'handler dei moduli di un'app che registra le sessioni di allenamento in Connessione Salute. Potrebbe essere presente anche nei gestori di importazione ed esportazione dei dati per un dispositivo indossabile in grado di rilevare e registrare le sessioni di allenamento.
insertedPlannedExerciseSessionId
qui viene riutilizzato dall'esempio precedente. In un'app reale, l'ID viene determinato dall'utente che seleziona una sessione di esercizi pianificata da un elenco di sessioni esistenti.
// Ensure the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(ExerciseSessionRecord::class))) {
// The user doesn't granted the app permission to write exercise session data.
return
}
val sessionDuration = Duration.ofMinutes(90)
val sessionEndTime = Instant.now()
val sessionStartTime = sessionEndTime.minus(sessionDuration)
val exerciseSessionRecord = ExerciseSessionRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
segments = listOf(
ExerciseSegment(
startTime = sessionStartTime,
endTime = sessionEndTime,
repetitions = 3,
segmentType = ExerciseSegment.EXERCISE_SEGMENT_TYPE_RUNNING
)
),
title = "Run at lake",
plannedExerciseSessionId = insertedPlannedExerciseSessionId,
)
val insertedExerciseSessions =
healthConnectClient.insertRecords(listOf(exerciseSessionRecord))
Un wearable registra anche il battito cardiaco durante la corsa. Il seguente snippet potrebbe essere utilizzato per generare record nell'intervallo target.
In un'app reale, i componenti principali di questo snippet potrebbero trovarsi nell'handler per un messaggio di un dispositivo indossabile, che scriverebbe la misurazione in Connessione Salute al momento della raccolta.
// Ensure the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.contains(
HealthPermission.getWritePermission(HeartRateRecord::class))) {
// The user doesn't granted the app permission to write heart rate record data.
return
}
val samples = mutableListOf<HeartRateRecord.Sample>()
var currentTime = sessionStartTime
while (currentTime.isBefore(sessionEndTime)) {
val bpm = Random.nextInt(21) + 90
val heartRateRecord = HeartRateRecord.Sample(
time = currentTime,
beatsPerMinute = bpm.toLong(),
)
samples.add(heartRateRecord)
currentTime = currentTime.plusSeconds(180)
}
val heartRateRecord = HeartRateRecord(
startTime = sessionStartTime,
startZoneOffset = ZoneOffset.UTC,
endTime = sessionEndTime,
endZoneOffset = ZoneOffset.UTC,
samples = samples,
)
val insertedHeartRateRecords = healthConnectClient.insertRecords(listOf(heartRateRecord))
Valutare gli obiettivi di rendimento
Il giorno dopo l'allenamento dell'utente, puoi recuperare l'allenamento registrato, controllare eventuali target di allenamento pianificati e valutare altri tipi di dati per determinare se i target impostati sono stati raggiunti.
Uno snippet come questo potrebbe essere trovato in un job periodico per valutare i target di rendimento o quando carichi un elenco di esercizi e visualizzi una notifica relativa ai target di rendimento in un'app.
// Ensure the user has granted all necessary permissions for this task
val grantedPermissions =
healthConnectClient.permissionController.getGrantedPermissions()
if (!grantedPermissions.containsAll(
listOf(
HealthPermission.getReadPermission(ExerciseSessionRecord::class),
HealthPermission.getReadPermission(PlannedExerciseSessionRecord::class),
HealthPermission.getReadPermission(HeartRateRecord::class)
)
)
) {
// The user doesn't granted the app permission to read exercise session record data.
return
}
val searchDuration = Duration.ofDays(1)
val searchEndTime = Instant.now()
val searchStartTime = searchEndTime.minus(searchDuration)
val response = healthConnectClient.readRecords(
ReadRecordsRequest<ExerciseSessionRecord>(
timeRangeFilter = TimeRangeFilter.between(searchStartTime, searchEndTime)
)
)
for (exerciseRecord in response.records) {
val plannedExerciseRecordId = exerciseRecord.plannedExerciseSessionId
val plannedExerciseRecord =
if (plannedExerciseRecordId == null) null else healthConnectClient.readRecord(
PlannedExerciseSessionRecord::class, plannedExerciseRecordId
).record
if (plannedExerciseRecord != null) {
val aggregateRequest = AggregateRequest(
metrics = setOf(HeartRateRecord.BPM_AVG),
timeRangeFilter = TimeRangeFilter.between(
exerciseRecord.startTime, exerciseRecord.endTime
),
)
val aggregationResult = healthConnectClient.aggregate(aggregateRequest)
val maxBpm = aggregationResult[HeartRateRecord.BPM_MAX]
val minBpm = aggregationResult[HeartRateRecord.BPM_MIN]
if (maxBpm != null && minBpm != null) {
plannedExerciseRecord.blocks.forEach { block ->
block.steps.forEach { step ->
step.performanceTargets.forEach { target ->
when (target) {
is ExercisePerformanceTarget.HeartRateTarget -> {
val minTarget = target.minHeartRate
val maxTarget = target.maxHeartRate
if(
minBpm >= minTarget && maxBpm <= maxTarget
) {
// Success!
}
}
// Handle more target types
}
}
}
}
}
}
}
}