Daten schreiben

Diese Anleitung ist mit Health Connect-Version 1.1.0-alpha12 oder höher kompatibel.

In diesem Leitfaden wird beschrieben, wie Daten in Health Connect geschrieben oder aktualisiert werden.

Umgang mit Nullwerten

Einige Datentypen wie Schritte, Entfernung oder Kalorien können den Wert 0 haben. Schreibe nur dann Nullwerte, wenn der Nutzer das Gerät getragen hat und tatsächlich inaktiv war. Schreibe keine Nullwerte, wenn das Gerät nicht getragen wurde, Daten fehlen oder der Akku leer war. Lassen Sie in solchen Fällen den Datensatz weg, um irreführende Daten zu vermeiden.

Datenstruktur einrichten

Bevor wir Daten schreiben können, müssen wir zuerst die Datensätze einrichten. Für mehr als 50 Datentypen mit jeweils eigenen Strukturen. Weitere Informationen zu den verfügbaren Datentypen finden Sie in der Jetpack-Referenz.

Grundlegende Datensätze

Der Datentyp Schritte in Health Connect erfasst die Anzahl der Schritte, die ein Nutzer zwischen den Messungen zurückgelegt hat. Die Schrittzahl ist ein gängiger Messwert auf Gesundheits-, Fitness- und Wellnessplattformen.

Im folgenden Beispiel wird gezeigt, wie Daten zur Schrittzahl festgelegt werden:

val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime)
val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = zoneOffset,
    endZoneOffset = zoneOffset,
    metadata = Metadata.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    )
)
healthConnectClient.insertRecords(listOf(stepsRecord))

Datensätze mit Maßeinheiten

Health Connect kann Werte zusammen mit ihren Maßeinheiten speichern, um die Genauigkeit zu gewährleisten. Ein Beispiel ist der Datentyp Ernährung, der sehr umfangreich ist. Sie enthält eine Vielzahl optionaler Nährstofffelder, von Gesamtkohlenhydraten bis hin zu Vitaminen. Jeder Datenpunkt steht für die Nährstoffe, die potenziell im Rahmen einer Mahlzeit oder eines Lebensmittels konsumiert wurden.

In diesem Datentyp werden alle Nährstoffe in Einheiten von Masse dargestellt, während energy in einer Einheit von Energie dargestellt wird.

Das folgende Beispiel zeigt, wie Ernährungsdaten für einen Nutzer festgelegt werden, der eine Banane gegessen hat:

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.activelyRecorded(
        device = Device(type = Device.TYPE_PHONE)
    )
)

Einträge mit Seriendaten

In Health Connect kann eine Liste mit Datenreihen gespeichert werden. Ein Beispiel ist der Datentyp Herzfrequenz, der eine Reihe von Herzfrequenzmessungen zwischen den Messwerten erfasst.

In diesem Datentyp wird der Parameter samples durch eine Liste von Herzfrequenz-Stichproben dargestellt. Jede Stichprobe enthält einen beatsPerMinute-Wert und einen time-Wert.

Im folgenden Beispiel wird gezeigt, wie Daten für Herzfrequenzreihen festgelegt werden:

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.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ))

Berechtigungen vom Nutzer anfordern

Nachdem Sie eine Clientinstanz erstellt haben, muss Ihre App Berechtigungen vom Nutzer anfordern. Nutzer müssen Berechtigungen jederzeit erteilen oder verweigern können. Erstellen Sie dazu eine Reihe von Berechtigungen für die erforderlichen Datentypen. Achte darauf, dass die Berechtigungen in der Gruppe zuerst in deinem Android-Manifest deklariert werden.

val permissions =
    setOf(
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class),
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class)
    )
Mit getGrantedPermissions kannst du prüfen, ob deiner App bereits die erforderlichen Berechtigungen gewährt wurden. Falls nicht, verwenden Sie createRequestPermissionResultContract, um diese Berechtigungen anzufordern. Der Bildschirm mit den Health Connect-Berechtigungen wird angezeigt.
val permissions = setOf(
        HealthPermission.getReadPermission(StepsRecord::class),
        HealthPermission.getWritePermission(StepsRecord::class),
        HealthPermission.getReadPermission(HeartRateRecord::class),
        HealthPermission.getWritePermission(HeartRateRecord::class)
    )

val requestPermissionsLauncher = rememberLauncherForActivityResult(
    contract = PermissionController.createRequestPermissionResultContract()
) { grantedPermissions ->
    if (grantedPermissions.containsAll(permissions)) {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions granted!") }
    } else {
        coroutineScope.launch { snackbarHostState.showSnackbar("Permissions denied.") }
    }
}
Da Nutzer Berechtigungen jederzeit erteilen oder widerrufen können, muss deine App vor jeder Verwendung prüfen, ob die Berechtigungen vorhanden sind, und Szenarien verarbeiten, in denen die Berechtigung verloren geht.

Daten schreiben

Einer der gängigen Workflows in Health Connect ist das Schreiben von Daten. Verwenden Sie insertRecords, um Einträge hinzuzufügen.

Das folgende Beispiel zeigt, wie Daten zum Einfügen von Schrittzahlen geschrieben werden:

val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime)
val stepsRecord = StepsRecord(
    count = 120,
    startTime = startTime,
    endTime = endTime,
    startZoneOffset = zoneOffset,
    endZoneOffset = zoneOffset,
    metadata = Metadata.autoRecorded(
        device = Device(type = Device.TYPE_WATCH)
    )
)
healthConnectClient.insertRecords(listOf(stepsRecord))

Daten aktualisieren

Wenn du einen oder mehrere Datensätze ändern musst, insbesondere wenn du deinen App-Datenspeicher mit Daten aus Health Connect synchronisieren musst, kannst du deine Daten aktualisieren. Es gibt zwei Möglichkeiten, vorhandene Daten zu aktualisieren. Welche Sie verwenden, hängt von der Kennung ab, die zum Suchen von Datensätzen verwendet wird.

Metadaten

Es lohnt sich, zuerst die Klasse Metadata zu untersuchen, da diese beim Aktualisieren von Daten erforderlich ist. Beim Erstellen hat jeder Record in Health Connect ein metadata-Feld. Die folgenden Properties sind für die Synchronisierung relevant:

Attribute Beschreibung
id Jeder Record in Health Connect hat einen eindeutigen id-Wert.
Health Connect füllt dieses Feld automatisch aus, wenn ein neuer Eintrag eingefügt wird.
lastModifiedTime Jeder Record verfolgt auch, wann der Eintrag zuletzt geändert wurde.
Health Connect füllt dieses Feld automatisch aus.
clientRecordId Jedem Record kann eine eindeutige ID zugeordnet werden, die als Referenz im Datenspeicher Ihrer Anwendung dient.
Dieser Wert wird von Ihrer App bereitgestellt.
clientRecordVersion Wenn ein Eintrag clientRecordId hat, kann der clientRecordVersion verwendet werden, um die Daten mit der Version im Datenspeicher Ihrer App synchron zu halten.
Dieser Wert wird von Ihrer App bereitgestellt.

Nach dem Lesen nach Zeitraum aktualisieren

Wenn Sie Daten aktualisieren möchten, bereiten Sie zuerst die erforderlichen Datensätze vor. Nehmen Sie bei Bedarf Änderungen an den Einträgen vor. Rufen Sie dann updateRecords auf, um die Änderungen vorzunehmen.

Im folgenden Beispiel wird gezeigt, wie Daten aktualisiert werden. Dazu werden die Werte für den Zonenversatz jedes Datensatzes an die PST angepasst.

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 über Client-Datensatz-ID

Wenn Sie die optionalen Werte „Client Record ID“ und „Client Record Version“ verwenden, empfehlen wir, insertRecords anstelle von updateRecords zu verwenden.

Die Funktion insertRecords kann Daten einfügen oder aktualisieren. Wenn die Daten in Health Connect basierend auf den angegebenen Client-Datensatz-IDs vorhanden sind, werden sie überschrieben. Andernfalls werden sie als neue Daten geschrieben. Dieses Szenario ist nützlich, wenn Sie Daten aus dem Datenspeicher Ihrer App mit Health Connect synchronisieren müssen.

Im folgenden Beispiel wird gezeigt, wie Sie einen Upsert für Daten ausführen, die aus dem App-Datenspeicher abgerufen wurden:

 fun pullStepsFromDatastore(startTime: Instant, endTime: Instant) : 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.activelyRecorded(
            clientRecordId = "Your client record ID",
            clientRecordVersion = 0L,
            device = Device(type = Device.TYPE_WATCH)
        ),
        startTime = startTime,
        startZoneOffset = startTime.atZone(ZoneId.of("PST")).offset,
        endTime = endTime,
        endZoneOffset = endTime.atZone(ZoneId.of("PST")).offset,
        count = 120
    )
    appStepsRecords.add(sr)
    // ...
    return appStepsRecords
}

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

Anschließend können Sie diese Funktionen in Ihrem Hauptthread aufrufen.

upsertSteps(healthConnectClient, pullStepsFromDatastore(
    startTime = startTime,
    endTime = endTime
))

Wertprüfung in der Client Record Version

Wenn Ihr Prozess zum Upsert von Daten die Client-Datensatzversion enthält, führt Health Connect Vergleichsprüfungen der clientRecordVersion-Werte durch. Wenn die Version der eingefügten Daten höher ist als die Version der vorhandenen Daten, wird der Upsert-Vorgang ausgeführt. Andernfalls wird die Änderung ignoriert und der Wert bleibt unverändert.

Wenn Sie die Versionsverwaltung in Ihre Daten einbeziehen möchten, müssen Sie Metadata.clientRecordVersion einen Long-Wert basierend auf Ihrer Versionsverwaltungslogik bereitstellen.

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.activelyRecorded(
        clientRecordId = "Your supplied record ID",
        clientRecordVersion = 0L, // Your supplied record version
        device = Device(type = Device.TYPE_WATCH)
    )
)

Upserts erhöhen version nicht automatisch, wenn Änderungen vorgenommen werden. Dadurch wird verhindert, dass Daten unerwartet überschrieben werden. In diesem Fall müssen Sie manuell einen höheren Wert angeben.

Allgemeine Anleitung

Ihre App sollte alle unterstützten selbst erhobenen Daten schreiben. Optional können Sie festlegen, dass Ihre App Daten aus Drittanbieterquellen schreibt. Wenn Ihre App jedoch Daten aus Health Connect gelesen hat, sollten diese Daten nicht wieder in Health Connect geschrieben werden.

Wenn Sie Daten schreiben, die aus einer anderen Quelle importiert oder abgeleitet wurden, müssen Sie deren Ursprung und die Metadaten des Quellgeräts korrekt angeben. Dazu müssen Sie für jeden schriftlichen Datensatz die folgenden Metadaten angeben:

  • recordingMethod: Bei automatisch oder manuell aufgezeichneten Daten erwarten wir, dass die Aufzeichnungsmethode aktualisiert wird, um die Art der aufgezeichneten Aktivität widerzuspiegeln:
    • RECORDING_METHOD_AUTOMATICALLY_RECORDED: Wenn die Daten automatisch aufgezeichnet wurden, z. B. wenn ein Fitnessarmband automatisch erkannt hat, dass der Nutzer laufen war.
    • RECORDING_METHOD_ACTIVELY_RECORDED: Wenn der Nutzer eine neue Aktivität auf seinem Wearable gestartet hat, z. B. Radfahren.
    • RECORDING_METHOD_MANUAL_ENTRY: Wenn der Nutzer die Daten manuell eingegeben hat.
  • device.type: Sie müssen einen Gerätetyp aus einem der unterstützten Device-Typen angeben.
  • device.manufacturer: Der Hersteller des Geräts, z. B. „Fitbit“.
  • device.model: Das Modell des Geräts, z. B. „Charge 3“.
  • device.udi: (Optional) Der Teil der Gerätekennung (DI) der eindeutigen Gerätekennung (UDI) des Medizinprodukts. Weitere Informationen zu den erforderlichen Berechtigungen und Datenschutzrichtlinien finden Sie im Leitfaden zu Metadaten.

Das korrekte Festlegen von Metadaten ist entscheidend für die Datentransparenz und hilft Nutzern zu verstehen, woher ihre Gesundheitsinformationen stammen. Ausführliche Informationen finden Sie im Leitfaden zu Health Connect-Metadaten.

Wenn Daten in Ihrer App aus einer anderen App importiert wurden, ist die andere App dafür verantwortlich, ihre eigenen Daten in Health Connect zu schreiben.

Es empfiehlt sich außerdem, eine Logik zu implementieren, die Schreibausnahmen wie Daten außerhalb der Grenzen oder einen internen Systemfehler verarbeitet. Sie können Ihre Backoff- und Wiederholungsstrategien auf einen Jobplanungsmechanismus anwenden. Wenn das Schreiben in Health Connect letztendlich nicht erfolgreich ist, muss deine App über diesen Exportpunkt hinausgehen können. Vergessen Sie nicht, Fehler zu protokollieren und zu melden, um die Diagnose zu erleichtern.

Beim Erfassen von Daten gibt es einige Vorschläge, die Sie je nach Art und Weise, wie Ihre App Daten schreibt, befolgen können.

Umgang mit Zeitzonen

Vermeide beim Schreiben zeitbasierter Datensätze, Offsets standardmäßig auf zoneOffset.UTC festzulegen, da dies zu ungenauen Zeitstempeln führen kann, wenn sich Nutzer in anderen Zeitzonen befinden. Berechnen Sie stattdessen die Abweichung anhand des tatsächlichen Standorts des Geräts. Sie können die Zeitzone des Geräts mit ZoneId.systemDefault() abrufen.

val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofDays(1))
val stepsRecords = mutableListOf<StepsRecord>()
var sampleTime = startTime
val minutesBetweenSamples = 15L
while (sampleTime < endTime) {
    // Get the default ZoneId then convert it to an offset
    val zoneOffset = ZoneOffset.systemDefault().rules.getOffset(sampleTime)
    stepsRecords += StepsRecord(
        startTime = sampleTime.minus(Duration.ofMinutes(minutesBetweenSamples)),
        startZoneOffset = zoneOffset,
        endTime = sampleTime,
        endZoneOffset = zoneOffset,
        count = Random.nextLong(1, 100),
        metadata = Metadata.activelyRecorded(device = Device(type = Device.TYPE_WATCH)),
    )
    sampleTime = sampleTime.plus(Duration.ofMinutes(minutesBetweenSamples))
}
healthConnectClient.insertRecords(
    stepsRecords
)

Weitere Informationen finden Sie in der Dokumentation zu ZoneId.

Schreibhäufigkeit und ‑granularität

Verwenden Sie beim Schreiben von Daten in Health Connect eine angemessene Auflösung. Die Verwendung der geeigneten Auflösung trägt dazu bei, die Speicherlast zu reduzieren, während gleichzeitig konsistente und genaue Daten beibehalten werden. Die Datenauflösung umfasst zwei Dinge:

  • Häufigkeit von Schreibvorgängen: Wie oft deine Anwendung neue Daten in Health Connect schreibt.
    • Schreibe Daten so oft wie möglich, wenn neue Daten verfügbar sind, und achte dabei auf die Geräteleistung.
    • Damit die Akkulaufzeit und andere Leistungsaspekte nicht beeinträchtigt werden, sollte das maximale Intervall zwischen Schreibvorgängen 15 Minuten betragen.
  • Granularität der geschriebenen Daten: Wie oft die Datenstichprobe erhoben wurde.
    • Schreibe beispielsweise alle 5 Sekunden Herzfrequenzproben.
    • Nicht für jeden Datentyp ist dieselbe Abtastrate erforderlich. Es bringt wenig, die Schrittzahldaten jede Sekunde zu aktualisieren, im Gegensatz zu einer weniger häufigen Aktualisierung, z. B. alle 60 Sekunden.
    • Höhere Abtastraten können Nutzern einen detaillierteren und genaueren Einblick in ihre Gesundheits- und Fitnessdaten geben. Die Abtastraten sollten ein ausgewogenes Verhältnis zwischen Detailgenauigkeit und Leistung bieten.

Zusätzliche Richtlinien

Beachten Sie beim Schreiben von Daten die folgenden Richtlinien:

  • Bei jeder Synchronisierung werden nur neue Daten und aktualisierte Daten geschrieben, die seit der letzten Synchronisierung geändert wurden.
  • Teilen Sie Anfragen in Blöcke mit maximal 1.000 Einträgen pro Schreibanfrage auf.
  • Aufgaben nur ausführen, wenn das Gerät inaktiv ist und der Akkustand nicht niedrig ist.
  • Verwenden Sie für Hintergrundaufgaben WorkManager, um regelmäßige Aufgaben mit einem maximalen Zeitraum von 15 Minuten zu planen.

Im folgenden Code wird WorkManager verwendet, um regelmäßige Hintergrundaufgaben mit einem maximalen Zeitraum von 15 Minuten und einem flexiblen Intervall von 5 Minuten zu planen. Diese Konfiguration wird mit der Klasse PeriodicWorkRequest.Builder festgelegt.

val constraints = Constraints.Builder()
    .requiresBatteryNotLow()
    .requiresDeviceIdle(true)
    .build()

val writeDataWork = PeriodicWorkRequestBuilder<WriteDataToHealthConnectWorker>(
        15,
        TimeUnit.MINUTES,
        5,
        TimeUnit.MINUTES
    )
    .setConstraints(constraints)
    .build()

Aktives Tracking

Dazu gehören Apps, die ereignisbasiertes Tracking wie Training und Schlaf oder manuelle Nutzereingaben wie Ernährung durchführen. Diese Einträge werden erstellt, wenn die App im Vordergrund ausgeführt wird, oder in seltenen Fällen, wenn sie mehrmals am Tag verwendet wird.

Achten Sie darauf, dass Health Connect nicht während der gesamten Dauer des Ereignisses ausgeführt wird.

Daten müssen auf eine der folgenden zwei Arten in Health Connect geschrieben werden:

  • Synchronisiere die Daten nach Abschluss des Trainings mit Health Connect. Synchronisiere beispielsweise Daten, wenn der Nutzer eine aufgezeichnete Trainingseinheit beendet.
  • Planen Sie eine einmalige Aufgabe mit WorkManager, um Daten später zu synchronisieren.

Best Practices für die Granularität und Häufigkeit von Schreibvorgängen

Verwenden Sie beim Schreiben von Daten in Health Connect eine geeignete Auflösung. Die Verwendung der geeigneten Auflösung trägt dazu bei, die Speicherlast zu reduzieren, während gleichzeitig konsistente und genaue Daten beibehalten werden. Die Datenauflösung umfasst zwei Dinge:

  1. Häufigkeit von Schreibvorgängen: Wie oft Ihre Anwendung neue Daten an Health Connect sendet. Schreibe Daten so oft wie möglich, wenn neue Daten verfügbar sind, und achte dabei auf die Geräteleistung. Damit die Akkulaufzeit und andere Leistungsaspekte nicht beeinträchtigt werden, sollte das maximale Intervall zwischen Schreibvorgängen 15 Minuten betragen.

  2. Granularität der geschriebenen Daten: wie oft die übertragenen Daten erfasst wurden. Beispiel: Herzfrequenzdaten alle 5 Sekunden schreiben. Nicht jeder Datentyp erfordert dieselbe Abtastrate. Es bringt wenig, die Schrittzahldaten jede Sekunde zu aktualisieren, im Gegensatz zu einer weniger häufigen Aktualisierung, z. B. alle 60 Sekunden. Höhere Abtastraten können Nutzern jedoch einen detaillierteren und genaueren Einblick in ihre Gesundheits- und Fitnessdaten geben. Die Abtastrate sollte ein ausgewogenes Verhältnis zwischen Detailgenauigkeit und Leistung bieten.

Datensätze für Seriendaten strukturieren

Bei Datentypen, die eine Reihe von Stichproben verwenden, z. B. HeartRateRecord, ist es wichtig, die Datensätze richtig zu strukturieren. Anstatt einen einzelnen, tagesübergreifenden Datensatz zu erstellen, der ständig aktualisiert wird, sollten Sie mehrere kleinere Datensätze erstellen, die jeweils ein bestimmtes Zeitintervall darstellen.

Für Herzfrequenzdaten sollten Sie beispielsweise für jede Minute einen neuen HeartRateRecord erstellen. Jeder Datensatz hat einen Beginn und ein Ende, die diese Minute umfassen, und enthält alle Herzfrequenzproben, die während dieser Minute erfasst wurden.

Bei regelmäßigen Synchronisierungen mit Health Connect (z. B. alle 15 Minuten) sollte deine App alle Ein-Minuten-Datensätze schreiben, die seit der vorherigen Synchronisierung erstellt wurden. So bleiben die Datensätze überschaubar und die Leistung bei der Abfrage und Verarbeitung von Daten wird verbessert.

Im folgenden Beispiel wird gezeigt, wie Sie einen HeartRateRecord für eine einzelne Minute mit mehreren Stichproben erstellen:

val startTime = Instant.now().truncatedTo(ChronoUnit.MINUTES)
val endTime = startTime.plus(Duration.ofMinutes(1))

val heartRateRecord = HeartRateRecord(
    startTime = startTime,
    startZoneOffset = ZoneOffset.UTC,
    endTime = endTime,
    endZoneOffset = ZoneOffset.UTC,
    // Create a new record every minute, containing a list of samples.
    samples = listOf(
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(15),
            beatsPerMinute = 80,
        ),
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(30),
            beatsPerMinute = 82,
        ),
        HeartRateRecord.Sample(
            time = startTime + Duration.ofSeconds(45),
            beatsPerMinute = 85,
        )
    ),
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ))

Daten schreiben, die den ganzen Tag über erfasst werden

Bei Daten, die fortlaufend erhoben werden, z. B. Schritte, sollte Ihre Anwendung so oft wie möglich in Health Connect schreiben, wenn neue Daten verfügbar sind. Um die Akkulaufzeit und andere Leistungsaspekte nicht negativ zu beeinflussen, sollte das maximale Intervall zwischen Schreibvorgängen 15 Minuten betragen.

Tabelle 1: Anleitung zum Schreiben von Daten

Datentyp

Einheit

Erwartet

Beispiel

Schritte

Schritte

Jede Minute

23:14–23:15 Uhr – 5 Schritte

23:16–23:17 Uhr – 22 Schritte

23:17–23:18 Uhr – 8 Schritte

StepsCadence

Schritte/min

Jede Minute

23:14–23:15 – 5 Schritte/Minute

23:16–23:17 – 22 Schritte/Minute

23:17–23:18 – 8 Schritte/Minute

Rollstuhlanschübe

Anschübe

Jede Minute

23:14–23:15 Uhr – 5 Push-ups

23:16–23:17 – 22 Schübe

23:17–23:18 Uhr – 8 Schübe

Aktiv verbrannte Kalorien

Kalorien

Alle 15 Minuten

23:15–23:30 Uhr – 2 Kalorien

23:30–23:45 Uhr – 25 Kalorien

23:45–00:00 Uhr – 5 Kalorien

TotalCaloriesBurned

Kalorien

Alle 15 Minuten

23:15–23:30 Uhr – 16 Kalorien

23:30–23:45 Uhr – 16 Kalorien

23:45–00:00 Uhr – 16 Kalorien

Entfernung

km/min

Jede Minute

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

23:16–23:16 – 0,021 km

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

ElevationGained

m

Jede Minute

20:36 - 20:37 - 3.048m

20:39 - 20:40 - 3.048m

23:23 - 23:24 - 9.144m

FloorsClimbed

Stockwerke

Jede Minute

23:14–23:15 – 5 Stockwerke

23:16 - 23:16 - 22 Stockwerke

23:17–23:18 Uhr – 8 Stockwerke

HeartRate

bpm

4‑mal pro Minute

06:11:15 Uhr – 55 bpm

06:11:30 Uhr – 56 bpm

06:11:45 – 56 bpm

6:12:00 Uhr – 55 S/Min

HeartRateVariabilityRmssd

ms

Jede Minute

06:11 – 23 ms

RespiratoryRate

Atemzüge/Minute

Jede Minute

23:14–23:15 Uhr – 60 Atemzüge/Minute

23:16–23:16 – 62 Atemzüge pro Minute

23:17–23:18 Uhr – 64 Atemzüge/Minute

OxygenSaturation

%

Stündlich

6:11 - 95.208%

Daten sollten am Ende des Trainings oder der Schlafeinheit in Health Connect geschrieben werden. Für die aktive Aufzeichnung, z. B. von Training und Schlaf, oder für manuelle Nutzereingaben wie Ernährung werden diese Datensätze erstellt, wenn die App im Vordergrund ist, oder in seltenen Fällen, wenn sie mehrmals am Tag verwendet wird.

Achten Sie darauf, dass Health Connect nicht während des gesamten Ereignisses ausgeführt wird.

Daten müssen auf eine der folgenden zwei Arten in Health Connect geschrieben werden:

  • Synchronisiere die Daten nach Abschluss des Trainings mit Health Connect. Synchronisiere beispielsweise Daten, wenn der Nutzer eine aufgezeichnete Trainingseinheit beendet.
  • Mit WorkManager eine einmalige Aufgabe planen, um Daten später zu synchronisieren.

Trainings- und Schlafeinheiten

Ihre Anwendung sollte mindestens die Anleitung in der Spalte Erwartet in Tabelle 2 befolgen. Folgen Sie nach Möglichkeit der Anleitung in der Spalte Best.

In der folgenden Tabelle wird gezeigt, wie Daten während eines Trainings geschrieben werden:

Tabelle 2: Anleitung zum Schreiben von Daten während einer Trainingseinheit

Datentyp

Einheit

Erwartet

Viele Grüße

Beispiel

Schritte

Schritte

Jede Minute

Jede Sekunde

23:14–23:15 – 5 Schritte

23:16–23:17 Uhr – 22 Schritte

23:17–23:18 Uhr – 8 Schritte

StepsCadence

Schritte/min

Jede Minute

Jede Sekunde

23:14–23:15 Uhr – 35 Schritte/Minute

23:16–23:17 – 37 Schritte/Minute

23:17–23:18 Uhr – 40 Schritte/Minute

Rollstuhlanschübe

Anschübe

Jede Minute

Jede Sekunde

23:14–23:15 Uhr – 5 Liegestütze

23:16–23:17 – 22 Schübe

23:17–23:18 Uhr – 8 Push-Benachrichtigungen

CyclingPedalingCadence

Atemzüge/Min.

Jede Minute

Jede Sekunde

23:14–23:15 Uhr – 65 Atemzüge/Min.

23:16–23:17 Uhr – 70 U/min

23:17–23:18 Uhr – 68 U/min

Stromversorgung

Watt

Jede Minute

Jede Sekunde

23:14–23:15 – 250 Watt

23:16–23:17 Uhr – 255 Watt

23:17–23:18 Uhr – 245 Watt

Geschwindigkeit

km/min

Jede Minute

Jede Sekunde

23:14–23:15 – 0,3 km/min

23:16–23:17 – 0,4 km/min

23:17–23:18 Uhr, -0,4 km/Min.

Entfernung

km/m

Jede Minute

Jede Sekunde

23:14–23:15 Uhr – 0,008 km

23:16–23:16 – 0,021 km

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

Aktiv verbrannte Kalorien

Kalorien

Jede Minute

Jede Sekunde

23:14–23:15 – 20 Kalorien

23:16–23:17 – 20 kcal

23:17–23:18 – 25 Kalorien

TotalCaloriesBurned

Kalorien

Jede Minute

Jede Sekunde

23:14–23:15 – 36 Kalorien

23:16–23:17 – 36 Kalorien

23:17–23:18 – 41 Kalorien

ElevationGained

m

Jede Minute

Jede Sekunde

20:36 - 20:37 - 3.048m

20:39 - 20:40 - 3.048m

23:23 - 23:24 - 9.144m

ExerciseRoutes

Breitengrad/Längengrad/Höhe

Alle 3–5 Sekunden

Jede Sekunde

HeartRate

bpm

4‑mal pro Minute

Jede Sekunde

23:14–23:15 – 150 bpm

In Tabelle 3 wird gezeigt, wie Daten während oder nach einer Schlafeinheit geschrieben werden:

Tabelle 3: Anleitung zum Schreiben von Daten während oder nach einer Schlafeinheit

Datentyp

Einheit

Erwartete Stichproben

Beispiel

Schlafphasen

Phase

Detaillierter Zeitraum pro Schlafphase

23:46–23:50 Uhr – wach

23:50–23:56 Uhr – Leichtschlaf

23:56–00:16 Uhr – Tiefschlaf

RestingHeartRate

bpm

Einzelner Tageswert (wird morgens erwartet)

06:11 Uhr – 60 bpm

OxygenSaturation

%

Einzelner Tageswert (wird morgens erwartet)

6:11 - 95.208%

Mehrdisziplin-Wettkämpfe

Bei diesem Ansatz werden vorhandene Datentypen und ‑strukturen verwendet und die Kompatibilität mit aktuellen Health Connect-Implementierungen und Datenlesern wird überprüft. Dies ist ein gängiger Ansatz von Fitnessplattformen.

Außerdem sind einzelne Trainingseinheiten wie Schwimmen, Radfahren und Laufen in Health Connect nicht von Natur aus miteinander verknüpft. Datenleser müssen die Beziehung zwischen diesen Trainingseinheiten anhand ihrer zeitlichen Nähe ableiten. Übergänge zwischen Segmenten, z. B. vom Schwimmen zum Radfahren, werden nicht explizit dargestellt.

Im folgenden Beispiel wird gezeigt, wie Daten für einen Triathlon geschrieben werden:

val swimStartTime = Instant.parse("2024-08-22T08:00:00Z")
val swimEndTime = Instant.parse("2024-08-22T08:30:00Z")
val bikeStartTime = Instant.parse("2024-08-22T08:40:00Z")
val bikeEndTime = Instant.parse("2024-08-22T09:40:00Z")
val runStartTime = Instant.parse("2024-08-22T09:50:00Z")
val runEndTime = Instant.parse("2024-08-22T10:20:00Z")

val swimSession = ExerciseSessionRecord(
    startTime = swimStartTime,
    endTime = swimEndTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_SWIMMING_OPEN_WATER,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ),
    startZoneOffset = null,
    endZoneOffset = null,
)

val bikeSession = ExerciseSessionRecord(
    startTime = bikeStartTime,
    endTime = bikeEndTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_BIKING,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ),
    startZoneOffset = null,
    endZoneOffset = null,
)

val runSession = ExerciseSessionRecord(
    startTime = runStartTime,
    endTime = runEndTime,
    exerciseType = ExerciseSessionRecord.EXERCISE_TYPE_RUNNING,
    metadata = Metadata.activelyRecorded(
        device = Device(type = Device.TYPE_WATCH)
    ),
    startZoneOffset = null,
    endZoneOffset = null,
)

healthConnectClient.insertRecords(listOf(swimSession, bikeSession, runSession))

Ausnahmen behandeln

Health Connect löst bei CRUD-Vorgängen Standardausnahmen aus, wenn ein Problem auftritt. Ihre App sollte jede dieser Ausnahmen entsprechend abfangen und verarbeiten.

Für jede Methode in HealthConnectClient werden die Ausnahmen aufgeführt, die ausgelöst werden können. Im Allgemeinen sollte Ihre App die folgenden Ausnahmen verarbeiten:

Tabelle 1: Health Connect-Ausnahmen und empfohlene Best Practices
Ausnahme Beschreibung Empfohlene Best Practices
IllegalStateException Eines der folgenden Szenarien ist eingetreten:

  • Der Health Connect-Dienst ist nicht verfügbar.
  • Die Anfrage ist nicht gültig. Beispiel: Eine aggregierte Anfrage in periodischen Buckets, bei der ein Instant-Objekt für die timeRangeFilter verwendet wird.

Beheben Sie mögliche Probleme mit den Eingaben, bevor Sie eine Anfrage stellen. Weisen Sie Variablen am besten Werte zu oder verwenden Sie sie als Parameter in einer benutzerdefinierten Funktion, anstatt sie direkt in Ihren Anfragen zu verwenden. So können Sie Strategien zur Fehlerbehandlung anwenden.
IOException Beim Lesen und Schreiben von Daten auf dem Laufwerk treten Probleme auf. Hier sind einige Vorschläge, wie Sie dieses Problem vermeiden können:

  • Sichern Sie alle Nutzereingaben.
  • Sie müssen in der Lage sein, alle Probleme zu beheben, die bei Bulk-Schreibvorgängen auftreten. Sorgen Sie beispielsweise dafür, dass der Prozess das Problem umgeht, und führen Sie die verbleibenden Vorgänge aus.
  • Wiederholungs- und Backoff-Strategien anwenden, um Anfrageprobleme zu beheben.

RemoteException Es sind Fehler im zugrunde liegenden Dienst, mit dem das SDK eine Verbindung herstellt, oder bei der Kommunikation mit diesem Dienst aufgetreten.

Ihre Anwendung versucht beispielsweise, einen Datensatz mit einer bestimmten uid zu löschen. Die Ausnahme wird jedoch ausgelöst, nachdem die Anwendung beim Prüfen des zugrunde liegenden Dienstes festgestellt hat, dass der Eintrag nicht vorhanden ist.
Hier sind einige Vorschläge, wie Sie dieses Problem vermeiden können:

  • Führe regelmäßige Synchronisierungen zwischen dem Datenspeicher deiner App und Health Connect durch.
  • Wiederholungs- und Backoff-Strategien anwenden, um Anfrageprobleme zu beheben.

SecurityException Es treten Probleme auf, wenn die Anfragen Berechtigungen erfordern, die nicht gewährt wurden. Um dies zu vermeiden, müssen Sie die Verwendung von Health Connect-Datentypen für Ihre veröffentlichte App deklarieren. Außerdem müssen Sie Health Connect-Berechtigungen in der Manifestdatei und in Ihrer Aktivität deklarieren.