Health Sync Overview & Best Practices
b.well Health SDK for Android
Health Sync Overview
Overview
Health Sync lets your app read health data stored locally on the user's phone (via Android Health Connect) and upload it to b.well for processing. It is a separate integration path from Cloud Provider connections — the two solve different problems and are not interchangeable. This page groups every method you need for each path, plus how they fit together.
Cloud Providers vs. Native On-Device Sync
- Cloud Providers: connects a cloud-hosted provider account (e.g. a fitness platform's web API) via a browser-based OAuth flow. b.well pulls data directly from that provider's servers — no on-device SDK is involved.
- Native On-Device Sync: connects to health data stored locally on the user's phone. Your app must call
syncperiodically (or in response to a trigger) to push data from the phone to b.well — there is no server-to-server pull. Data from a wearable only reaches this path indirectly, if the wearable's own app already writes it into Android Health Connect.
Use Cloud Providers when the data lives with a third-party provider's servers. Use Health Sync when the data lives on the phone itself.
1. Reading Health Data
Regardless of which path below populated the data, reading it back always goes through HealthDataManager (BWellSdk.health):
- Retrieve Device Metrics — flat, ungrouped raw observations.
- Retrieve Device Metrics Groups — the same data pre-organized into named groups.
- Retrieve Health Score — the patient's overall health score.
- Retrieve Body System Score — a detailed score for one body system.
2. Syncing with Cloud Providers
- Get Device Providers — discover which providers are currently available to connect and their
slugvalues. This list is dynamic (backend-driven) — there is no fixed set of provider names; always fetch it live rather than hardcoding one. - Retrieve an Oauth URL — start the OAuth flow for a provider
slugfrom the list above. - Disconnect (
deleteConnection) — remove an existing cloud provider connection.
Don't confuse this with the Native On-Device Sync
disconnectbelow. They're two unrelated methods:deleteConnectionremoves a Cloud Provider's OAuth connection;BWellSdk.healthSync.disconnect()(section 3) ends an on-device sync session. Calling one does not affect the other.
3. Syncing with Android Health Connect (Native On-Device Sync)
These 4 methods compose the native on-device path. All 4 live on BWellSdk.healthSync:
- Connect —
BWellSdk.healthSync.connect(). Provisions backend credentials for the on-device adapter and starts its sync session. - Request Permissions —
BWellSdk.healthSync.requestPermissions(types). Requests OS-level authorization for the health data types you need. - Sync —
BWellSdk.healthSync.sync(types, window). Reads data from the phone; with the registered on-device adapter, that read is what feeds data into b.well as a side effect. To see the data afterward, use the methods in Reading Health Data above —syncdoes not return records itself. See the Sync page for foreground and permission-related limitations. - Disconnect —
BWellSdk.healthSync.disconnect(). Ends the session and removes the connection.
sourceId is technically a parameter on all 4 methods, but omit it — there's currently only one supported on-device adapter, auto-selected when not specified.
Switching accounts on the same device: call disconnect for the current user before calling connect for a new one. Calling connect while a different user's session is still active fails with a session-conflict error rather than silently overwriting it — see Session Conflict Handling below.
Configure the on-device adapter once, at app startup, before calling any of the 4 methods above. The exact adapter class comes from whichever on-device health source package you add — per the ports & adapters design, the SDK's public methods behave identically regardless of which adapter is registered:
BWellHealthSync.configure(
YourOnDeviceHealthSource(applicationContext) { types ->
// Launch the OS permission dialog for `types` and return the results
}
)Session Conflict Handling
Only one on-device sync session can be active per user per device at a time.
var connectResult = BWellSdk.healthSync.connect()
if (!connectResult.success() && /* result indicates a session conflict */) {
BWellSdk.healthSync.disconnect()
connectResult = BWellSdk.healthSync.connect()
}Async Data Ingestion
sync returns per-type record counts, not the records themselves — reading a type is what feeds it into b.well's pipeline, but processing on b.well's side happens asynchronously after that. Don't assume data is immediately readable right after sync returns; poll Retrieve Device Metrics Groups after a short delay, or on your app's next natural data-refresh point, to confirm the data was processed.
Best Practices
- Call
configureexactly once per app process, before any other Health Sync method. - Request only the health data types your app actually uses.
- Always
disconnectbefore connecting a different user or source on the same device. - Treat
sync's return value as a record-count receipt, not as the synced data itself. - Call
syncwhile your app is in the foreground — see Sync for why. - A
FAILEDcount fromsyncusually means a missing permission for that type, not a real error. - Fetch
getDeviceProviders()live rather than hardcoding provider slugs — availability changes per org.
Updated 12 days ago
