Skip to main content
Back to Blog

Mobile Engineering

How Do You Build Reliable Activity Sync Across Apple Health and Health Connect?

Published by IHP Technology11 min read

Build reliable activity sync by defining the data contract before connecting the platform APIs: choose an active provider, request only the required read permissions, preserve time and source context, and assign each metric one role. Then verify the entire path from the device’s health store through the backend to the interface. A populated chart alone cannot establish that its values came from the intended provider or that calories were counted correctly.

IHP Technology applies these boundaries in MyFitLife, its own nutrition and activity product. The publicly listed 1.3.7 release introduced Health Central with steps, active calories, workouts, active minutes, and period views. This article examines that release’s implementation baseline and develops reusable engineering checks from it. Implementation details are grounded in the associated 1.3.7+32 source; recommended tests and extensions are identified separately. Later internal changes are outside this example.

Start with a metric contract, not a collection of APIs

A health integration needs a definition of meaning for every value it displays. Steps describe progress. Active energy describes a provider’s reported energy expenditure. Workout duration describes a recorded session. These values overlap in time, but they are not interchangeable. A screen that gives them the same visual weight can still require very different rules for storage, aggregation, and target adjustment.

MyFitLife’s released contract keeps steps progress-only and uses the connected provider’s daily active energy for optional calorie credit. The practical design artifact is a metric ledger: write down the source, unit, aggregation boundary, destination, and allowed calculation before implementation. Review that ledger when adding a new card or provider field. A new display should never silently become a new input to an existing nutrition calculation.

Activity metric contract used to reason about MyFitLife Health Central
MetricPurposeCalorie-target role
StepsDaily progress and period trendsNo step-to-calorie conversion
Daily active energyProvider-reported daily activity totalOnly activity input for optional credit
Workouts and session minutesActivity history and duration contextDo not add workout energy again
Apple Activity / Android intensity contextOptional provider-specific presentationOutside target calculation

Scroll horizontally to read all table columns.

Choose one active provider for the account

Cross-platform support does not require merging two independently connected feeds. MyFitLife’s release baseline selects one active health provider per account: Apple Health on the supported Apple device or Health Connect on Android. The synchronization snapshot carries a source-platform value alongside its window and records. That makes the provider boundary explicit instead of inferring ownership from whichever phone submits data last.

This decision also shapes cross-device behavior. A person can open an account on a device whose local provider differs from the connected provider. The release contract keeps previously synchronized history readable while reserving synchronization for the matching device. Switching is an explicit disconnect-and-delete operation followed by connection on the other platform. The interface must explain this dependency before presenting a sync action.

For another product, write down whether provider switching replaces history, preserves a labeled archive, or migrates selected records. Each policy creates different expectations. Avoid an implicit last-writer policy: simultaneous devices can otherwise change the interpretation of a day without a deliberate user action. One active provider simplifies ownership; it does not prove that every underlying sensor record is unique.

Keep read consent and downstream use separate

The core MyFitLife gateway requests read access for active energy, steps, and workouts. Reading those records does not require writing nutrition records back to the health store. Additional provider presentation has its own capability and authorization path. Scope should follow the feature the person is enabling, with a clear explanation of which information leaves the device.

The release implementation also separates calorie adjustment and Coach sharing into preferences, both disabled by default. This matters because permission to read a device record is different from a decision to use that record in an adjusted target or send selected context into a coaching feature. Model these decisions independently rather than treating the operating-system consent sheet as blanket permission for every downstream purpose.

Apple documents a further constraint: an app cannot determine whether a person granted read access through the authorization-status method used for saving data. Empty results therefore cannot reliably identify a denial. Describe what the app can observe, provide a route to review permissions, and avoid a message that claims knowledge the platform intentionally withholds.

Make energy accounting deliberately non-additive

Suppose a provider reports 420 active kilocalories for a day and a workout row shows 180 kilocalories during a run. If the daily total already contains that run, adding both produces 600 and credits the same activity twice. Deriving another allowance from steps creates the same problem through a different route. This is a synthetic accounting example, not a MyFitLife measurement or an estimate of anyone’s needs.

MyFitLife uses the provider’s daily active-energy total as the canonical activity value. Workout-window energy is a display read, separate from daily synchronization. Apple Move presentation also stays outside the additional-credit calculation. The reusable rule is to distinguish a measure of the whole day from an explanation of part of that day.

For a test fixture, hold daily active energy constant while changing workout details, steps, or optional provider context. The activity credit should remain unchanged. Then disable the adjustment preference and verify that the underlying activity history remains available without affecting the target. These tests exercise the accounting boundary directly, rather than merely asserting that several cards display numbers.

Distinguish measured zero from unavailable data

An integration should not force every outcome into a numeric field. A zero can mean an observed total of zero. An empty response can mean no records in the requested interval. A read can be unavailable because of capability, permissions, or an execution failure. Previously stored history can remain useful while being stale. Those conditions need different language and different recovery actions.

The 1.3.7 source models provider insight states including available, no data, unsupported, authorization required, and unavailable. Apple Activity uses a truthful unavailable fallback where the platform does not expose the cause. This state model is useful evidence of design intent, but it should not be generalized into a claim that every metric and every failure path already preserves all these distinctions.

As an implementation recommendation, carry availability and observation time alongside values at each boundary. Check that a failed read cannot overwrite a known value with an invented zero. Make accessibility announcements as specific as the visible message. A person hearing “zero steps” should have the same evidential basis for that statement as someone reading the chart.

Define calendar windows and reread recent history

A daily total is a value plus a calendar interval. The release client constructs local-day windows, limits the current day to the read time, and defines an initial history window of 30 days with a shorter two-day foreground window. Rereading recent days accommodates records that reach the platform after the first read; it does not guarantee that all later corrections will be discovered.

For a new integration, specify the time zone used to assign records to dates and what happens after travel. Test sessions crossing midnight, a daylight-saving transition, a changed phone clock, and a partially completed current day. Compare the exact intervals requested from the provider with the dates stored by the backend. Calendar correctness needs its own fixtures; a successful ordinary-day example does not cover those cases.

Health Connect’s default historical read allowance also matters: Android documents access reaching 30 days before the first permission grant, with a separate permission to extend history. Design the import screen around actual authorized availability. A year selector should not suggest that connecting today necessarily imports a complete year.

Separate provider aggregation from record deduplication

There are two different duplicate problems. A health store can contain overlapping observations from multiple originating apps or devices. Separately, an app can encounter the same workout repeatedly during synchronization. Combining those problems into one generic “dedupe” flag hides the rules that actually determine the result.

Android documents priority-aware duplicate handling for supported Activity and Sleep aggregate reads. That is a reason to understand the selected provider API before summing raw records. It does not justify claiming that every record type, custom query, or application-side sum receives identical treatment.

MyFitLife’s release client also consolidates workout snapshots using external identifiers and a fingerprint built from workout type and start/end instants. Duplicate merging retains the larger energy value instead of summing it and can label differing origins as multiple sources. This is a concrete bounded strategy, not proof that two differently timed descriptions of the same real activity will always match.

For verification, test repeated reads, identical identifiers, matching fingerprints with different identifiers, and genuinely distinct overlapping sessions. Document what the algorithm cannot establish. Record identity can make repeated processing safer without providing an exactly-once guarantee across every device and failure mode.

Separate detailed retention from long-term trends

MyFitLife’s release baseline defines 400-day retention for daily aggregates and 30-day retention for detailed workouts. Current-day hourly arrays are not retained as long-term history. This explains how a longer period view can remain useful without promising an equally detailed archive of every session.

An engineering retention map should distinguish what the client can read, what the backend retains, and what the interface can currently load. These are separate limits. A cached record does not extend the provider’s authorized read window, and an empty older workout list does not prove the person had no activity on that date.

Use the same separation for deletion design. Specify whether disconnecting stops future reads, deletes imported application records, or revokes platform access, and verify each promised effect separately. Do not imply that deleting an app’s copy deletes the originating health-store data. For another product, choose retention according to the feature’s purpose and document deletion behavior before adding more detailed categories.

Retention and availability questions to keep separate
LayerMyFitLife release baselineVerification question
Initial client history30-day snapshot windowWhich days are authorized and actually readable?
Daily backend history400-day retention policyWhich retained dates contain imported aggregates?
Detailed workouts30-day retention policyIs the loaded session list complete for this view?
Provider-specific contextDevice-local presentationDoes absence affect only this enhancement?

Scroll horizontally to read all table columns.

Preserve native meaning in the interface

Provider-specific features deserve provider-specific labels. MyFitLife’s baseline presents Apple Activity through the native ring view and accounts for Move modes that can represent minutes instead of energy. On Android, optional intensity information depends on capability and available source data. Exercise-session duration is not automatically a measured intensity total.

The source deliberately keeps these presentation objects outside the shared synchronization snapshot, stored fitness history, Coach context, and calorie-target calculation. This creates a useful architectural boundary: richer device-local presentation can improve a screen without enlarging every downstream data contract.

For another integration, add a capability matrix before designing equivalent-looking cards. Record the source unit, whether a goal exists, whether the value is daily or session-based, and the fallback when unsupported. Visual symmetry between platforms is less useful than semantic consistency. If two cards measure different things, their titles and explanations should make that difference visible.

Verify the contract on the distributed build

Use independent evidence for provider access, transformation, persistence, and presentation. Deterministic fixtures can prove accounting rules and state rendering. Backend readback can prove which records were stored. Physical-device checks can establish what a particular signed build reads after a particular permission choice. None of these layers substitutes for the others.

The public App Store listing establishes the released Health Central feature description. The corresponding source establishes implementation decisions discussed here. This article does not report a new physical-device regression run, a synchronization success rate, or complete Android store verification. Those require their own current evidence.

For release review, capture the app version, device platform, permission choices, provider date interval, expected result, and actual stored result. Keep test accounts and synthetic fixtures identifiable so their records cannot be mistaken for production observations. A useful handoff lets another engineer reproduce the discrepancy without collecting unrelated personal health data.

  • -Test permission rejection and partial availability without inventing a reason for an empty Apple read.
  • -Hold daily energy constant while varying steps and workout details; confirm credit does not increase.
  • -Open a connected account on the other platform; verify readable history and explicit sync guidance.
  • -Read the same window again, interrupt a sync, and inspect stored dates and workout identity.
  • -Exercise retention boundaries and deletion against the exact signed candidate, then record unresolved results.

Related services

  • Mobile Apps

    Plan, design, and build mobile apps for iOS and Android with IHP Technology, including user experience, APIs, cloud infrastructure, and launch support.

  • Data & AI

    IHP Technology helps businesses design practical data pipelines, analytics workflows, and AI-enabled software features that are secure and maintainable.

Keep reading