An empty Health Connect aggregate should remain an absent value until the product has decided what absence means. A successful request with no value, a successful request returning zero and a failed request are three different outcomes. Converting them all into 0 makes charts easy to draw while making synchronization failures much harder to understand.
Begin with the exact record type, requested metric, time interval and data-origin filter. This guide concerns absent aggregate results and downstream states. Resolving overlapping source totals is a separate task, covered in the duplicate-data guide. A complete result needs both a value contract and an execution contract.
A successful request can still have no reading
Android’s aggregation documentation explicitly notes that a metric can be null when no data is available in the requested range. Its sample chooses a zero fallback for a particular display; that fallback is a policy choice, not evidence that every empty interval measured zero activity. Bucketed results also require inspecting the documented output rather than assuming one populated row per requested hour.
Android: aggregate results and time buckets
Keep the requested window when no row appears, but do not fabricate a measurement to fill it. A chart can draw an empty position, a gap or a neutral marker. A score calculation should receive the coverage status as well as any number, so it can decline to calculate or disclose a partial-input policy.
Give the adapter a state that survives JSON
type Reading =
| { state: "available"; value: number }
| { state: "no_data"; value: null }
| { state: "error"; value: null; retryable: boolean };This is a proposed application contract, not a Health Connect response type. Add the interval, origin and fetched-at timestamp around it. Do not infer permission denial from the missing value alone. Handle a known permission check through the platform’s supported flow, and keep a read exception available for retry and support diagnostics without exposing personal records.
| Input | Retained state | Display decision |
|---|---|---|
| null | no_data | No reading available |
| 0 | available | 0, with its unit |
| 120 | available | 120, with its unit |
| Thrown read error | error | Retry or retain last known reading |
The isolated fixture retained null, zero and 120 as three distinct values and added a separate error state. It did not call Android or a wearable. This verifies the proposed serialization distinction; it does not establish what a particular bridge returns on a particular handset.
Trace the point where absence disappears
In the reviewed UltraFit360 step reader, a raw-record sum returns null unless the total is positive. That source example collapses an explicit zero into the same value as no positive records. It is also a raw-read path, not the aggregate API. Inspect both boundaries before replacing a UI label: changing text cannot restore information already discarded by the adapter.
A useful diagnostic trace records requested metric, window, result state, number of source records when relevant and the transformation applied. Log synthetic values during development. A bare totalSteps=0 line cannot distinguish an empty store from a failed request hidden by a catch block.
Decide how partial coverage affects the next calculation
Suppose a synthetic daily view has two available hours and one missing hour. Its known subtotal is a subtotal, not a complete daily measurement. Retain the missing interval when preparing the summary, and distinguish “last updated” from “measured during.” Retry should change availability only after a successful read; a connection button should not optimistically turn every missing metric green.
Acceptance should include absent buckets, explicit zeros, exceptions, a stale cached reading and a later correction. Confirm that the same distinctions survive persistence, chart formatting and any score input. This produces a useful adapter review artifact without claiming that a wellness score is physiologically validated.
A useful cache key includes the metric and requested window, not only the calendar date. If a user changes the selected origin, a previous all-source result must not be reused as that origin’s result. Keep request identity with the cached state, including an absent result. This lets a later retry replace exactly the unavailable reading it resolves, while a separate metric remains unchanged. Test this with two fictional origins that return different coverage for the same interval.
Bring the specific record types, device/OS targets and one failing or proposed data journey to scope a wearable integration review.
Should an empty Health Connect aggregate become zero?
Preserve absence separately from an explicit zero and a failed read. Choose the display only after the adapter has retained those states.
Does null prove the user denied access?
No. Absence alone does not establish the cause. Use supported permission checks and neutral missing-data language.
