aggregate() and AggregateRequest: totals, averages and deduplicated sources
Last verified October 4, 2026 · 5 min read
Covered here:Health Connect
aggregate is how you ask Health Connect for a number instead of a list: a total, a minimum, a maximum or an average over one window. It is also the call Google tells you to use for step totals. This page covers the request, the result and what Google says about duplicate data, from the HealthConnectClient reference, the AggregateRequest reference, the AggregationResult reference and the aggregate data guide, all fetched October 4, 2026.
The method and the request#
The declaration is suspend fun aggregate(request: AggregateRequest): AggregationResult. Google's summary: it "Reads AggregateMetrics according to requested read criteria: Records from AggregateRequest.dataOriginFilter and within AggregateRequest.timeRangeFilter." Like the other read calls it lists RemoteException, SecurityException and IOException.
AggregateRequest(
metrics: Set<AggregateMetric<*>>,
timeRangeFilter: TimeRangeFilter,
dataOriginFilter: Set<DataOrigin> = emptySet()
)
| Parameter | Google's description |
|---|---|
metrics | "Set of AggregateMetrics to aggregate." |
timeRangeFilter | "The TimeRangeFilter to read from." |
dataOriginFilter | "Set of DataOrigins to read from, or empty for no filter." |
The metrics are constants on the record classes: StepsRecord.COUNT_TOTAL, DistanceRecord.DISTANCE_TOTAL, HeartRateRecord.BPM_MAX and so on. The guide splits them into cumulative aggregation, which "computes the total value", and statistical aggregation, which "computes the minimum, maximum, or average values of records with samples." The full list of metrics for every record type is on the Health Connect aggregate metrics page.
Availability. The reference labels AggregateRequest and AggregationResult "Added in 1.1.0". The aggregate method carries no label of its own.
Reading the AggregationResult#
| Member | What Google documents |
|---|---|
operator fun <T : Any> get(metric: AggregateMetric<T>): T? | "If there are no relevant records contributing to the requested metric, the metric will not be provided." Returns "the value of the metric, or null if not set." |
operator fun contains(metric: AggregateMetric<*>): Boolean | "Checks whether the aggregation result contains a metric or not." |
val dataOrigins: Set<DataOrigin> | "Set of DataOrigins that contributed to the aggregation result." |
Values are typed by the metric. DISTANCE_TOTAL gives a length, which Google's sample reads with .inMeters; the heart-rate minimum and maximum come back as Long. One request can mix record types: the example on Google's AggregationResult page asks for a steps total and a distance total together and reads both from the same result.
A sketch#
suspend fun stepsAndPeakHeartRate(
client: HealthConnectClient,
start: Instant,
end: Instant
) {
val result = client.aggregate(
AggregateRequest(
metrics = setOf(StepsRecord.COUNT_TOTAL, HeartRateRecord.BPM_MAX),
timeRangeFilter = TimeRangeFilter.between(start, end)
)
)
val steps: Long? = result[StepsRecord.COUNT_TOTAL] // null: nothing contributed
val peakBpm: Long? = result[HeartRateRecord.BPM_MAX]
val sources = result.dataOrigins.map { it.packageName }
// Show "no data" when steps is null instead of rendering 0.
}
What Google says about duplicates#
This is the reason aggregate exists for step totals. The aggregate guide:
"End users can set priority for the Sleep and Activity apps that they have integrated with Health Connect. Only end users can alter these priority lists. When you perform an aggregate read, the Aggregate API accounts for any duplicate data and keeps only the data from the app with the highest priority."
And, later on the same page: "Only the Activity and Sleep data types are deduped by Health Connect" and "For other types of data, the aggregated results combine all data of the type in Health Connect from all apps which wrote the data." The read guide adds that the aggregation API "contains logic to handle duplicate records, and lessens the chances of rate limiting."
What Google does not spell out: the page gives steps and distance as examples of duplicate Activity data but does not list every record type it counts as Activity, and it does not describe how Health Connect decides that two records overlap. What happens to totals when a user reorders that priority list is covered in deduplicating health data.
Filtering by data origin#
To aggregate one app's data, pass its package name. The guide's example aggregates steps "from a specific app" with dataOriginFilter = setOf(DataOrigin(appPackageName)). Google does not say how the priority-based deduplication above behaves once the filter narrows the read to a single app.
Since the June 2026 Health Connect update, a filter also decides whether you see the steps the phone counts itself. The read guide: "If your app reads aggregated step counts using aggregate and doesn't filter by DataOrigin, on-device steps are automatically included in the total". On-device steps recorded since that update are attributed to a device-specific Synthetic Package Name (SPN) instead of android, so an app that reads them with a filter, or breaks steps down by source, "must query for records where the DataOrigin is android or matches the device's SPN." Google adds that "you must not hardcode SPN values." The guide also notes that the API that returns the SPN, getCurrentDeviceDataSource(), "is not yet available in the Health Connect Jetpack library". The record itself is described on the StepsRecord page.
Pitfalls#
?: 0Lturns "no data" into zero. Google's samples default a missing metric to0L. For a chart or a goal, a day with no records and a day with zero steps are different facts; keep thenulluntil you render.- Summing
readRecordsinstead. Google's read guide says to useaggregate()rather thanreadRecords()for cumulative types "to avoid double counting from multiple sources". A hand-written sum gets none of the deduplication described above. - A
DataOriginfilter that drops the phone's own steps. Filtering to an app list withoutandroidand the device SPN leaves out on-device steps. Without a filter they are included. - Expecting deduplication for every type. Only Activity and Sleep data are deduplicated by priority. For other types, Google says the aggregate combines the data of every app that wrote it.
- The default read window applies. The aggregate guide repeats that apps can read data for up to 30 days before any permission was first granted, and that without
PERMISSION_READ_HEALTH_DATA_HISTORY"an attempt to read records older than 30 days results in an error." Health Connect returns no data covers that limit. - Malformed requests throw. Google's read guide lists
IllegalStateExceptionfor a request that "isn't a valid construction", with an example from the bucketed variants covered on the Duration vs Period page.
Frequently asked questions
- Does Health Connect's aggregate API remove duplicate steps written by different apps?
- For Activity and Sleep data, yes. Google's aggregate guide says users can set a priority order for their Activity and Sleep apps, and that an aggregate read accounts for duplicate data and keeps only the data from the app with the highest priority, giving steps and distance as examples. Google also says only Activity and Sleep types are deduplicated; for other types the aggregate combines the data of every app that wrote it.
- Why does an AggregationResult return null for a metric I asked for?
- Because no records contributed to it. Google's AggregationResult reference says that if there are no relevant records contributing to the requested metric, the metric will not be provided, and get returns null when the metric is not set. You can test for this with contains(metric). Defaulting the value to zero, as Google's samples do, hides the difference between no data and a real zero.
- Can one Health Connect AggregateRequest include metrics from different record types?
- Yes. The metrics parameter is a set of AggregateMetric values, and the example on Google's AggregationResult reference requests a steps total and a distance total together, then reads each one from the same result. Each value is typed by its metric, so a distance total comes back as a length and a heart-rate maximum as a Long.
- How can I tell which apps contributed to a Health Connect aggregate value?
- Read the dataOrigins property of the AggregationResult. Google's reference describes it as the set of DataOrigin values that contributed to the aggregation result, and each DataOrigin carries the package name of the app that inserted the data. To restrict an aggregate to particular apps instead, pass their package names in the request's dataOriginFilter.
Keep reading
Elsewhere on the site
Pages that share this one’s concepts and sources, from other sections.
Next steps
Was this page useful?
Independent comparison, last reviewed October 4, 2026. Pricing, rate limits, and feature availability change often — confirm current details in each provider’s official documentation before you commit. Product and company names are trademarks of their respective owners; AIFitnessAPI is not affiliated with, endorsed by, or sponsored by any product listed here.
← All health connect api · by AIFitnessAPI