Cómo leer datos agregados

En Health Connect, se pueden hacer agregaciones básicas o agregar datos en buckets. En los siguientes flujos de trabajo, se muestra cómo realizar ambas tareas.

Agregación básica

Para usar la agregación básica en tus datos, utiliza la función aggregate en tu objeto HealthConnectClient. Acepta un objeto AggregateRequest en el que agregas los tipos de métricas y el intervalo de tiempo como sus parámetros. La forma en que se llaman las agregaciones básicas depende de los tipos de métricas usados.

Agregación acumulativa

La agregación acumulativa calcula el valor total.

En el siguiente ejemplo, se muestra cómo agregar datos a un tipo de datos:

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
    }
}

Filtrar por origen de los datos

También puedes filtrar los datos agregados por su origen. Por ejemplo, solo incluir datos escritos por una app específica

En el siguiente ejemplo, se muestra cómo usar dataOriginFilter y AggregateRequest para agregar pasos de una app específica:

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
    }
}

Agregación estadística

La agregación estadística calcula los valores mínimos, máximos o promedio de los registros con muestras.

En el siguiente ejemplo, se muestra cómo usar la agregación estadística:

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

Health Connect también te permite agregar datos a buckets. Los dos tipos de buckets que puedes usar incluyen duración y período.

Una vez que se los llama, muestran una lista de buckets. Ten en cuenta que la lista puede ser dispersa, por lo que no se incluye un bucket en ella si no contiene datos.

Duración

En este caso, los datos agregados se dividen en buckets dentro de un período fijo, como un minuto o una hora. Para agregar datos en buckets, usa aggregateGroupByDuration. Acepta un objeto AggregateGroupByDurationRequest en el que agregas los tipos de métricas, el intervalo de tiempo y la Duration como parámetros. Puedes usar pares de objetos Instant o LocalDateTime para startTime y endTime en TimeRangeFilter.

A continuación, se muestra un ejemplo de cómo agregar pasos en buckets de un minuto:

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
    }
}

Período

En este caso, los datos agregados se dividen en buckets dentro de un intervalo de tiempo basado en la fecha, como una semana o un mes. Para agregar datos en buckets, usa aggregateGroupByPeriod. Acepta un objeto AggregateGroupByPeriodRequest en el que agregas los tipos de métricas, el intervalo de tiempo y la Period como parámetros.

A continuación, se muestra un ejemplo de cómo agregar pasos en buckets mensuales:

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
    }
}

Restricciones de lectura

De forma predeterminada, todas las aplicaciones pueden leer datos de Health Connect hasta 30 días antes del otorgamiento de cualquier permiso.

Si necesitas extender los permisos de lectura más allá de cualquiera de las restricciones predeterminadas, solicita el PERMISSION_READ_HEALTH_DATA_HISTORY. De lo contrario, sin este permiso, cualquier intento de leer registros con una antigüedad superior a 30 días generará un error.

Historial de permisos de una app borrada

Si un usuario borra tu app, se revocarán todos los permisos, incluido el permiso de historial. Si el usuario vuelve a instalar tu app y le otorga permiso de nuevo, se aplicarán las mismas restricciones predeterminadas, y tu app podrá leer datos de Health Connect hasta 30 días antes de esa fecha nueva.

Por ejemplo, supongamos que el usuario borra tu app el 10 de mayo de 2023 y, luego, la reinstala el 15 de mayo de 2023 y otorga permisos de lectura. Ahora, la fecha más antigua de la que tu app puede leer datos de forma predeterminada es el 15 de abril de 2023.

Datos agregados afectados por las prioridades de las apps seleccionadas por el usuario

Los usuarios finales pueden establecer la prioridad de las apps de Sueño y Actividad que integraron con Health Connect. Solo los usuarios finales pueden modificar estas listas de prioridad. Cuando realizas una lectura agregada, la API de Aggregate tiene en cuenta los datos duplicados y solo conserva los datos de la app con la prioridad más alta. Es posible que haya datos duplicados si el usuario tiene varias apps que escriben el mismo tipo de datos (por ejemplo, la cantidad de pasos realizados o la distancia recorrida) al mismo tiempo.

Imagen que muestra cómo reordenar la prioridad de las apps
Figura 1: Reordena las prioridades de las apps

Imagen que muestra cómo reordenar las prioridades de las apps

Para obtener información sobre cómo los usuarios finales pueden priorizar sus apps, consulta Administra los datos de Health Connect.

El usuario puede agregar o quitar apps, así como cambiar sus prioridades. Es posible que un usuario quiera quitar una app que escribe datos duplicados para que los totales de datos en la pantalla de Health Connect sean idénticos a los de la app a la que le dio la mayor prioridad. Los totales de datos se actualizan en tiempo real.

Aunque la API de Aggregate calcula los datos de las apps de Actividad y Sueño quitando los duplicados según cómo el usuario estableció las prioridades, puedes crear tu propia lógica para calcular los datos por separado para cada app que escribe esos datos.

Health Connect solo anula los datos duplicados de los tipos de datos de Actividad y Sueño, y los totales de datos que se muestran son los valores después de que la API de Aggregate realiza la anulación de duplicados. Estos totales muestran el día completo más reciente en el que hay datos de pasos y distancia. Para otros tipos de datos, los resultados agregados combinan todos los datos del tipo en Health Connect de todas las apps que escribieron los datos.

Lecturas en segundo plano

Puedes solicitar que tu aplicación se ejecute en segundo plano y lea datos de Health Connect. Si solicitas el permiso de Lectura en segundo plano, el usuario puede otorgarle a tu app acceso para leer datos en segundo plano.

Tipos de datos agregados admitidos por registro

En esta tabla, se enumeran todos los tipos de datos agregados admitidos por el registro de Health Connect.

Tabla: Tipos de datos agregados admitidos por registro
Grabar Tipo de datos agregados
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