Aggregierte Daten lesen

Das Aggregieren von Daten in Health Connect umfasst grundlegende Aggregationen oder das Aggregieren von Daten in Buckets. In den folgenden Arbeitsabläufen wird gezeigt, wie Sie beides tun können.

Einfache Aggregation

Wenn Sie eine einfache Aggregation für Ihre Daten verwenden möchten, verwenden Sie die Funktion aggregate für Ihr HealthConnectClient-Objekt. Es akzeptiert ein AggregateRequest-Objekt, dem Sie die Messwerttypen und den Zeitraum als Parameter hinzufügen. Die Bezeichnung der grundlegenden Aggregierungen hängt von den verwendeten Messwerttypen ab.

Kumulative Aggregation

Bei der kumulativen Aggregation wird der Gesamtwert berechnet.

Im folgenden Beispiel wird gezeigt, wie Sie Daten für einen Datentyp aggregieren:

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

Nach Datenursprung filtern

Sie können aggregierte Daten auch nach ihrem Ursprung filtern. Sie können beispielsweise nur Daten einbeziehen, die von einer bestimmten App geschrieben wurden.

Das folgende Beispiel zeigt, wie Sie mit dataOriginFilter und AggregateRequest Schritte aus einer bestimmten App zusammenfassen:

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

Statistische Aggregation

Bei der statistischen Aggregation werden die Mindest-, Höchst- oder Durchschnittswerte von Datensätzen mit Stichproben berechnet.

Das folgende Beispiel zeigt, wie die statistische Aggregation verwendet wird:

suspend fun aggregateHeartRate(
    healthConnectClient: HealthConnectClient,
    startTime: Instant,
    endTime: Instant
) {
    try {
        val response =
            healthConnectClient.aggregate(
                AggregateRequest(
                    setOf(HeartRateRecord.BPM_MAX, HeartRateRecord.BPM_MIN),
                    timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
                )
            )
        // The result may be null if no data is available in the time range
        val minimumHeartRate = response[HeartRateRecord.BPM_MIN] ?: 0L
        val maximumHeartRate = response[HeartRateRecord.BPM_MAX] ?: 0L
    } catch (e: Exception) {
        // Run error handling here
    }
}

Buckets

Mit Health Connect können Sie Daten auch in Buckets zusammenfassen. Sie können zwei Arten von Buckets verwenden: duration (Dauer) und period (Zeitraum).

Nach dem Aufruf wird eine Liste mit Buckets zurückgegeben. Die Liste kann lückenhaft sein. Ein Bucket wird nicht in die Liste aufgenommen, wenn er keine Daten enthält.

Dauer

In diesem Fall werden aggregierte Daten in Zeiträume mit einer festen Länge unterteilt, z. B. in Minuten oder Stunden. Verwenden Sie aggregateGroupByDuration, um Daten in Buckets zusammenzufassen. Es akzeptiert ein AggregateGroupByDurationRequest-Objekt, dem Sie die Messwerttypen, den Zeitraum und Duration als Parameter hinzufügen. Sie können Paare von Instant- oder LocalDateTime-Objekten für startTime und endTime in TimeRangeFilter verwenden.

Im Folgenden sehen Sie ein Beispiel für die Aggregation von Schritten in Buckets von einer Minute:

suspend fun aggregateStepsIntoMinutes(
    healthConnectClient: HealthConnectClient,
    startTime: LocalDateTime,
    endTime: LocalDateTime
) {
    try {
        val response =
            healthConnectClient.aggregateGroupByDuration(
                AggregateGroupByDurationRequest(
                    metrics = setOf(StepsRecord.COUNT_TOTAL),
                    timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
                    timeRangeSlicer = Duration.ofMinutes(1L)
                )
            )
        for (durationResult in response) {
            // The result may be null if no data is available in the time range
            val totalSteps = durationResult.result[StepsRecord.COUNT_TOTAL] ?: 0L
        }
    } catch (e: Exception) {
        // Run error handling here
    }
}

Punkt

In diesem Fall werden zusammengefasste Daten in Zeiträumen wie einer Woche oder einem Monat in Buckets aufgeteilt. Verwenden Sie aggregateGroupByPeriod, um Daten in Buckets zusammenzufassen. Es akzeptiert ein AggregateGroupByPeriodRequest-Objekt, dem Sie die Messwerttypen, den Zeitraum und Period als Parameter hinzufügen.

Im Folgenden sehen Sie ein Beispiel für die Aggregation von Schritten in monatlichen Buckets:

suspend fun aggregateStepsIntoMonths(
    healthConnectClient: HealthConnectClient,
    startTime: LocalDateTime,
    endTime: LocalDateTime
) {
    try {
        val response =
            healthConnectClient.aggregateGroupByPeriod(
                AggregateGroupByPeriodRequest(
                    metrics = setOf(StepsRecord.COUNT_TOTAL),
                    timeRangeFilter = TimeRangeFilter.between(startTime, endTime),
                    timeRangeSlicer = Period.ofMonths(1)
                )
            )
        for (monthlyResult in response) {
            // The result may be null if no data is available in the time range
            val totalSteps = monthlyResult.result[StepsRecord.COUNT_TOTAL] ?: 0L
        }
    } catch (e: Exception) {
        // Run error handling here
    }
}

Leseeinschränkungen

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.

Daten aggregieren, die von den vom Nutzer ausgewählten App-Prioritäten betroffen sind

Endnutzer können die Priorität für die Schlaf- und Aktivitäts-Apps festlegen, die sie in Health Connect eingebunden haben. Nur Endnutzer können diese Prioritätslisten ändern. Wenn Sie einen aggregierten Lesevorgang ausführen, werden in der Aggregate API alle doppelten Daten berücksichtigt und nur die Daten der App mit der höchsten Priorität beibehalten. Doppelte Daten können vorhanden sein, wenn der Nutzer mehrere Apps hat, die gleichzeitig dieselben Daten schreiben, z. B. die Anzahl der Schritte oder die zurückgelegte Distanz.

Abbildung zum Ändern der Priorität von Apps
Abbildung 1: Prioritäten von Apps neu anordnen

Abbildung zum Ändern der Priorität von Apps

Informationen dazu, wie Nutzer ihre Apps priorisieren können, finden Sie unter Health Connect-Daten verwalten.

Der Nutzer kann Apps hinzufügen oder entfernen und ihre Prioritäten ändern. Ein Nutzer möchte möglicherweise eine App entfernen, die doppelte Daten schreibt, damit die Gesamtdaten auf dem Health Connect-Bildschirm mit den Daten der App übereinstimmen, die er als wichtigste App festgelegt hat. Die Datensummen werden in Echtzeit aktualisiert.

Auch wenn die Aggregate API Daten von Aktivitäts- und Schlaf-Apps berechnet, indem Daten entsprechend den vom Nutzer festgelegten Prioritäten dedupliziert werden, können Sie Ihre eigene Logik erstellen, um die Daten für jede App, die diese Daten schreibt, separat zu berechnen.

Nur die Datentypen „Aktivität“ und „Schlaf“ werden von Health Connect dedupliziert. Die angezeigten Datensummen sind die Werte nach der Deduplizierung durch die Aggregate API. Diese Summen beziehen sich auf den letzten vollständigen Tag, für den Daten zu Schritten und Distanz verfügbar sind. Bei anderen Datentypen werden in den aggregierten Ergebnissen alle Daten des Typs in Health Connect aus allen Apps zusammengefasst, die die Daten geschrieben haben.

Lesevorgänge im Hintergrund

Sie können anfordern, dass Ihre Anwendung im Hintergrund ausgeführt wird und Daten aus Health Connect liest. Wenn Sie die Berechtigung Im Hintergrund lesen anfordern, kann der Nutzer Ihrer App Zugriff zum Lesen von Daten im Hintergrund gewähren.

Unterstützte aggregierte Datentypen nach Datensatz

In dieser Tabelle sind alle unterstützten aggregierten Datentypen nach Health Connect-Datensatz aufgeführt.

Tabelle: Unterstützte aggregierte Datentypen nach Datensatz
Aufnehmen Aggregierter Datentyp
ActiveCaloriesBurnedRecord ACTIVE_CALORIES_TOTAL
ActivityIntensityRecord DURATION_TOTAL, INTENSITY_MINUTES_TOTAL, MODERATE_DURATION_TOTAL, VIGOROUS_DURATION_TOTAL
BasalMetabolicRateRecord BASAL_CALORIES_TOTAL
BloodPressureRecord DIASTOLIC_AVG, DIASTOLIC_MAX, DIASTOLIC_MIN, SYSTOLIC_AVG, SYSTOLIC_MAX, SYSTOLIC_MIN
CyclingPedalingCadenceRecord RPM_AVG, RPM_MAX, RPM_MIN
DistanceRecord DISTANCE_TOTAL
ElevationGainedRecord ELEVATION_GAINED_TOTAL
ExerciseSessionRecord EXERCISE_DURATION_TOTAL
FloorsClimbedRecord FLOORS_CLIMBED_TOTAL
HeartRateRecord BPM_AVG, BPM_MAX, BPM_MIN, MEASUREMENTS_COUNT
HeightRecord HEIGHT_AVG, HEIGHT_MAX, HEIGHT_MIN
HydrationRecord VOLUME_TOTAL
MindfulnessSessionRecord MINDFULNESS_DURATION_TOTAL
NutritionRecord BIOTIN_TOTAL, CAFFEINE_TOTAL, CALCIUM_TOTAL, CHLORIDE_TOTAL, CHOLESTEROL_TOTAL, CHROMIUM_TOTAL, COPPER_TOTAL, DIETARY_FIBER_TOTAL, ENERGY_FROM_FAT_TOTAL, ENERGY_TOTAL, FOLATE_TOTAL, FOLIC_ACID_TOTAL, IODINE_TOTAL, IRON_TOTAL, MAGNESIUM_TOTAL, MANGANESE_TOTAL,  MOLYBDENUM_TOTAL, MONOUNSATURATED_FAT_TOTAL, NIACIN_TOTAL, PANTOTHENIC_ACID_TOTAL, PHOSPHORUS_TOTAL, POLYUNSATURATED_FAT_TOTAL, POTASSIUM_TOTAL, PROTEIN_TOTAL, RIBOFLAVIN_TOTAL, SATURATED_FAT_TOTAL, SELENIUM_TOTAL, SODIUM_TOTAL, SUGAR_TOTAL, THIAMIN_TOTAL, TOTAL_CARBOHYDRATE_TOTAL, TOTAL_FAT_TOTAL, TRANS_FAT_TOTAL, UNSATURATED_FAT_TOTAL, VITAMIN_A_TOTAL, VITAMIN_B12_TOTAL, VITAMIN_B6_TOTAL, VITAMIN_C_TOTAL, VITAMIN_D_TOTAL, VITAMIN_E_TOTAL, VITAMIN_K_TOTAL, ZINC_TOTAL
PowerRecord POWER_AVG, POWER_MAX, POWER_MIN
RestingHeartRateRecord BPM_AVG, BPM_MAX, BPM_MIN
SkinTemperatureRecord TEMPERATURE_DELTA_AVG, TEMPERATURE_DELTA_MAX, TEMPERATURE_DELTA_MIN
SleepSessionRecord SLEEP_DURATION_TOTAL
SpeedRecord SPEED_AVG, SPEED_MAX, SPEED_MIN
StepsRecord COUNT_TOTAL
StepsCadenceRecord RATE_AVG, RATE_MAX, RATE_MIN
TotalCaloriesBurnedRecord ENERGY_TOTAL
WeightRecord WEIGHT_AVG, WEIGHT_MAX, WEIGHT_MIN
WheelchairPushesRecord COUNT_TOTAL