Rohdaten lesen

Das folgende Beispiel zeigt, wie Sie Rohdaten im Rahmen des allgemeinen Workflows lesen.

Daten lesen

Mit Health Connect können Apps Daten aus dem Datenspeicher lesen, wenn die App im Vordergrund und im Hintergrund ausgeführt wird:

  • Lesen im Vordergrund: Normalerweise können Sie Daten aus Health Connect lesen, wenn sich Ihre App im Vordergrund befindet. In diesen Fällen sollten Sie einen Vordergrunddienst verwenden, um diesen Vorgang auszuführen, falls der Nutzer oder das System Ihre App während eines Lesevorgangs in den Hintergrund verschiebt.

  • Lesen im Hintergrund: Wenn Sie eine zusätzliche Berechtigung vom Nutzer anfordern, können Sie Daten lesen, nachdem der Nutzer oder das System Ihre App in den Hintergrund verschoben hat. Vollständiges Beispiel für das Lesen im Hintergrund

Der Datentyp „Schritte“ in Health Connect erfasst die Anzahl der Schritte, die ein Nutzer zwischen den Messungen zurückgelegt hat. Schrittzahlen sind ein gängiger Messwert auf Gesundheits-, Fitness- und Wellnessplattformen. Mit Health Connect können Sie Daten zur Schrittzahl lesen und schreiben.

Wenn Sie Datensätze lesen möchten, erstellen Sie ein ReadRecordsRequest und geben Sie es beim Aufrufen von readRecords an.

Das folgende Beispiel zeigt, wie Schrittzählerdaten für einen Nutzer innerhalb eines bestimmten Zeitraums gelesen werden. Ein ausführliches Beispiel mit SensorManager finden Sie im Leitfaden zu Schrittzählerdaten.

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.readRecords(
            ReadRecordsRequest(
                StepsRecord::class,
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        for (record in response.records) {
            // Process each record
        }
    } catch (e: Exception) {
        // Run error handling here
    }
}

Sie können Ihre Daten auch aggregiert mit aggregate lesen.

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
            )
        )
        // The result may be null if no data is available in the time range
        val stepCount = response[StepsRecord.COUNT_TOTAL]
    } catch (e: Exception) {
        // Run error handling here
    }
}

Schritte auf dem Smartphone lesen

Unter Android 14 (API-Level 34) und SDK-Erweiterung Version 20 oder höher bietet Health Connect eine Schrittzählung auf dem Gerät. Wenn einer App die Berechtigung READ_STEPS erteilt wurde, erfasst Health Connect Schritte vom Android-Gerät und Nutzer sehen automatisch Schrittdaten, die den Health Connect-Einträgen Schritte hinzugefügt wurden.

Wenn Sie prüfen möchten, ob die Schrittzählung auf dem Gerät verfügbar ist, müssen Sie prüfen, ob auf dem Gerät Android 14 (API-Level 34) ausgeführt wird und es mindestens die SDK-Erweiterungsversion 20 hat. Sie können den folgenden Code verwenden:

val isStepTrackingAvailable =
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
        SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 20

Für von Health Connect erfasste Schritte auf dem Smartphone ist DataOrigin auf den Paketnamen android festgelegt. Wenn Ihre App nur aggregierte Schrittzahlen mit aggregate liest und nicht nach DataOrigin filtert, werden die Schritte auf dem Gerät automatisch in die Gesamtzahl einbezogen.

Wenn Ihre App Schritte auf dem Gerät lesen muss oder Schrittdaten nach Quellanwendung oder Gerät aufgeschlüsselt anzeigt, können Sie Datensätze abfragen, bei denen DataOrigin gleich android ist. Wenn in Ihrer App die Attribution für Schrittdaten angezeigt wird, sollten Sie Daten aus dem Android-Paket dem aktuellen Gerät zuordnen. Dazu können Sie ein Label wie „Mein Smartphone“ verwenden, den Gerätenamen mit Settings.Global.getString(resolver, Settings.Global.DEVICE_NAME) abrufen oder das Feld Device in den Metadaten des Datensatzes prüfen.

Im folgenden Beispiel wird gezeigt, wie aggregierte Daten zur Anzahl der Schritte auf Mobilgeräten gelesen werden, indem nach dem Datenursprung android gefiltert wird:

suspend fun readStepsByTimeRange(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response = healthConnectClient.aggregate(
            AggregateRequest(
                metrics = setOf(StepsRecord.COUNT_TOTAL),
                timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
                dataOriginFilter = setOf(DataOrigin("android"))
            )
        )
        // The result may be null if no data is available in the time range
        val stepCount = response[StepsRecord.COUNT_TOTAL]
    } catch (e: Exception) {
        // Run error handling here
    }
}

Schrittzählung auf dem Gerät

Weitere Informationen zur Funktion zum Zählen von Schritten auf dem Gerät:

  • Sensornutzung: Health Connect verwendet den Sensor TYPE_STEP_COUNTER von SensorManager. Dieser Sensor ist für einen geringen Stromverbrauch optimiert und eignet sich daher ideal für die kontinuierliche Schrittzählung im Hintergrund.
  • Datengranularität: Um den Akku zu schonen, werden Schrittdaten in der Regel in Batches zusammengefasst und höchstens einmal pro Minute in die Health Connect-Datenbank geschrieben.
  • Attribution: Wie bereits erwähnt, werden alle von dieser On-Device-Funktion aufgezeichneten Schritte dem Paketnamen android im DataOrigin zugeordnet.
  • Aktivierung: Der Mechanismus zur Schrittzählung auf dem Gerät ist nur aktiv, wenn mindestens einer Anwendung auf dem Gerät die Berechtigung READ_STEPS in Health Connect erteilt wurde.

Beispiel für das Abrufen von Daten im Hintergrund

Wenn Sie Daten im Hintergrund lesen möchten, deklarieren Sie die folgende Berechtigung in Ihrer Manifestdatei:

<application>
  <uses-permission android:name="android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND" />
...
</application>

Das folgende Beispiel zeigt, wie Schrittzählerdaten für einen Nutzer in einem bestimmten Zeitraum im Hintergrund mit WorkManager gelesen werden:

class ScheduleWorker(private val appContext: Context, workerParams: WorkerParameters):
    CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        // Read data and process it.
        ...

        // Return success indicating successful data retrieval
        return Result.success()
    }
}

if (healthConnectClient
    .features
    .getFeatureStatus(
    HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
    ) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE) {

    // Check if necessary permission is granted
    val grantedPermissions = healthConnectClient.permissionController.getGrantedPermissions()

    if (PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND !in grantedPermissions) {
        // Perform read in foreground
        ...
    } else {
        // Schedule the periodic work request in background
        val periodicWorkRequest = PeriodicWorkRequestBuilder<ScheduleWorker>(1, TimeUnit.HOURS)
            .build()

        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "read_health_connect",
            ExistingPeriodicWorkPolicy.KEEP,
            periodicWorkRequest
        )
    }
} else {
  // Background reading is not available, perform read in foreground
  ...
}

Der Parameter ReadRecordsRequest hat den Standardwert pageSize von 1.000. Wenn die Anzahl der Datensätze in einem einzelnen readResponse die pageSize der Anfrage überschreitet, müssen Sie alle Seiten der Antwort durchlaufen, um alle Datensätze mit pageToken abzurufen. Achten Sie jedoch darauf, dass Sie das Ratenlimit nicht überschreiten.

Beispiel für das Lesen von „pageToken“

Es wird empfohlen, pageToken zum Lesen von Datensätzen zu verwenden, um alle verfügbaren Daten aus dem angeforderten Zeitraum abzurufen.

Im folgenden Beispiel wird gezeigt, wie alle Datensätze gelesen werden, bis alle Seitentokens aufgebraucht sind:

val type = HeartRateRecord::class
val endTime = Instant.now()
val startTime = endTime.minus(Duration.ofDays(7))

try {
    var pageToken: String? = null
    do {
        val readResponse =
            healthConnectClient.readRecords(
                ReadRecordsRequest(
                    recordType = type,
                    timeRangeFilter = TimeRangeFilter.between(
                        startTime,
                        endTime
                    ),
                    pageToken = pageToken
                )
            )
        val records = readResponse.records
        // Do something with records
        pageToken = readResponse.pageToken
    } while (pageToken != null)
} catch (quotaError: IllegalStateException) {
    // Backoff
}

Informationen zu Best Practices beim Lesen großer Datasets finden Sie unter Ratenbegrenzung vermeiden.

Zuvor geschriebene Daten lesen

Wenn eine App bereits Einträge in Health Connect geschrieben hat, kann sie Verlaufsdaten lesen. Dies gilt für Szenarien, in denen die App nach der Neuinstallation durch den Nutzer mit Health Connect synchronisiert werden muss.

Es gelten einige Leseeinschränkungen:

  • Android 14 und höher

    • Es gibt kein Verlaufsdatenlimit für Apps, die ihre eigenen Daten lesen.
    • 30-Tage-Limit für Apps, die andere Daten lesen.
  • Android 13 und niedriger

    • 30-Tage-Limit für das Lesen von Daten durch Apps.

Die Einschränkungen können aufgehoben werden, indem Sie eine Leseberechtigung anfordern.

Wenn Sie Verlaufsdaten lesen möchten, müssen Sie den Paketnamen als DataOrigin-Objekt im Parameter dataOriginFilter Ihres ReadRecordsRequest angeben.

Das folgende Beispiel zeigt, wie ein Paketname beim Lesen von Herzfrequenzdatensätzen angegeben wird:

try {
    val response =  healthConnectClient.readRecords(
        ReadRecordsRequest(
            recordType = HeartRateRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
            dataOriginFilter = setOf(DataOrigin("com.my.package.name"))
        )
    )
    for (record in response.records) {
        // Process each record
    }
} catch (e: Exception) {
    // Run error handling here
}

Daten lesen, die älter als 30 Tage sind

Standardmäßig können alle Anwendungen Daten aus Health Connect für bis zu 30 Tage vor dem ersten Erteilen einer Berechtigung lesen.

Wenn Sie die Leseberechtigungen über die Standardeinschränkungen hinaus erweitern möchten, fordern Sie die PERMISSION_READ_HEALTH_DATA_HISTORY an. Andernfalls führt ein Versuch, Datensätze zu lesen, die älter als 30 Tage sind, zu einem Fehler.

Berechtigungsverlauf für eine gelöschte App

Wenn ein Nutzer Ihre App löscht, werden alle Berechtigungen widerrufen, einschließlich der Berechtigung für den Verlauf. Wenn der Nutzer Ihre App neu installiert und die Berechtigung noch einmal erteilt, gelten dieselben Standardeinschränkungen. Ihre App kann dann Daten aus Health Connect lesen, die bis zu 30 Tage vor diesem neuen Datum erhoben wurden.

Angenommen, der Nutzer löscht Ihre App am 10. Mai 2023, installiert sie am 15. Mai 2023 neu und erteilt Leseberechtigungen. Das früheste Datum, ab dem Ihre App standardmäßig Daten lesen kann, ist jetzt der 15. April 2023.

Ausnahmen behandeln

Health Connect löst Standardausnahmen für CRUD-Vorgänge aus, wenn ein Problem auftritt. Ihre App sollte jede dieser Ausnahmen abfangen und angemessen behandeln.

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 abfangen:

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

  • Der Health Connect-Dienst ist nicht verfügbar.
  • Die Anfrage ist nicht gültig. Beispiel: Eine Aggregatanfrage in regelmäßigen Zeiträumen, bei der ein Instant-Objekt für die timeRangeFilter verwendet wird.

Beheben Sie mögliche Probleme mit den Eingaben, bevor Sie eine Anfrage senden. Weisen Sie Variablen vorzugsweise 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 die Festplatte sind Probleme aufgetreten. Hier sind einige Vorschläge, wie Sie dieses Problem vermeiden können:

  • Sichern Sie alle Nutzereingaben.
  • Sie müssen alle Probleme beheben können, die bei Bulk-Schreibvorgängen auftreten. Achten Sie beispielsweise darauf, dass der Prozess das Problem überwindet und die verbleibenden Vorgänge ausgeführt werden.
  • Wenden Sie Wiederholungs- und Backoff-Strategien an, um Probleme mit Anfragen zu beheben.

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

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

  • Führen Sie regelmäßige Synchronisierungen zwischen dem Datenspeicher Ihrer App und Health Connect durch.
  • Wenden Sie Wiederholungs- und Backoff-Strategien an, um Probleme mit Anfragen zu beheben.

SecurityException Es treten Probleme auf, wenn für die Anfragen Berechtigungen erforderlich sind, die nicht erteilt 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.