Scrittura di dati

Questa guida illustra il processo di scrittura o aggiornamento dei dati in Connessione Salute.

Configura la struttura dei dati

Prima di scrivere i dati, dobbiamo configurare i record. Per oltre 50 tipi di dati, ognuno ha le proprie strutture. Per ulteriori dettagli sui tipi di dati disponibili, consulta la documentazione di riferimento di Jetpack.

Record di base

Il tipo di dati Passi in Connessione Salute registra il numero di passi effettuati da un utente tra una lettura e l'altra. Il conteggio dei passi è una misurazione comune sulle piattaforme di salute, fitness e benessere.

L'esempio seguente mostra come impostare i dati per il conteggio dei passi:

val stepsRecord = StepsRecord(
    count = 120,
    startTime = START_TIME,
    endTime = END_TIME,
    startZoneOffset = START_ZONE_OFFSET,
    endZoneOffset = END_ZONE_OFFSET
)

Registrazione con unità di misura

Connessione Salute può archiviare i valori insieme alle relative unità di misura per fornire accuratezza. Un esempio è il tipo di dati Alimentazione, che è vasto e comprensivo. Include un'ampia varietà di campi nutritivi facoltativi, dai carboidrati totali alle vitamine. Ogni punto dati rappresenta le sostanze nutritive che sono state potenzialmente consumate come parte di un pasto o di un alimento.

In questo tipo di dati, tutti i nutrienti sono rappresentati in unità di Mass, mentre energy è rappresentato in un'unità di Energy.

L'esempio seguente mostra come impostare i dati nutrizionali di un utente che ha mangiato una banana:

val banana = NutritionRecord(
    name = "banana",
    energy = 105.0.kilocalories,
    dietaryFiber = 3.1.grams,
    potassium = 0.422.grams,
    totalCarbohydrate = 27.0.grams,
    totalFat = 0.4.grams,
    saturatedFat = 0.1.grams,
    sodium = 0.001.grams,
    sugar = 14.0.grams,
    vitaminB6 = 0.0005.grams,
    vitaminC = 0.0103.grams,
    startTime = START_TIME,
    endTime = END_TIME,
    startZoneOffset = START_ZONE_OFFSET,
    endZoneOffset = END_ZONE_OFFSET
)

Record con dati della serie

Connessione Salute può archiviare un elenco di dati delle serie. Un esempio è il tipo di dati Battito cardiaco, che acquisisce una serie di campioni di battito cardiaco rilevati tra una lettura e l'altra.

In questo tipo di dati, il parametro samples è rappresentato da un elenco di campioni del battito cardiaco. Ogni campione contiene un valore beatsPerMinute e un valore time.

L'esempio seguente mostra come impostare i dati delle serie del battito cardiaco:

val heartRateRecord = HeartRateRecord(
    startTime = START_TIME,
    startZoneOffset = START_ZONE_OFFSET,
    endTime = END_TIME,
    endZoneOffset = END_ZONE_OFFSET,
    // records 10 arbitrary data, to replace with actual data
    samples = List(10) { index ->
        HeartRateRecord.Sample(
            time = START_TIME + Duration.ofSeconds(index.toLong()),
            beatsPerMinute = 100 + index.toLong(),
        )
    }
)

Scrittura di dati

Uno dei flussi di lavoro comuni in Connessione Salute è la scrittura di dati. Per aggiungere record, utilizza insertRecords.

L'esempio seguente mostra come scrivere i conteggi di passaggi per l'inserimento di dati:

suspend fun insertSteps(healthConnectClient: HealthConnectClient) {
    try {
        val stepsRecord = StepsRecord(
            count = 120,
            startTime = START_TIME,
            endTime = END_TIME,
            startZoneOffset = START_ZONE_OFFSET,
            endZoneOffset = END_ZONE_OFFSET
        )
        healthConnectClient.insertRecords(listOf(stepsRecord))
    } catch (e: Exception) {
        // Run error handling here
    }
}

Aggiorna dati

Se devi modificare uno o più record, in particolare quando devi sincronizzare il datastore dell'app con i dati di Connessione Salute, puoi aggiornare i tuoi dati. Esistono due modi per aggiornare i dati esistenti, che dipendono dall'identificatore utilizzato per trovare i record.

Metadati

Consigliamo di esaminare prima il corso Metadata in quanto è necessario quando si aggiornano i dati. Al momento della creazione, ogni Record in Connessione Salute ha un campo metadata. Le seguenti proprietà sono pertinenti per la sincronizzazione:

Proprietà Descrizione
id Ogni Record in Connessione Salute ha un valore id univoco.
Connessione Salute compila automaticamente questo campo quando viene inserito un nuovo record.
lastModifiedTime Ogni Record tiene traccia anche dell'ultima modifica del record.
Connessione Salute compila automaticamente questo campo.
clientRecordId A ogni Record può essere associato un ID univoco da utilizzare come riferimento nel datastore dell'app.
La tua app fornisce questo valore.
clientRecordVersion Se un record ha clientRecordId, clientRecordVersion può essere utilizzato per consentire ai dati di rimanere sincronizzati con la versione nel datastore dell'app.
La tua app fornisce questo valore.

Aggiorna tramite Record ID

Per aggiornare i dati, prepara prima i record necessari. Se necessario, apporta eventuali modifiche ai record. Quindi, chiama updateRecords per apportare le modifiche.

L'esempio seguente mostra come aggiornare i dati. A questo scopo, ogni record ha i propri valori di offset di zona regolati in PST.

suspend fun updateSteps(
    healthConnectClient: HealthConnectClient,
    prevRecordStartTime: Instant,
    prevRecordEndTime: Instant
) {
    try {
        val request = healthConnectClient.readRecords(
            ReadRecordsRequest(
                recordType = StepsRecord::class,
                timeRangeFilter = TimeRangeFilter.between(
                    prevRecordStartTime,
                    prevRecordEndTime
                )
            )
        )

        val newStepsRecords = arrayListOf<StepsRecord>()
        for (record in request.records) {
            // Adjusted both offset values to reflect changes
            val sr = StepsRecord(
                count = record.count,
                startTime = record.startTime,
                startZoneOffset = record.startTime.atZone(ZoneId.of("PST")).offset,
                endTime = record.endTime,
                endZoneOffset = record.endTime.atZone(ZoneId.of("PST")).offset,
                metadata = record.metadata
            )
            newStepsRecords.add(sr)
        }

        client.updateRecords(newStepsRecords)
    } catch (e: Exception) {
        // Run error handling here
    }
}

Esegui upsert tramite ID record client

Se utilizzi i valori facoltativi ID record client e Versione record client, ti consigliamo di utilizzare insertRecords anziché updateRecords.

La funzione insertRecords è in grado di eseguire l'upsert dei dati. Se i dati esistono in Connessione Salute in base all'insieme specificato di ID record client, vengono sovrascritti. In caso contrario, vengono scritti come nuovi dati. Questo scenario è utile ogni volta che devi sincronizzare i dati del datastore dell'app con Connessione Salute.

L'esempio seguente mostra come eseguire un upsert sui dati estratti dal datastore dell'app:

suspend fun pullStepsFromDatastore() : ArrayList<StepsRecord> {
    val appStepsRecords = arrayListOf<StepsRecord>()
    // Pull data from app datastore
    // ...
    // Make changes to data if necessary
    // ...
    // Store data in appStepsRecords
    // ...
    var sr = StepsRecord(
        // Assign parameters for this record
        metadata = Metadata(
            clientRecordId = cid
        )
    )
    appStepsRecords.add(sr)
    // ...
    return appStepsRecords
}

suspend fun upsertSteps(
    healthConnectClient: HealthConnectClient,
    newStepsRecords: ArrayList<StepsRecord>
) {
    try {
        healthConnectClient.insertRecords(newStepsRecords)
    } catch (e: Exception) {
        // Run error handling here
    }
}

Dopodiché, puoi chiamare queste funzioni nel thread principale.

upsertSteps(healthConnectClient, pullStepsFromDatastore())

Controllo del valore nella versione del record client

Se il processo di upserting dei dati include la versione del record del client, Connessione Salute esegue controlli di confronto nei valori clientRecordVersion. Se la versione dei dati inseriti è superiore a quella dei dati esistenti, si verifica l'upsert. In caso contrario, il processo ignora la modifica e il valore rimane lo stesso.

Per includere il controllo delle versioni nei dati, devi fornire a Metadata.clientRecordVersion un valore Long in base alla logica di controllo delle versioni.

val sr = StepsRecord(
    count = count,
    startTime = startTime,
    startZoneOffset = startZoneOffset,
    endTime = endTime,
    endZoneOffset = endZoneOffset,
    metadata = Metadata(
        clientRecordId = cid,
        clientRecordVersion = version
    )
)

Gli upsert non incrementano automaticamente version ogni volta che vengono apportate modifiche, impedendo eventuali istanze impreviste di sovrascrittura dei dati. Devi quindi dargli manualmente un valore più alto.

Best practice per la scrittura dei dati

Le app devono scrivere in Connessione Salute solo dati provenienti dalla tua proprietà.

Se i dati nella tua app sono stati importati da un'altra app, la responsabilità di scrivere i propri dati in Connessione Salute ricade sull'altra app.

Inoltre, è una buona idea implementare una logica che gestisca le eccezioni di scrittura, ad esempio un errore di sistema interno o che i dati sono al di fuori dei limiti. Puoi applicare le strategie di backoff e di ripetizione a un meccanismo di pianificazione dei job. Se scrivere in Connessione Salute alla fine non va a buon fine, assicurati che la tua app possa andare oltre il punto di esportazione. Non dimenticare di registrare e segnalare gli errori per facilitare la diagnosi.

Per il monitoraggio dei dati, puoi seguire un paio di suggerimenti a seconda del modo in cui l'app scrive i dati.

Monitoraggio passivo

Sono incluse le app che eseguono il monitoraggio passivo o della salute, come la registrazione continua dei passi o del battito cardiaco in background.

La tua app deve scrivere periodicamente i dati in Connessione Salute nei seguenti modi:

  • A ogni sincronizzazione, scrivi solo i nuovi dati e i dati aggiornati che sono stati modificati dopo l'ultima sincronizzazione.
  • Richieste di chunk a un massimo di 1000 record per richiesta di scrittura.
  • Utilizza WorkManager per pianificare attività periodiche in background, con un periodo di tempo di almeno 15 minuti.
  • Limita l'esecuzione delle attività solo quando il dispositivo è inattivo e non ha la batteria scarica.

    val constraints = Constraints.Builder()
        .requiresBatteryNotLow()
        .requiresDeviceIdle(true)
        .build()
    
    val writeDataWork = PeriodicWorkRequestBuilder<WriteDataToHealthConnectWorker>(
            15,
            TimeUnit.MINUTES,
            5,
            TimeUnit.MINUTES
        )
        .setConstraints(constraints)
        .build()
    

Monitoraggio attivo

Sono incluse le app che eseguono il monitoraggio basato su eventi come allenamento e sonno, o input manuali dell'utente come l'alimentazione. Questi record vengono creati quando l'app è in primo piano o in rari eventi in cui viene utilizzata alcune volte al giorno.

Assicurati che l'app non tenga in esecuzione Connessione Salute per l'intera durata dell'evento.

I dati devono essere scritti in Connessione Salute in uno dei due modi seguenti:

  • Sincronizza i dati in Connessione Salute al termine dell'evento. Ad esempio, sincronizza i dati quando l'utente termina una sessione di allenamento rilevata.
  • Pianifica un'attività una tantum utilizzando WorkManager per sincronizzare i dati in un secondo momento.

Best practice per granularità e frequenza delle scritture

Quando scrivi dati in Connessione Salute, usa la risoluzione appropriata. Utilizzare la risoluzione appropriata aiuta a ridurre il carico di archiviazione, mantenendo al contempo dati coerenti e accurati. La risoluzione dei dati include due aspetti:

  1. Frequenza di scritture: la frequenza con cui l'applicazione invia nuovi dati a Connessione Salute. Ad esempio, scrivi nuovi dati ogni 15 minuti.
  2. Granularità dei dati scritti: frequenza con cui i dati inviati sono stati campionati. Ad esempio, scrivi campioni del battito cardiaco ogni 5 secondi. Non tutti i tipi di dati richiedono la stessa frequenza di campionamento. L'aggiornamento dei dati sul conteggio dei passi ogni secondo presenta un vantaggio minimo, rispetto a una cadenza meno frequente come ogni 60 secondi. Tuttavia, frequenze di campionamento più elevate possono offrire agli utenti una panoramica più dettagliata e dettagliata dei loro dati su salute e fitness. Le frequenze di campionamento devono trovare un equilibrio tra dettaglio e prestazioni.

Scrivere dati monitorati durante il giorno

Per i dati raccolti regolarmente, come i passaggi, l'applicazione dovrebbe scrivere a Connessione Salute almeno ogni 15 minuti durante il giorno.

Tipo di dati

Unità

Prevista

Esempio

Passi

passi

Ogni minuto

23:14 - 23:15 - 5 passi

23:16 - 23:17 - 22 passi

23:17 - 23:18 - 8 passi

Cadenza dei passi

passi/min

Ogni minuto

23:14 - 23:15 - 17:00

23:16 - 23:17 - 22 spm

23:17 - 23:18 - 20:00

Spinte in sedia a rotelle

push

Ogni minuto

23:14 - 23:15 - 5 spinte

23:16 - 23:17 - 22 spinte

23:17 - 23:18 - 8 spinte

Calorie bruciate in fase di attività

Calorie

Ogni 15 minuti

23:15 - 23:30 - 2 Calorie

23:30 - 23:45 - 25 Calorie

23:45 - 00:00 - 5 Calorie

TotaleCalorieBrute

kcal

Ogni 15 minuti

23:15 - 23:30 - 16 kcal

23:30 - 23:45 - 16 kcal

23:45 - 00:00 - 16 kcal

Distanza

km/min

Ogni minuto

23:14-23:15 - 0.008 km

23:16 - 23:16 - 0.021 km

23:17 - 23:18 - 0.012 km

Dislivello

M

Ogni minuto

20:36 - 20:37 - 3,048 m

20:39 - 20:40 - 3,048 m

23:23 - 23:24 - 9,144 m

Piani saliti

piani

Ogni minuto

23:14 - 23:15 - 5 piani

23:16 - 23:16 - 22 piani

23:17 - 23:18 - 8 piani

Battito cardiaco

bpm

Ogni minuto

6:11 - 55 b/m

Variabilità della frequenza cardiaca (HRmssd)

ms

Ogni minuto

6:11 - 23 ms

Frequenza respiratoria

respiri/minuto

Ogni minuto

23:14 - 23:15 - 60 respiri/minuto

23:16 - 23:16 - 62 respiri/minuto

23:17 - 23:18 - 64 respiri/minuto

Saturazione ossigeno

%

Ogni ora

6:11 - 95,208%

Scrittura delle sessioni

I dati devono essere scritti in Connessione Salute al termine dell'esercizio o della sessione di sonno.

Come best practice, qualsiasi sessione di sonno o allenamento deve essere scritta con il dispositivo di registrazione e i metadati appropriati, tra cui RecordingMethod.

La tua richiesta deve seguire almeno le indicazioni riportate nella colonna "Prevista" di seguito. Ove possibile, segui le indicazioni "migliori".

Dati rilevati durante un allenamento

Tipo di dati

Unità

Prevista

Cordiali saluti,

Esempio

Passi

passi

Ogni minuto

Ogni secondo

23:14-23:15 - 5 passi

23:16 - 23:17 - 22 passi

23:17 - 23:18 - 8 passi

Cadenza dei passi

passi/min

Ogni minuto

Ogni secondo

23:14-23:15 - 35 spm

23:16 - 23:17 - 37 spm

23:17 - 23:18 - 40 spm

Spinte in sedia a rotelle

push

Ogni minuto

Ogni secondo

23:14-23:15 - 5 spinte

23:16 - 23:17 - 22 spinte

23:17 - 23:18 - 8 spinte

CiclismoPedalingCadence

rpm / respiri al minuto

Ogni minuto

Ogni secondo

23:14-23:15 - 65 giri/min

23:16 - 23:17 - 70 giri/min

23:17 - 23:18 - 68 giri/min

Potenza

watt

Ogni minuto

Ogni secondo

23:14-23:15 - 250 watt

23:16 - 23:17 - 255 watt

23:17 - 23:18 - 245 watt

Velocità

km/min

Ogni minuto

Ogni secondo

23:14-23:15 - 0.3 km/min

23:16 - 23:17 - 0.4 km/min

23:17 - 23:18 -0,4 km/min

Distanza

km/m

Ogni minuto

Ogni secondo

23:14-23:15 - 0.008 km

23:16 - 23:16 - 0.021 km

23:17 - 23:18 - 0.012 km

Calorie bruciate in fase di attività

kcal

Ogni minuto

Ogni secondo

23:14-23:15 - 20 kcal

23:16 - 23:17 - 20 kcal

23:17 - 23:18 - 25 kcals

TotaleCalorieBrute

kcal

Ogni minuto

Ogni secondo

23:14-23:15 - 36 kcals

23:16 - 23:17 - 36 kcals

23:17 - 23:18 - 41 kcals

Dislivello

M

Ogni minuto

Ogni secondo

20:36 - 20:37 - 3,048 m

20:39 - 20:40 - 3,048 m

23:23 - 23:24 - 9,144 m

Percorsi allenamento

lat/lng/alt

Ogni 3-5 secondi

Ogni secondo

Battito cardiaco

bpm

Ogni minuto

Ogni secondo

23:14-23:15 - 150 b/m

23:16 - 23:17 -152 bpm

23:17 - 23:18 - 155 bpm

Dati rilevati durante il sonno

Tipo di dati

Unità

Campioni previsti

Esempio

Preparazione del sonno

fase

Periodo di tempo granulare per fase del sonno

23:46 - 23:50 - sveglio

23:50 - 23:56 - sonno leggero

23:56 - 00:16 - sonno profondo

Battito cardiaco a riposo

bpm

Singolo valore giornaliero (previsto come prima cosa al mattino)

06:11 - 60 b/m

Saturazione ossigeno

%

Singolo valore giornaliero (previsto come prima cosa al mattino)

6:11 - 95,208%