health_connector 2.1.0 copy "health_connector: ^2.1.0" to clipboard
health_connector: ^2.1.0 copied to clipboard

A Flutter plugin to access health data from Android Health Connect and iOS HealthKit

health_connector #

Pub Version Pub Points License Platform

The most complete Flutter health SDK β€” unified, type-safe access to 100+ health data types across iOS HealthKit and Android Health Connect.


πŸ“– Table of Contents #


πŸ“± Exploring SDK Capabilities using Health Connector Toolbox #

To explore the SDK's capabilities hands-on, you can use the Health Connector Toolbox app included in the repository.

Permission Request Read Data Write Data Delete Data Aggregate Data
[Permission Request] [Read Data] [Write Data] [Delete Data] [Aggregate Data]
[Permission Request] [Read Data] [Write Data] [Delete Data] [Aggregate Data]

ℹ️ Note: The toolbox is intended as a demonstration and internal testing tool only. It is not recommended as a reference for building production applications.

What the Toolbox Offers

  • Interactive demonstrations of core SDK capabilities
    • Permission management
    • Read, write, update, and delete operations
    • Data aggregation
    • Feature management
  • Visual representation of health records

Running the Toolbox

# Clone the repository
git clone https://github.com/fam-tung-lam/health_connector.git
cd health_connector

# Navigate to the toolbox app
cd examples/health_connector_toolbox

# Install dependencies
flutter pub get

# Run on your device
flutter run

πŸš€ Quick Start #

πŸ“‹ Requirements #

Platform Minimum Version
Android API 26+
iOS β‰₯15.0

πŸ“¦ Installation #

flutter pub add health_connector

Or add manually to pubspec.yaml:

dependencies:
  health_connector: [latest_version]

πŸ”§ Platform Setup #

πŸ€– Android Health Connect Setup
Update AndroidManifest.xml

Add to android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application>
        <!-- Your existing configuration -->

        <!-- Health Connect intent filter for showing permissions rationale -->
        <activity-alias
            android:name="ViewPermissionUsageActivity"
            android:exported="true"
            android:targetActivity=".MainActivity"
            android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
            <intent-filter>
                <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
            </intent-filter>
        </activity-alias>
    </application>

    <!-- Declare Health Connect permissions for each data type you use -->

    <!-- Read permissions -->
    <uses-permission android:name="android.permission.health.READ_STEPS" />
    <uses-permission android:name="android.permission.health.READ_WEIGHT" />
    <uses-permission android:name="android.permission.health.READ_HEART_RATE" />
    <!-- Add more read permissions... -->
    
    <!-- Write permissions -->
    <uses-permission android:name="android.permission.health.WRITE_STEPS" />
    <uses-permission android:name="android.permission.health.WRITE_WEIGHT" />
    <uses-permission android:name="android.permission.health.WRITE_HEART_RATE" />
    <!-- Add more write permissions... -->

    <!-- 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" />
    <!-- Add more feature permissions... -->
</manifest>

❗ Important: You must declare a permission for each health data type and feature your app accesses. See the Health Connect data types list for all available permissions.

Update MainActivity (Android 14+)

This SDK uses the modern registerForActivityResult API when requesting permissions from Health Connect. For this to work correctly, your app's MainActivity must extend FlutterFragmentActivity instead of FlutterActivity. This is required because registerForActivityResult is only available in ComponentActivity and its subclasses.

Update android/app/src/main/kotlin/.../MainActivity.kt:

package com.example.yourapp

import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity() {
    // Your existing code
}
Enable AndroidX

Health Connect is built on AndroidX libraries. android.useAndroidX=true enables AndroidX support, and android.enableJetifier=true automatically migrates third-party libraries to use AndroidX.

Update android/gradle.properties:

# Your existing configuration

android.enableJetifier=true
android.useAndroidX=true
🍎 iOS HealthKit Setup
Enable HealthKit Capability
  1. Open your project in Xcode (ios/Runner.xcworkspace)
  2. Select your app target
  3. Go to Signing & Capabilities tab
  4. Click + Capability
  5. Add HealthKit
Update Info.plist

Add to ios/Runner/Info.plist:

<dict>
    <!-- Existing keys -->

    <!-- Required: Describe why your app reads health data -->
    <key>NSHealthShareUsageDescription</key>
    <string>This app needs to read your health data to provide personalized insights.</string>

    <!-- Required: Describe why your app writes health data -->
    <key>NSHealthUpdateUsageDescription</key>
    <string>This app needs to save health data to track your progress.</string>
</dict>

⚠️ Warning: Vague or generic usage descriptions may result in App Store rejection. Be specific about what data you access and why.

⚑ Quick Demo #

import 'package:health_connector/health_connector.dart';

Future<void> quickStart() async {
  // 1. Check platform availability
  final status = await HealthConnector.getHealthPlatformStatus();
  if (status != HealthPlatformStatus.available) {
    print('Health platform not available: $status');
    return;
  }

  // 2. Create connector instance
  final connector = await HealthConnector.create(
    HealthConnectorConfig(isLoggerEnabled: true),
  );

  // 3. Request permissions for steps
  // **Note**: Feel free to use any other data type you want.
  final results = await connector.requestPermissions([
    HealthDataType.steps.readPermission,
    HealthDataType.steps.writePermission,
  ]);

  // 4. Check if all permissions were granted
  final arePermissionsGranted = results.every((r) => r.status == PermissionStatus.granted);

  if (!arePermissionsGranted) {
    print('Permissions not granted');
    return;
  }

  // 5. Write multiple step records
  final stepsRecords = [
    StepsRecord(
      startTime: DateTime.now().subtract(Duration(hours: 3)),
      endTime: DateTime.now().subtract(Duration(hours: 2)),
      count: Numeric(1500),
      metadata: Metadata.automaticallyRecorded(
        device: Device.fromType(DeviceType.phone),
      ),
    ),
    StepsRecord(
      startTime: DateTime.now().subtract(Duration(hours: 2)),
      endTime: DateTime.now().subtract(Duration(hours: 1)),
      count: Numeric(2000),
      metadata: Metadata.automaticallyRecorded(
        device: Device.fromType(DeviceType.phone),
      ),
    ),
    StepsRecord(
      startTime: DateTime.now().subtract(Duration(hours: 1)),
      endTime: DateTime.now(),
      count: Numeric(1800),
      metadata: Metadata.automaticallyRecorded(
        device: Device.fromType(DeviceType.phone),
      ),
    ),
  ];
  final recordIds = await connector.writeRecords(stepsRecords);
  print('Wrote ${recordIds.length} records');


  // 6. Read today's step records
  final response = await connector.readRecords(
    HealthDataType.steps.readInTimeRange(
      startTime: DateTime.now().subtract(Duration(days: 1)),
      endTime: DateTime.now(),
    ),
  );

  for (final record in response.records) {
    print('Record: ${record.count.value} (${record.startTime} - ${record.endTime})');
  }
}

πŸ“˜ Developer Guide #

πŸ” Permission Management #

Request Permissions

iOS Privacy Note: Read permissions always return PermissionStatus.unknown on iOS. This is intentionalβ€”Apple prevents apps from detecting whether users have health data by checking permission status.

final permissions = [
  // Data permissions
  HealthDataType.steps.readPermission,
  HealthDataType.steps.writePermission,
  HealthDataType.weight.readPermission,
  HealthDataType.weight.writePermission,
  
  // Feature permissions
  HealthPlatformFeature.readHealthDataInBackground.permission,
];

final results = await connector.requestPermissions(permissions);

for (final result in results) {
  print('${result.permission}: ${result.status}');
}

Check Individual Permission Status

final status = await connector.getPermissionStatus(
  HealthDataType.steps.readPermission,
);

switch (status) {
  case PermissionStatus.granted:
    print('Permission granted');
  case PermissionStatus.denied:
    print('Permission denied');
  case PermissionStatus.unknown:
    print('Cannot determine (iOS read permission)');
}

Get All Granted Permissions (Android Health Connect Only)

iOS Privacy Note: This API is not available on iOS. HealthKit does not provide a way to query all granted permissions to protect user privacy. Apps cannot enumerate what health data access they have been granted.

try {
  final grantedPermissions = await connector.getGrantedPermissions();
  for (final permission in grantedPermissions) {
    if (permission is HealthDataPermission) {
      print('${permission.dataType} (${permission.accessType})');
    }
  }
} on UnsupportedOperationException {
  print('Only available on Android');
}

Revoke All Permissions (Android Health Connect Only)

iOS Privacy Note: This API is not available on iOS. HealthKit requires users to manually revoke permissions through the iOS Settings app. This ensures users have full control and visibility over their health data permissions.

try {
  await connector.revokeAllPermissions();
} on UnsupportedOperationException {
  print('Only available on Android');
}

πŸ“– Reading Health Data #

Platform Note - Historical Data Access

Android Health Connect: By default, Health Connect only provides access to the last 30 days of historical health data. To read data older than 30 days, the HealthPlatformFeature.readHealthDataHistory feature must be available and its permission must be granted.

iOS HealthKit: HealthKit has no default limitation on historical data access. Apps can read health data from any time period, subject only to user permission.

Read by ID

final recordId = HealthRecordId('existing-record-id');
final request = HealthDataType.steps.readRecord(recordId);
final record = await connector.readRecord(request);

if (record != null) {
  print('Steps: ${record.count.value}');
} else {
  print('Record not found');
}

Read Multiple Records

final request = HealthDataType.steps.readInTimeRange(
  startTime: DateTime.now().subtract(Duration(days: 7)),
  endTime: DateTime.now(),
  pageSize: 100,
);

final response = await connector.readRecords(request);

for (final record in response.records) {
  print('Steps: ${record.count.value} (${record.startTime} - ${record.endTime})');
}

Pagination

var request = HealthDataType.steps.readInTimeRange(
  startTime: DateTime.now().subtract(Duration(days: 30)),
  endTime: DateTime.now(),
  pageSize: 100,
);

final allRecords = <StepsRecord>[];

while (true) {
  final response = await connector.readRecords(request);
  allRecords.addAll(response.records.cast<StepsRecord>());

  if (response.nextPageRequest == null) break;
  request = response.nextPageRequest!;
}

print('Total records: ${allRecords.length}');

πŸ’Ύ Writing Health Data #

Write Single Record

final stepRecord = StepsRecord(
  id: HealthRecordId.none, // Must be .none for new records
  startTime: DateTime.now().subtract(Duration(hours: 1)),
  endTime: DateTime.now(),
  count: Numeric(5000),
  metadata: Metadata.automaticallyRecorded(
    device: Device.fromType(DeviceType.phone),
  ),
);

final recordId = await connector.writeRecord(stepRecord);
print('Record ID: $recordId');

Atomic Write Multiple Records

All records succeed or all fail together:

final records = [
  StepsRecord(
    id: HealthRecordId.none,
    startTime: DateTime.now().subtract(Duration(hours: 2)),
    endTime: DateTime.now().subtract(Duration(hours: 1)),
    count: Numeric(3000),
    metadata: Metadata.automaticallyRecorded(
      device: Device.fromType(DeviceType.phone),
    ),
  ),
  StepsRecord(
    id: HealthRecordId.none,
    startTime: DateTime.now().subtract(Duration(hours: 1)),
    endTime: DateTime.now(),
    count: Numeric(2000),
    metadata: Metadata.automaticallyRecorded(
      device: Device.fromType(DeviceType.phone),
    ),
  ),
];

final recordIds = await connector.writeRecords(records);
print('Wrote ${recordIds.length} records');

✍️ Updating Health Records #

iOS Privacy Note: HealthKit does not provide an update API because it uses an immutable data model. Once a health record is written to HealthKit, it cannot be modifiedβ€”only deleted.

Update Record (Android Health Connect Only)

final recordId = HealthRecordId('existing-record-id');
final request = HealthDataType.steps.readRecord(recordId);
final existingRecord = await connector.readRecord(request);

if (existingRecord != null) {
  final updatedRecord = existingRecord.copyWith(
    count: Numeric(existingRecord.count.value + 500),
  );

  await connector.updateRecord(updatedRecord);
  print('Record updated');
}

Atomic Update Multiple Records (Android Health Connect Only)

Update multiple records atomicallyβ€”all succeed or all fail together:

// Read existing records
final readRequest = HealthDataType.steps.readInTimeRange(
  startTime: DateTime.now().subtract(Duration(days: 7)),
  endTime: DateTime.now(),
);
final response = await connector.readRecords(readRequest);

// Update all records by adding 100 steps to each
final updatedRecords = response.records.map((record) {
  return record.copyWith(
    count: Numeric(record.count.value + 100),
  );
}).toList();

// Batch update all records
await connector.updateRecords(updatedRecords);
print('Updated ${updatedRecords.length} records');

iOS HealthKit Update Workaround (Delete + Write)

// 1. Delete existing record
await connector.deleteRecords(
  HealthDataType.steps.deleteByIds([existingRecord.id]),
);

// 2. Write new record with updated values
final newRecord = StepsRecord(
  id: HealthRecordId.none,
  startTime: existingRecord.startTime,
  endTime: existingRecord.endTime,
  count: Numeric(newValue),
  metadata: existingRecord.metadata,
);

final newId = await connector.writeRecord(newRecord);
// Note: newId will be different from the original ID

πŸ—‘οΈ Deleting Health Records #

Atomic Delete by IDs

await connector.deleteRecords(
  HealthDataType.steps.deleteByIds([
    HealthRecordId('id-1'),
    HealthRecordId('id-2'),
  ]),
);

Atomic Delete by Time Range

await connector.deleteRecords(
  HealthDataType.steps.deleteInTimeRange(
    startTime: DateTime.now().subtract(Duration(days: 7)),
    endTime: DateTime.now(),
  ),
);

Important: Apps can only delete records they created. Attempting to delete records from other apps will lead to NotAuthorizedException.

βž• Aggregating Health Data #

Sum Aggregation

Get the total value over a period, such as total steps for a day:

final sumRequest = HealthDataType.steps.aggregateSum(
  startTime: DateTime.now().subtract(Duration(days: 1)),
  endTime: DateTime.now(),
);

final sumResponse = await connector.aggregate(sumRequest);
print('Total steps: ${sumResponse.value.value}');

Average Aggregation

Get the average value over 30 days:

final avgRequest = HealthDataType.weight.aggregateAvg(
  startTime: DateTime.now().subtract(Duration(days: 30)),
  endTime: DateTime.now(),
);

final avgResponse = await connector.aggregate(avgRequest);
print('Average weight: ${avgResponse.value.inKilograms} kg');

Minimum Aggregation

Get the minimum recorded value over a period:

final minRequest = HealthDataType.weight.aggregateMin(
  startTime: DateTime.now().subtract(Duration(days: 30)),
  endTime: DateTime.now(),
);

final minResponse = await connector.aggregate(minRequest);
print('Min weight: ${minResponse.value.inKilograms} kg');

Maximum Aggregation

Get the maximum recorded value over a period:

final maxRequest = HealthDataType.weight.aggregateMax(
  startTime: DateTime.now().subtract(Duration(days: 30)),
  endTime: DateTime.now(),
);

final maxResponse = await connector.aggregate(maxRequest);
print('Max weight: ${maxResponse.value.inKilograms} kg');

βš™οΈ Feature Management #

Platform features have different availability characteristics across platforms.

Platform Differences

  • iOS HealthKit:
    • All features are available and granted by default
    • When checking feature status with getFeatureStatus(), the SDK always returns HealthPlatformFeatureStatus.available
    • When requesting feature permissions with requestPermissions(), the SDK always returns PermissionStatus.granted
  • Android Health Connect:
    • Feature availability depends on Android version and Health Connect SDK version
    • Some features require specific minimum versions, f.e. background health data reading requires Health Connect SDK v1.1.0-alpha04

Checking Feature Availability

// Check if background reading is available
final status = await connector.getFeatureStatus(
  HealthPlatformFeature.readHealthDataInBackground,
);

if (status == HealthPlatformFeatureStatus.available) {
  // Feature is supported - safe to request permission
  await connector.requestPermissions([
    HealthPlatformFeature.readHealthDataInBackground.permission,
  ]);
} else {
  // Feature not available on this device/version
  print('Background reading not available');
  // Implement fallback or disable feature in UI
}

Feature Permission Status

When checking the status of a feature permission:

final permissionStatus = await connector.getPermissionStatus(
  HealthPlatformFeature.readHealthDataInBackground.permission,
);

// On iOS: Always returns PermissionStatus.granted
// On Android: Returns actual status (granted/denied)

⚠️ Error Handling #

The SDK provides two approaches for handling errors.

Approach 1: Catching Specific Exceptions

Use Dart's type-based exception handling to catch specific error types.

try {
  await connector.requestPermissions([...]);
  await connector.writeRecord(record);
} on NotAuthorizedException catch (e) {
  // User denied or revoked permissions
  // Recovery: Explain why permission is needed, guide to settings
  print('Permission denied: ${e.message}');
} on InvalidConfigurationException catch (e) {
  // Missing AndroidManifest.xml or Info.plist configuration
  // Recovery: Fix app configuration (development-time error)
  print('Configuration error: ${e.message}');
} on UnsupportedOperationException catch (e) {
  // Platform doesn't support this operation
  // Recovery: Check platform before calling, use alternative approach
  print('Not supported: ${e.message}');
} on InvalidArgumentException catch (e) {
  // Invalid input (e.g., startTime > endTime, negative values)
  // Recovery: Validate inputs before calling
  print('Invalid argument: ${e.message}');
} on HealthPlatformUnavailableException catch (e) {
  // Device doesn't support health API
  // Recovery: Disable health features for this device
  print('Health unavailable: ${e.message}');
} on HealthPlatformNotInstalledOrUpdateRequiredException catch (e) {
  // Health Connect needs installation/update (Android Health Connect Only)
  // Recovery: Prompt user to install/update Health Connect
  print('Health Connect needs update: ${e.message}');
} on RemoteErrorException catch (e) {
  // Transient I/O or communication error
  // Recovery: Retry with exponential backoff
  print('Remote error: ${e.message}');
} on HealthConnectorException catch (e) {
  // Generic fallback for unexpected errors
  print('Unknown error [${e.code}]: ${e.message}');
}

Approach 2: Handling by Error Code

Catch the base HealthConnectorException and switch on HealthConnectorErrorCode.

try {
  await connector.requestPermissions([...]);
  await connector.writeRecord(record);
} on HealthConnectorException catch (e) {
  switch (e.code) {
    case HealthConnectorErrorCode.notAuthorized:
      print('Permission denied: ${e.message}');
    case HealthConnectorErrorCode.invalidConfiguration:
      print('Configuration error: ${e.message}');
    case HealthConnectorErrorCode.unsupportedOperation:
      print('Not supported: ${e.message}');
    case HealthConnectorErrorCode.invalidArgument:
      print('Invalid argument: ${e.message}');
    case HealthConnectorErrorCode.healthPlatformUnavailable:
      print('Health unavailable: ${e.message}');
    case HealthConnectorErrorCode.healthPlatformNotInstalledOrUpdateRequired:
      print('Health Connect needs update: ${e.message}');
    case HealthConnectorErrorCode.remoteError:
      print('Remote error: ${e.message}');
    case HealthConnectorErrorCode.unknown:
      print('Unknown error [${e.code}]: ${e.message}');
  }
}

Exception Quick Reference

Exception Cause Recovery
NotAuthorizedException Permission denied/revoked Guide user to settings
InvalidConfigurationException Missing manifest entries Fix configuration
UnsupportedOperationException API not available Check platform first
InvalidArgumentException Invalid input values Validate inputs
HealthPlatformUnavailableException Device unsupported Disable health features
HealthPlatformNotInstalledOrUpdateRequiredException Health Connect app missing Prompt installation

πŸ”§ Troubleshooting #

Common Issues

Issue Platform Solution
HealthPlatformUnavailableException iOS HealthKit Add HealthKit capability in Xcode β†’ Signing & Capabilities
HealthPlatformUnavailableException Android Health Connect Device doesn't support Health Connect (requires Android 8.0+)
HealthPlatformNotInstalledOrUpdateRequiredException Android Health Connect Prompt user to install Health Connect
InvalidConfigurationException Android Health Connect Add required permissions to AndroidManifest.xml
InvalidConfigurationException iOS HealthKit Add NSHealthShareUsageDescription and NSHealthUpdateUsageDescription to Info.plist
Read permissions return unknown iOS HealthKit Normal behaviorβ€”iOS doesn't expose read permission status for privacy
Can't delete/update records Both Apps can only modify records they created

Debug Logging

Enable detailed logs to troubleshoot issues:

final connector = await HealthConnector.create(
  HealthConnectorConfig(isLoggerEnabled: true),
);

❓ FAQ #

Why do iOS read permissions always return unknown?

Apple intentionally hides read permission status to protect user privacy. This prevents apps from inferring whether a user has any health data by checking if read permission was denied.

How do I handle Health Connect not being installed?

final status = await HealthConnector.getHealthPlatformStatus();
if (status == HealthPlatformStatus.installationOrUpdateRequired) {
  // Show dialog prompting user to install Health Connect
  // Open Play Store: https://play.google.com/store/apps/details?id=com.google.android.apps.healthdata
}

What's the difference between heartRateSeriesRecord and heartRateMeasurementRecord?

  • Android Health Connect: Uses heartRateSeriesRecord β€” a single record with multiple samples over a time interval
  • iOS HealthKit: Uses heartRateMeasurementRecord β€” each measurement is a separate record with its own ID

Can I read health data from other apps?

Yes, with user permission. When granted read access, you can read health data from all sources ( other apps, devices, manual entries).

Can I delete health data from other apps?

No. Apps can only delete records they created. This is a platform security restriction.

🎯 Real-World Use Cases #

Fitness Tracker

Track daily activity with steps, calories, and distance:

Future<Map<String, double>> getDailyActivitySummary(
  HealthConnector connector,
  DateTime date,
) async {
  final startOfDay = DateTime(date.year, date.month, date.day);
  final endOfDay = startOfDay.add(Duration(days: 1));

  final steps = await connector.aggregate(
    HealthDataType.steps.aggregateSum(
      startTime: startOfDay,
      endTime: endOfDay,
    ),
  );

  final calories = await connector.aggregate(
    HealthDataType.activeCaloriesBurned.aggregateSum(
      startTime: startOfDay,
      endTime: endOfDay,
    ),
  );

  return {
    'steps': steps.value.value,
    'calories': calories.value.inKilocalories,
  };
}

Health Dashboard

Display vital signs with recent measurements:

Future<void> displayVitals(HealthConnector connector) async {
  final now = DateTime.now();
  final weekAgo = now.subtract(Duration(days: 7));

  // Get latest weight
  final weightResponse = await connector.readRecords(
    HealthDataType.weight.readInTimeRange(
      startTime: weekAgo,
      endTime: now,
      pageSize: 1,
    ),
  );

  if (weightResponse.records.isNotEmpty) {
    final latestWeight = weightResponse.records.first as WeightRecord;
    print('Latest weight: ${latestWeight.weight.inKilograms} kg');
  }

  // Get heart rate average
  final heartRateAvg = await connector.aggregate(
    HealthDataType.restingHeartRate.aggregateAvg(
      startTime: weekAgo,
      endTime: now,
    ),
  );
  print('Avg resting HR: ${heartRateAvg.value.inBeatsPerMinute} bpm');
}

Nutrition Logger

Log meals with macronutrients:

Future<void> logMeal({
  required HealthConnector connector,
  required String mealName,
  required double calories,
  required double proteinGrams,
  required double carbsGrams,
  required double fatGrams,
}) async {
  final now = DateTime.now();

  final nutritionRecord = NutritionRecord(
    id: HealthRecordId.none,
    startTime: now.subtract(Duration(minutes: 30)),
    endTime: now,
    mealType: MealType.lunch,
    name: mealName,
    energy: Energy.kilocalories(calories),
    protein: Mass.grams(proteinGrams),
    totalCarbohydrate: Mass.grams(carbsGrams),
    totalFat: Mass.grams(fatGrams),
    metadata: Metadata.manual(),
  );

  await connector.writeRecord(nutritionRecord);
  print('Meal logged: $mealName');
}

πŸ“š References #

πŸ“‹ Supported Health Data Types #

πŸƒ Activity

General Activity
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Steps Number of steps taken StepsRecord HKQuantityTypeIdentifier.stepCount HealthDataType.steps Sum
Active Calories Burned Energy burned through active movement ActiveCaloriesBurnedRecord HKQuantityTypeIdentifier.activeEnergyBurned HealthDataType.activeCaloriesBurned Sum
Floors Climbed Number of floors (flights of stairs) climbed FloorsClimbedRecord HKQuantityTypeIdentifier.flightsClimbed HealthDataType.floorsClimbed Sum
Sexual Activity Sexual activity tracking SexualActivityRecord HKCategoryTypeIdentifier.sexualActivity HealthDataType.sexualActivity -
Wheelchair Pushes Number of wheelchair pushes WheelchairPushesRecord HKQuantityTypeIdentifier.pushCount HealthDataType.wheelchairPushes Sum
Distance Types
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Distance (generic) Generic distance traveled DistanceRecord ❌ HealthDataType.distance Sum
Walking/Running Distance Distance covered by walking or running ❌ HKQuantityTypeIdentifier.distanceWalkingRunning HealthDataType.walkingRunningDistance Sum
Cycling Distance Distance covered by cycling ❌ HKQuantityTypeIdentifier.distanceCycling HealthDataType.cyclingDistance Sum
Swimming Distance Distance covered by swimming ❌ HKQuantityTypeIdentifier.distanceSwimming HealthDataType.swimmingDistance Sum
Wheelchair Distance Distance covered using a wheelchair ❌ HKQuantityTypeIdentifier.distanceWheelchair HealthDataType.wheelchairDistance Sum
Downhill Snow Sports Distance Distance covered during downhill snow sports ❌ HKQuantityTypeIdentifier.distanceDownhillSnowSports HealthDataType.downhillSnowSportsDistance Sum
Cross Country Skiing Distance Distance covered during cross country skiing ❌ HKQuantityTypeIdentifier.distanceCrossCountrySkiing HealthDataType.crossCountrySkiingDistance Sum
Paddle Sports Distance Distance covered during paddle sports ❌ HKQuantityTypeIdentifier.distancePaddleSports HealthDataType.paddleSportsDistance Sum
Rowing Distance Distance covered during rowing ❌ HKQuantityTypeIdentifier.distanceRowing HealthDataType.rowingDistance Sum
Skating Sports Distance Distance covered during skating sports ❌ HKQuantityTypeIdentifier.distanceSkatingSports HealthDataType.skatingSportsDistance Sum
Six Minute Walk Test Distance Distance covered during 6-minute walk test ❌ HKQuantityTypeIdentifier.sixMinuteWalkTestDistance HealthDataType.sixMinuteWalkTestDistance Sum
Speed Types
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Speed Series Speed measurements over time SpeedRecord ❌ HealthDataType.speedSeries -
Walking Speed Walking speed measurement ❌ HKQuantityTypeIdentifier.walkingSpeed HealthDataType.walkingSpeed -
Running Speed Running speed measurement ❌ HKQuantityTypeIdentifier.runningSpeed HealthDataType.runningSpeed -
Stair Ascent Speed Speed while climbing stairs ❌ HKQuantityTypeIdentifier.stairAscentSpeed HealthDataType.stairAscentSpeed -
Stair Descent Speed Speed while descending stairs ❌ HKQuantityTypeIdentifier.stairDescentSpeed HealthDataType.stairDescentSpeed -
Power Types
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Power Series Power measurements over time PowerRecord ❌ HealthDataType.powerSeries Avg, Min, Max
Cycling Power Power output during cycling ❌ HKQuantityTypeIdentifier.cyclingPower HealthDataType.cyclingPower Avg, Min, Max
Exercise Sessions
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Exercise Session Complete workout session with exercise type and stats ExerciseSessionRecord HKWorkout HealthDataType.exerciseSession Duration

The SDK supports 100+ exercise types across both platforms. For complete exercise type documentation, please see the ExerciseType enum documentation.

πŸ“ Body Measurements

Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Weight Body weight measurement WeightRecord HKQuantityTypeIdentifier.bodyMass HealthDataType.weight Avg, Min, Max
Height Body height measurement HeightRecord HKQuantityTypeIdentifier.height HealthDataType.height Avg, Min, Max
Body Fat Percentage Percentage of body fat BodyFatRecord HKQuantityTypeIdentifier.bodyFatPercentage HealthDataType.bodyFatPercentage Avg, Min, Max
Lean Body Mass Mass of body excluding fat LeanBodyMassRecord HKQuantityTypeIdentifier.leanBodyMass HealthDataType.leanBodyMass Avg, Min, Max
Body Temperature Core body temperature BodyTemperatureRecord HKQuantityTypeIdentifier.bodyTemperature HealthDataType.bodyTemperature Avg, Min, Max

❀️ Vitals

Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Heart Rate Series Heart rate measurements over time HeartRateRecord ❌ HealthDataType.heartRateSeriesRecord Avg, Min, Max
Heart Rate Measurement Single heart rate measurement ❌ HKQuantityTypeIdentifier.heartRate HealthDataType.heartRateMeasurementRecord Avg, Min, Max
Resting Heart Rate Heart rate while at rest RestingHeartRateRecord HKQuantityTypeIdentifier.restingHeartRate HealthDataType.restingHeartRate Avg, Min, Max
Blood Pressure Systolic and diastolic blood pressure BloodPressureRecord HKCorrelationTypeIdentifier.bloodPressure HealthDataType.bloodPressure Avg, Min, Max
Systolic Blood Pressure Upper blood pressure value ❌ HKQuantityTypeIdentifier.bloodPressureSystolic HealthDataType.systolicBloodPressure Avg, Min, Max
Diastolic Blood Pressure Lower blood pressure value ❌ HKQuantityTypeIdentifier.bloodPressureDiastolic HealthDataType.diastolicBloodPressure Avg, Min, Max
Oxygen Saturation Blood oxygen saturation percentage OxygenSaturationRecord HKQuantityTypeIdentifier.oxygenSaturation HealthDataType.oxygenSaturation Avg, Min, Max
Respiratory Rate Breathing rate (breaths per minute) RespiratoryRateRecord HKQuantityTypeIdentifier.respiratoryRate HealthDataType.respiratoryRate Avg, Min, Max
VOβ‚‚ Max Maximum oxygen consumption Vo2MaxRecord HKQuantityTypeIdentifier.vo2Max HealthDataType.vo2Max Avg, Min, Max
Blood Glucose Blood glucose concentration BloodGlucoseRecord HKQuantityTypeIdentifier.bloodGlucose HealthDataType.bloodGlucose Avg, Min, Max

😴 Sleep

Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Sleep Session Complete sleep session with sleep stages SleepSessionRecord ❌ HealthDataType.sleepSession -
Sleep Stage Record Individual sleep stage measurement ❌ HKCategoryTypeIdentifier.sleepAnalysis HealthDataType.sleepStageRecord -

πŸ˜‹ Nutrition

Core & Hydration
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Nutrition (composite) Complete nutrition record with macros and micronutrients NutritionRecord HKCorrelationType.food HealthDataType.nutrition -
Energy Total energy intake from food NutritionRecord (NutritionRecord.energy field) HKQuantityTypeIdentifier.dietaryEnergyConsumed HealthDataType.energyNutrient (iOS HealthKit Only) Sum
Hydration/Water Water and fluid intake HydrationRecord HKQuantityTypeIdentifier.dietaryWater HealthDataType.hydration Sum
Macronutrients
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Protein Protein intake NutritionRecord (NutritionRecord.protein) HKQuantityTypeIdentifier.dietaryProtein HealthDataType.protein (iOS HealthKit Only) Sum
Total Carbohydrate Total carbs intake NutritionRecord (NutritionRecord.carbs) HKQuantityType Identifier.dietaryCarbohydrates HealthDataType.totalCarbohydrate (iOS HealthKit Only) Sum
Total Fat Total fat intake NutritionRecord (NutritionRecord.totalFat) HKQuantityTypeIdentifier.dietaryFatTotal HealthDataType.totalFat (iOS HealthKit Only) Sum
Caffeine Caffeine intake NutritionRecord (NutritionRecord.caffeine) HKQuantityTypeIdentifier.dietaryCaffeine HealthDataType.caffeine (iOS HealthKit Only) Sum
Fats
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Saturated Fat Saturated fat intake NutritionRecord (NutritionRecord.saturatedFat) HKQuantityTypeIdentifier.dietaryFatSaturated HealthDataType.saturatedFat (iOS HealthKit Only) Sum
Monounsaturated Fat Monounsaturated fat intake NutritionRecord (NutritionRecord.monounsaturatedFat) HKQuantityTypeIdentifier.dietaryFatMonounsaturated HealthDataType.monounsaturatedFat (iOS HealthKit Only) Sum
Polyunsaturated Fat Polyunsaturated fat intake NutritionRecord (NutritionRecord.polyunsaturatedFat) HKQuantityTypeIdentifier.dietaryFatPolyunsaturated HealthDataType.polyunsaturatedFat (iOS HealthKit Only) Sum
Cholesterol Cholesterol intake NutritionRecord (NutritionRecord.cholesterol) HKQuantityTypeIdentifier.dietaryCholesterol HealthDataType.cholesterol (iOS HealthKit Only) Sum
Fiber & Sugar
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Dietary Fiber Dietary fiber intake NutritionRecord (NutritionRecord.dietaryFiber) HKQuantityTypeIdentifier.dietaryFiber HealthDataType.dietaryFiber (iOS HealthKit Only) Sum
Sugar Sugar intake NutritionRecord (NutritionRecord.sugar) HKQuantityTypeIdentifier.dietarySugar HealthDataType.sugar (iOS HealthKit Only) Sum
Minerals
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Calcium Calcium intake NutritionRecord (NutritionRecord.calcium) HKQuantityTypeIdentifier.dietaryCalcium HealthDataType.calcium (iOS HealthKit Only) Sum
Iron Iron intake NutritionRecord (NutritionRecord.iron) HKQuantityTypeIdentifier.dietaryIron HealthDataType.iron (iOS HealthKit Only) Sum
Magnesium Magnesium intake NutritionRecord (NutritionRecord.magnesium) HKQuantityTypeIdentifier.dietaryMagnesium HealthDataType.magnesium (iOS HealthKit Only) Sum
Manganese Manganese intake NutritionRecord (NutritionRecord.manganese) HKQuantityTypeIdentifier.dietaryManganese HealthDataType.manganese (iOS HealthKit Only) Sum
Phosphorus Phosphorus intake NutritionRecord (NutritionRecord.phosphorus) HKQuantityTypeIdentifier.dietaryPhosphorus HealthDataType.phosphorus (iOS HealthKit Only) Sum
Potassium Potassium intake NutritionRecord (NutritionRecord.potassium) HKQuantityTypeIdentifier.dietaryPotassium HealthDataType.potassium (iOS HealthKit Only) Sum
Selenium Selenium intake NutritionRecord (NutritionRecord.selenium) HKQuantityTypeIdentifier.dietarySelenium HealthDataType.selenium (iOS HealthKit Only) Sum
Sodium Sodium intake NutritionRecord (NutritionRecord.sodium) HKQuantityTypeIdentifier.dietarySodium HealthDataType.sodium (iOS HealthKit Only) Sum
Zinc Zinc intake NutritionRecord (NutritionRecord.zinc) HKQuantityTypeIdentifier.dietaryZinc HealthDataType.zinc (iOS HealthKit Only) Sum
B Vitamins
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Thiamin (B1) Thiamin (vitamin B1) intake NutritionRecord (NutritionRecord.thiamin) HKQuantityTypeIdentifier.dietaryThiamin HealthDataType.thiamin (iOS HealthKit Only) Sum
Riboflavin (B2) Riboflavin (vitamin B2) NutritionRecord (NutritionRecord.riboflavin) HKQuantityTypeIdentifier.dietaryRiboflavin HealthDataType.riboflavin (iOS HealthKit Only) Sum
Niacin (B3) Niacin (vitamin B3) intake NutritionRecord (NutritionRecord.niacin) HKQuantityTypeIdentifier.dietaryNiacin HealthDataType.niacin (iOS HealthKit Only) Sum
Pantothenic Acid (B5) Pantothenic acid (vitamin B5) NutritionRecord (NutritionRecord.pantothenicAcid) HKQuantityTypeIdentifier.dietaryPantothenicAcid HealthDataType.pantothenicAcid (iOS HealthKit Only) Sum
Vitamin B6 Vitamin B6 intake NutritionRecord (NutritionRecord.vitaminB6) HKQuantityTypeIdentifier.dietaryVitaminB6 HealthDataType.vitaminB6 (iOS HealthKit Only) Sum
Biotin (B7) Biotin (vitamin B7) intake NutritionRecord (NutritionRecord.biotin) HKQuantityTypeIdentifier.dietaryBiotin HealthDataType.biotin (iOS HealthKit Only) Sum
Folate (B9) Folate (vitamin B9) intake NutritionRecord (NutritionRecord.folate) HKQuantityTypeIdentifier.dietaryFolate HealthDataType.folate (iOS HealthKit Only) Sum
Vitamin B12 Vitamin B12 intake NutritionRecord (NutritionRecord.vitaminB12) HKQuantityTypeIdentifier.dietaryVitaminB12 HealthDataType.vitaminB12 (iOS HealthKit Only) Sum
Other Vitamins
Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Vitamin A Vitamin A intake NutritionRecord (NutritionRecord.vitaminA) HKQuantityTypeIdentifier.dietaryVitaminA HealthDataType.vitaminA (iOS HealthKit Only) Sum
Vitamin C Vitamin C intake NutritionRecord (NutritionRecord.vitaminC) HKQuantityTypeIdentifier.dietaryVitaminC HealthDataType.vitaminC (iOS HealthKit Only) Sum
Vitamin D Vitamin D intake NutritionRecord (NutritionRecord.vitaminD) HKQuantityTypeIdentifier.dietaryVitaminD HealthDataType.vitaminD (iOS HealthKit Only) Sum
Vitamin E Vitamin E intake NutritionRecord (NutritionRecord.vitaminE) HKQuantityTypeIdentifier.dietaryVitaminE HealthDataType.vitaminE (iOS HealthKit Only) Sum
Vitamin K Vitamin K intake NutritionRecord (NutritionRecord.vitaminK) HKQuantityTypeIdentifier.dietaryVitaminK HealthDataType.vitaminK (iOS HealthKit Only) Sum

🧘 Wellness

Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Mindfulness Session Meditation and mindfulness sessions MindfulnessSessionRecord HKCategoryTypeIdentifier.mindfulSession HealthDataType.mindfulnessSession Sum

πŸͺ· Cycle Tracking

Data Type Description Android Health Connect iOS HealthKit SDK Data Type Aggregation
Cervical Mucus Cervical mucus observations for fertility CervicalMucusRecord HKCategoryTypeIdentifier.cervicalMucusQuality HealthDataType.cervicalMucus -

πŸ”„ Migration Guides #

  • Migration Guide from v1.x.x to v2.x.x

🀝 Contributing #

Contributions are welcome! See our GitHub Issues to report bugs or request features.

πŸ“„ License #

This project is licensed under the Apache 2.0 License - see the LICENSE file for details.

14
likes
0
points
1.05k
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin to access health data from Android Health Connect and iOS HealthKit

Homepage
Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, health_connector_core, health_connector_hc_android, health_connector_hk_ios, health_connector_logger, meta

More

Packages that depend on health_connector