Integrating with Health Connect

AndroidHealth ConnectPrivacyIntegration
Share on LinkedIn

Health Connect is Android's bet on health data not being locked in silos — steps in one app, sleep in another, heart rate in a third, none talking to each other. It provides a unified datastore with granular permissions: users choose exactly which data types each app can read or write. Building a fitness app, wellness tracker, or medical integration in 2026 means Health Connect, not Google Fit (deprecated) or proprietary SDKs. The API is clean; the complexity is in permission UX, background sync policies, and the privacy requirements Google enforces during Health Connect app review.

Setup

dependencies {
    implementation("androidx.health.connect:connect-client:1.1.0")
}
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.health.READ_STEPS" />
<uses-permission android:name="android.permission.health.WRITE_STEPS" />
<uses-permission android:name="android.permission.health.READ_HEART_RATE" />

<!-- Required for Health Connect to discover your app -->
<activity android:name=".PermissionsActivity" android:exported="true">
    <intent-filter>
        <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
    </intent-filter>
</activity>

<activity-alias
    android:name="ViewPermissionUsageActivity"
    android:exported="true"
    android:targetActivity=".PermissionsActivity"
    android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
    <intent-filter>
        <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
        <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
    </intent-filter>
</activity-alias>

The activity-alias for VIEW_PERMISSION_USAGE is required — Health Connect app review checks for it.

Checking availability and permissions

class HealthConnectManager(private val context: Context) {
    private val client = HealthConnectClient.getOrCreate(context)

    suspend fun isAvailable(): Boolean {
        return HealthConnectClient.getSdkStatus(context) == HealthConnectClient.SDK_AVAILABLE
    }

    suspend fun hasAllPermissions(permissions: Set<String>): Boolean {
        val granted = client.permissionController.getGrantedPermissions()
        return permissions.all { it in granted }
    }

    fun permissionLauncher(
        activity: ComponentActivity,
        onResult: (Boolean) -> Unit
    ): ActivityResultLauncher<Set<String>> {
        return activity.registerForActivityResult(
            PermissionController.createRequestPermissionResultContract()
        ) { granted ->
            onResult(granted.containsAll(requiredPermissions))
        }
    }
}

Request permissions with rationale:

if (!healthConnect.hasAllPermissions(requiredPermissions)) {
    if (shouldShowRationale) {
        showRationaleDialog {
            permissionLauncher.launch(requiredPermissions)
        }
    } else {
        permissionLauncher.launch(requiredPermissions)
    }
}

Reading health records

suspend fun readTodaySteps(): Long {
    val now = Instant.now()
    val startOfDay = now.atZone(ZoneId.systemDefault()).toLocalDate()
        .atStartOfDay(ZoneId.systemDefault()).toInstant()

    val response = client.readRecords(
        ReadRecordsRequest(
            recordType = StepsRecord::class,
            timeRangeFilter = TimeRangeFilter.between(startOfDay, now),
        )
    )
    return response.records.sumOf { it.count }
}

Available record types include: StepsRecord, HeartRateRecord, SleepSessionRecord, WeightRecord, NutritionRecord, DistanceRecord, ActiveCaloriesBurnedRecord, and more. Check the Health Connect data types reference for the full list.

Writing records

suspend fun writeSteps(count: Long, startTime: Instant, endTime: Instant) {
    val record = StepsRecord(
        count = count,
        startTime = startTime,
        endTime = endTime,
        startZoneOffset = ZoneOffset.systemDefault().rules.getOffset(startTime),
        endZoneOffset = ZoneOffset.systemDefault().rules.getOffset(endTime),
    )
    client.insertRecords(listOf(record))
}

Always include zone offsets — Health Connect requires them for temporal records.

Background sync with changes token

For efficient background reads without polling:

suspend fun syncChanges() {
    var changesToken = prefs.getString("changes_token", null)

    val changes = client.getChanges(
        ChangesTokenRequest(changesToken ?: "")
    )

    for (change in changes.changes) {
        when (change) {
            is UpsertionChange -> handleNewRecord(change.record)
            is DeletionChange -> handleDeletedRecord(change.recordId)
        }
    }

    prefs.edit { putString("changes_token", changes.nextChangesToken) }
}

Run via WorkManager on a periodic schedule. Much more efficient than full re-reads.

Privacy requirements

Health Connect apps go through additional review:

Build the privacy policy link into your permission request flow. Health Connect review rejects apps with vague data use descriptions.

Health Connect vs platform sensors

Health Connect is a data aggregation layer, not a sensor API. To read live sensor data (real-time heart rate during a workout), use the Android Sensor API or Health Services API directly, then write results to Health Connect for other apps to access.

Sensors/Health Services → your app processes → write to Health Connect → other apps read

Permission and data minimization

Request only Health Connect permissions your feature needs:

val permissions = setOf(
    HealthPermission.getReadPermission(StepsRecord::class),
    HealthPermission.getReadPermission(HeartRateRecord::class),
)

Background reads require explicit user grant. Show in-app rationale before system permission dialog — Health Connect denial is hard to reverse.

Common production mistakes

Teams get health connect integration wrong in predictable ways:

Shipping health connect integration on Android fails quietly when you test only on flagship devices, skip process-death scenarios, or assume minSdk behavior matches latest API docs. Emulator-only validation misses OEM-specific battery optimizations and background execution limits.

Debugging and triage workflow

When health connect integration misbehaves in production, work top-down instead of guessing:

  1. Confirm scope — one tenant, region, or deployment stage? Narrow blast radius before deep diving.
  2. Check recent changes — deploys, flag flips, config pushes, and schema migrations in the last 24 hours.
  3. Compare golden signals — latency, error rate, saturation, and traffic for the affected surface vs. baseline.
  4. Reproduce minimally — smallest input or scenario that triggers the failure; capture traces/logs with correlation IDs.
  5. Fix forward or rollback — if rollback is faster than root-cause during incident, rollback first, postmortem second.
  6. Add a guard — alert, integration test, or circuit breaker so the same class of failure is caught earlier next time.

Document the timeline during triage. Future you (and on-call) will need timestamps, not just conclusions.

Resources

Frequently asked questions

What is Health Connect on Android?

Health Connect is Android's centralized health and fitness data platform. It provides a unified API for reading and writing health records (steps, heart rate, sleep, nutrition, etc.) and acts as a permission-controlled datastore that apps share data through, replacing direct access to Google Fit and siloed health databases.

How do Health Connect permissions work?

Health Connect uses granular per-data-type permissions (read/write separately for steps, heart rate, sleep, etc.). Users grant permissions through the Health Connect permission UI, not standard Android runtime permissions. Your app declares required permissions in the manifest and requests them at runtime via the Health Connect permission contract.

Do I need Health Connect or can I use Google Fit directly?

Google Fit APIs are deprecated in favor of Health Connect. New apps should integrate with Health Connect directly. If your app currently reads from Google Fit, migrate to Health Connect — it provides the same data with better privacy controls and is the platform Google is investing in.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →