Skip to content

Install & configure ​

Adding the package takes one command. Most of the work is platform configuration — and you only need the platform you actually ship.

Check your toolchain ​

ComponentRequirement
Flutter≥ 3.38.0 (the package declares flutter: '>=3.38.0', sdk: ^3.10.0)
AndroidAPI 26+ (Android 8.0), Kotlin 2.1.0, Java 17
iOSiOS 15.0+, Swift 5.9

Flutter 3.38.0 is a hard floor

The package declares flutter: '>=3.38.0', so pub get fails on Flutter 3.35.x and older. This is a resolution requirement, not a recommendation.

Flutter 3.38.0 ships Dart 3.10.0, so a single Flutter upgrade satisfies both constraints. Swift 5.9 and Kotlin 2.1 remain compatible with Swift 5.0 and Kotlin 2.0 code, so the native side is a version bump in your build files.

Full details, including why each floor exists, are in Requirements.

Add the package ​

bash
flutter pub add health_connector

Or declare it directly in pubspec.yaml:

yaml
dependencies:
  health_connector: ^3.9.4

Depend only on the facade. The Android and iOS implementations arrive transitively, which lets the facade coordinate compatible releases — see Packages.

Configure your platform ​

Android · Health Connect ​

  1. Declare a permission for every data type you touch.

    Health Connect will not grant access to a type your manifest does not name. Add one <uses-permission> per type and direction to android/app/src/main/AndroidManifest.xml:

    xml
    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- Data permissions: one per type, per direction -->
        <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_WEIGHT" />
        <uses-permission android:name="android.permission.health.WRITE_WEIGHT" />
        <uses-permission android:name="android.permission.health.READ_HEART_RATE" />
        <uses-permission android:name="android.permission.health.WRITE_HEART_RATE" />
    
        <!-- Exercise sessions, and GPS routes on top of them -->
        <uses-permission android:name="android.permission.health.READ_EXERCISE" />
        <uses-permission android:name="android.permission.health.WRITE_EXERCISE" />
        <uses-permission android:name="android.permission.health.READ_EXERCISE_ROUTE" />
        <uses-permission android:name="android.permission.health.WRITE_EXERCISE_ROUTE" />
    
        <!-- Feature permissions -->
        <uses-permission android:name="android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND" />
        <uses-permission android:name="android.permission.health.READ_HEALTH_DATA_HISTORY" />
    </manifest>

    The permission name follows the data type: HealthDataType.bloodGlucose needs READ_BLOOD_GLUCOSE. Google's Health Connect data types reference lists every one.

  2. Declare the permissions-rationale entry points.

    Health Connect and the Android settings UI both need a way into your app to show why you want health data — and they use different mechanisms per OS version. You need both, inside <application>:

    xml
    <application>
        <activity android:name=".MainActivity" android:exported="true" …>
            <!-- Your existing MAIN/LAUNCHER intent-filter -->
    
            <!-- Android 13 and below -->
            <intent-filter>
                <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
            </intent-filter>
        </activity>
    
        <!-- Android 14 and above -->
        <activity-alias
            android:name="ViewPermissionUsageActivity"
            android:exported="true"
            android:permission="android.permission.START_VIEW_PERMISSION_USAGE"
            android:targetActivity=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
                <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
            </intent-filter>
        </activity-alias>
    </application>

    Both entries are required, and they are not interchangeable

    Putting ACTION_SHOW_PERMISSIONS_RATIONALE inside the activity-alias satisfies neither path. Google Play reviews this flow, so getting it wrong can hold up a release. The example app's manifest is the reference.

  3. Make MainActivity extend FlutterFragmentActivity.

    Permission requests use the modern registerForActivityResult API, which needs a FragmentActivity host. In android/app/src/main/kotlin/.../MainActivity.kt:

    kotlin
    package com.example.yourapp
    
    import io.flutter.embedding.android.FlutterFragmentActivity
    
    class MainActivity : FlutterFragmentActivity() {
        // Your existing code
    }
  4. Enable AndroidX in android/gradle.properties, since Health Connect is built on AndroidX libraries:

    properties
    android.useAndroidX=true

    Older setup guides also add android.enableJetifier=true. Jetifier rewrites pre-AndroidX dependencies and is deprecated — it is off by default under AGP 8 and slows every build. Add it only if you still depend on a legacy support-library artifact.

  5. Raise minSdkVersion to 26 in android/app/build.gradle:

    groovy
    android {
        defaultConfig {
            minSdkVersion 26
        }
    }

    API 26 is what the Health Connect client library compiles against. It is not a promise that Health Connect exists on every API 26 device — the health store is a separate app, and on older devices it may be absent entirely. Always gate on getHealthPlatformStatus() at runtime.

  6. Set compileSdkExtension 19 (required from Health Connector SDK v3.9.0, which builds against Health Connect 1.2.0-alpha03):

    groovy
    // android/app/build.gradle — Groovy DSL
    android {
        compileSdkExtension 19
    }
    kotlin
    // android/app/build.gradle.kts — Kotlin DSL
    android {
        compileSdkExtension = 19
    }

compileSdkExtension is compile-time only

Setting extension 19 satisfies the build. Separately, writing a non-null ExerciseSessionSegmentEvent.weight, .setIndex, or .rateOfPerceivedExertion performs a runtime device check and throws UnsupportedOperationException if that device's Health Connect Mainline module is below SDK Extension 21. The same binary can succeed on one Android 14 device and fail on another. See exercise segment extended fields.

Verify the setup ​

Before requesting anything, confirm the device actually has a usable health store:

dart
final status = await HealthConnector.getHealthPlatformStatus();

if (status != HealthPlatformStatus.available) {
  // On Android this commonly means Health Connect is missing or out of date.
  await HealthConnector.launchHealthAppPageInAppStore();
  return;
}

final connector = await HealthConnector.create();

If this returns anything other than available, or your first call throws, Setup troubleshooting maps each symptom to its cause.

Released under the MIT License.