Scrivi dati

Questa guida è compatibile con la versione 1.1.0-alpha12 di Connessione Salute.

Questa guida illustra la procedura di scrittura o aggiornamento dei dati in Connessione Salute.

Configura la struttura dei dati

Prima di scrivere i dati, dobbiamo configurare i record. Esistono più di 50 tipi di dati, ognuno con le rispettive strutture. Per ulteriori dettagli sui tipi di dati disponibili, consulta le Informazioni di riferimento di Jetpack.

Record di base

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

Il seguente esempio mostra come impostare i dati del conteggio dei passi:

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(15))

val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = ZoneOffset.UTC,
    endZoneOffset = ZoneOffset.UTC,
    metadata = Metadata.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    )
)

Record con unità di misura

Connessione Salute può memorizzare i valori insieme alle relative unità di misura per garantire la precisione. Un esempio è il tipo di dato Nutrizione, che è ampio e completo. Include un'ampia gamma di campi facoltativi per i nutrienti, che vanno dai carboidrati totali alle vitamine. Ogni punto dati rappresenta i nutrienti che sono stati potenzialmente consumati nell'ambito 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 una unità di Energy.

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

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(1))

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 = startTime,
    endTime = endTime,
    startZoneOffset = ZoneOffset.UTC,
    endZoneOffset = ZoneOffset.UTC,
    metadata = Metadata.manualEntry(
        device = Device(type = Device.TYPE_PHONE)
    )
)

Record con dati delle serie

Connessione Salute può memorizzare un elenco di dati delle serie. Un esempio è il tipo di dato Battito cardiaco che acquisisce una serie di campioni di battito cardiaco rilevati tra le letture.

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

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

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(5))

val heartRateRecord = HeartRateRecord(
    startTime = startTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = endTime,
    endZoneOffset = ZoneOffset.UTC,
    // records 10 arbitrary data, to replace with actual data
    samples = List(10) { index ->
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(index.toLong()),
            beatsPerMinute = 100 + index.toLong(),
        )
    },
    metadata = Metadata.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ))

Scrittura di dati

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

Il seguente esempio mostra come scrivere i conteggi dei passaggi di inserimento dei dati:

suspend fun insertSteps(healthConnectClient: HealthConnectClient) {
    val endTime = Instant.now()
    val startTime = endTime.minus(Duration.ofMinutes(5))
    try {
        val stepsRecord = StepsRecord(
            count = 120,
            startTime = startTime,
            endTime = endTime,
            startZoneOffset = ZoneOffset.UTC,
            endZoneOffset = ZoneOffset.UTC,
            metadata = Metadata.autoRecorded(
                device = Device(type = Device.TYPE_WATCH)
            )
        )
        healthConnectClient.insertRecords(listOf(stepsRecord))
    } catch (e: Exception) {
        // Run error handling here
    }
}

Aggiornare i dati

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

Metadati

Vale la pena esaminare prima la classe Metadata, poiché è necessaria per aggiornare i dati. Al momento della creazione, ogni Record in Connessione Salute ha un campo metadata. Le seguenti proprietà sono pertinenti alla sincronizzazione:

Proprietà Descrizione
id Ogni Record in Health Connect ha un valore id unico.
Connessione Salute compila automaticamente questo campo quando inserisci un nuovo record.
lastModifiedTime Ogni Record tiene traccia anche dell'ultima volta che il record è stato modificato.
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 contiene clientRecordId, il valore clientRecordVersion può essere utilizzato per consentire ai dati di rimanere sincronizzati con la versione nel datastore dell'app.
La tua app fornisce questo valore.

Aggiornamento tramite ID record

Per aggiornare i dati, prepara prima i record necessari. Apporta le modifiche necessarie ai record. Quindi, chiama updateRecords per apportare le modifiche.

Il seguente esempio mostra come aggiornare i dati. A questo scopo, i valori di offset della zona di ogni record vengono aggiustati 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)
        }

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

Upsert tramite ID record cliente

Se utilizzi i valori facoltativi ID record cliente e Versione record cliente, 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 cliente, vengono sovrascritti. In caso contrario, vengono scritti come nuovi dati. Questo scenario è utile ogni volta che devi sincronizzare i dati dal datastore dell'app a 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(
        metadata = Metadata.autoRecorded(
            clientRecordId = "Your client record ID",
            device = Device(type = Device.TYPE_WATCH)
        ),
        // Assign more parameters for this record
    )
    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 cliente

Se la procedura di inserimento dei dati include la versione del record del cliente, Connessione Salute esegue controlli di confronto nei valori clientRecordVersion. Se la versione dei dati inseriti è superiore alla versione dei dati esistenti, viene eseguito l'upsert. In caso contrario, il processo ignora la modifica e il valore rimane invariato.

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

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofMinutes(15))

val stepsRecord = StepsRecord(
    count = 100L,
    startTime = startTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = endTime,
    endZoneOffset = ZoneOffset.UTC,
    metadata = Metadata.manualEntry(
        clientRecordId = "Your supplied record ID",
        clientRecordVersion = 0L, // Your supplied record version
        device = Device(type = Device.TYPE_WATCH)
    )
)

Gli upsert non incrementano automaticamente version ogni volta che vengono apportate modifiche, evitando eventuali istanze impreviste di sovrascrittura dei dati. In questo caso, dovrai fornire manualmente un valore più elevato.

Best practice per la scrittura dei dati

Le app devono scrivere in Connessione Salute solo dati di proprietà propria.

Se i dati nella tua app sono stati importati da un'altra app, è responsabilità dell'altra app scrivere i propri dati in Connessione Salute.

È inoltre buona norma implementare una logica che gestisca le eccezioni di scrittura, ad esempio i dati fuori intervallo o un errore di sistema interno. Puoi applicare le tue strategie di backoff e di nuovo tentativo a un meccanismo di pianificazione dei job. Se la scrittura in Connessione Salute non va a buon fine, assicurati che la tua app possa superare questo punto di esportazione. Non dimenticare di registrare e segnalare gli errori per facilitare la diagnosi.

Quando monitori i dati, puoi seguire alcuni suggerimenti in base al modo in cui la tua app scrive i dati.

Monitoraggio passivo

Sono incluse le app che eseguono il monitoraggio passivo della salute o del fitness, ad esempio la registrazione continua dei passi o della frequenza cardiaca in background.

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

  • A ogni sincronizzazione, vengono scritti solo i nuovi dati e quelli aggiornati che sono stati modificati dall'ultima sincronizzazione.
  • Suddividi le richieste in blocchi di massimo 1000 record per richiesta di scrittura.
  • Utilizza WorkManager per pianificare attività in background periodiche, con un periodo di tempo di almeno 15 minuti.
  • Limita l'esecuzione delle attività solo quando il dispositivo è inattivo e la batteria non è in esaurimento.

    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 in base a eventi, come allenamento e sonno, o l'inserimento manuale da parte dell'utente, come l'alimentazione. Questi record vengono creati quando l'app è in primo piano o in rari casi in cui viene utilizzata alcune volte al giorno.

Assicurati che la tua app non mantenga Connessione Salute in esecuzione 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 monitorata.
  • Pianifica un'attività una tantum utilizzando WorkManager per sincronizzare i dati in un secondo momento.

Best practice per la granularità e la frequenza delle scritture

Quando scrivi dati in Connessione Salute, utilizza la risoluzione appropriata. L'utilizzo della risoluzione appropriata consente di ridurre il carico di archiviazione, mantenendo al contempo dati coerenti e accurati. La risoluzione dei dati comprende due aspetti:

  1. Frequenza delle scritture: la frequenza con cui la tua applicazione invia nuovi dati a Connessione Salute. Ad esempio, scrivi nuovi dati ogni 15 minuti.
  2. Granularità dei dati scritti: la frequenza con cui sono stati campionati i dati inviati. Ad esempio, scrivi i campioni della frequenza cardiaca 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 offre pochi vantaggi rispetto a una cadenza meno frequente, ad esempio ogni 60 secondi. Tuttavia, frequenze di campionamento più elevate possono offrire agli utenti un quadro più dettagliato e granulare dei loro dati relativi a salute e attività fisica. Le frequenze di campionamento devono trovare un equilibrio tra dettaglio e prestazioni.

Scrivere i dati monitorati durante il giorno

Per i dati raccolti in modo continuativo, come i passi, la tua applicazione deve scrivere in 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

Frequenza del passo

passi/min

Ogni minuto

23:14 - 23:15 - 5 spm

23:16 - 23:17 - 22 bpm

23:17 - 23:18 - 8 spm

Spinte in sedia a rotelle

spinte

Ogni minuto

23:14 - 23:15 - 5 push

23:16 - 23:17 - 22 push

23:17 - 23:18 - 8 push

ActiveCaloriesBurned

Calorie

Ogni 15 minuti

23:15 - 23:30 - 2 calorie

23:30 - 23:45 - 25 calorie

23:45 - 00:00 - 5 calorie

TotalCaloriesBurned

Calorie

Ogni 15 minuti

23:15 - 23:30 - 16 calorie

23:30 - 23:45 - 16 calorie

23:45 - 00:00 - 16 calorie

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

ElevationGained

m

Ogni minuto

20:36 - 20:37 - 3.048m

20:39 - 20:40 - 3.048m

23:23 - 23:24 - 9.144m

PianiClimbed

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

06:11 - 55 bpm

HeartRateVariabilityRmssd

ms

Ogni minuto

06:11 - 23 ms

RespiratoryRate

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

OxygenSaturation

%

Ogni ora

6:11 - 95,208%

Scrivere sessioni

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

Come best practice, qualsiasi sessione di sonno o esercizio fisico deve essere registrata con il dispositivo di registrazione e i metadati appropriati, inclusi RecordingMethod.

Come minimo, la tua applicazione deve seguire le indicazioni riportate nella colonna "Previsto" 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 1 secondo

23:14-23:15 - 5 passi

23:16 - 23:17 - 22 passi

23:17 - 23:18 - 8 passi

Frequenza del passo

passi/min

Ogni minuto

Ogni 1 secondo

23:14-23:15 - 35 spm

23:16 - 23:17 - 37 bpm

23:17 - 23:18 - 40 bpm

Spinte in sedia a rotelle

spinte

Ogni minuto

Ogni 1 secondo

23:14-23:15 - 5 push

23:16 - 23:17 - 22 push

23:17 - 23:18 - 8 push

CyclingPedalingCadence

rpm / respiri al minuto

Ogni minuto

Ogni 1 secondo

23:14-23:15 - 65 rpm

23:16 - 23:17 - 70 rpm

23:17 - 23:18 - 68 rpm

Potenza

watt

Ogni minuto

Ogni 1 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 1 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 1 secondo

23:14-23:15 - 0,008 km

23:16 - 23:16 - 0,021 km

23:17 - 23:18 - 0,012 km

ActiveCaloriesBurned

Calorie

Ogni minuto

Ogni 1 secondo

23:14-23:15 - 20 calorie

23:16 - 23:17 - 20 calorie

23:17 - 23:18 - 25 calorie

TotalCaloriesBurned

Calorie

Ogni minuto

Ogni 1 secondo

23:14-23:15 - 36 calorie

23:16 - 23:17 - 36 calorie

23:17 - 23:18 - 41 calorie

ElevationGained

m

Ogni minuto

Ogni 1 secondo

20:36 - 20:37 - 3.048m

20:39 - 20:40 - 3.048m

23:23 - 23:24 - 9.144m

PercorsiEsercizio

lat/lng/alt

Ogni 3-5 secondi

Ogni 1 secondo

Battito cardiaco

bpm

Ogni minuto

Ogni 1 secondo

23:14-23:15 - 150 bpm

23:16 - 23:17 -152 bpm

23:17 - 23:18 - 155 bpm

Dati monitorati durante il sonno

Tipo di dati

Unità

Campioni previsti

Esempio

Fasi 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

Un singolo valore giornaliero (previsto la mattina presto)

06:11 - 60 bpm

OxygenSaturation

%

Un singolo valore giornaliero (previsto la mattina presto)

6:11 - 95,208%