health_connector 2.4.0
health_connector: ^2.4.0 copied to clipboard
The most comprehensive Flutter health plugin for seamless iOS HealthKit and Android Health Connect integration.
health_connector #
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 #
๐ฎ See It In Action โ Interactive Toolbox Demo #
See what's possible. The Health Connector Toolbox showcases the full power of the SDK with live, interactive demonstrations running on both iOS and Android.
| ๐ Permissions | ๐ Read | โ๏ธ Write | ๐๏ธ Delete | ๐ Aggregate |
|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
๐ Try It Yourself #
git clone https://github.com/fam-tung-lam/health_connector.git
cd health_connector/examples/health_connector_toolbox
flutter pub get && flutter run
Explore:
- ๐ Permission flows for HealthKit & Health Connect
- ๐ Real-time health data visualization
- โ๏ธ CRUD operations with live feedback
- ๐งช Feature detection and platform capabilities
๐ก Note: The toolbox is a demonstration toolโperfect for exploring APIs, not for production reference.
๐ 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
Step 1: 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.
Step 2: 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
}
Step 3: 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
Step 4: Set Minimum Android Version
Health Connect requires Android 8.0 (API 26) or higher. Update android/app/build.gradle:
android {
// Your existing configuration
defaultConfig {
// Your existing configuration
minSdkVersion 26 // Required for Health Connect
}
}
๐ iOS HealthKit Setup
Step 1: Configure Xcode
- Open your project in Xcode (
ios/Runner.xcworkspace) - Select your app target
- In General tab โ Set Minimum Deployments to 15.0
- In Signing & Capabilities tab โ Click + Capability โ Add HealthKit
Step 2: 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(
const HealthConnectorConfig(isLoggerEnabled: true),
);
// 3. Request permissions
final results = await connector.requestPermissions([
HealthDataType.steps.readPermission,
HealthDataType.steps.writePermission,
]);
// 4. Verify permissions were granted
final granted = results.every((r) => r.status != PermissionStatus.denied);
if (!granted) {
print('Permissions denied');
return;
}
// 5. Write health data
final now = DateTime.now();
final records = [
_createStepsRecord(now.subtract(Duration(hours: 3)), 1500),
_createStepsRecord(now.subtract(Duration(hours: 2)), 2000),
_createStepsRecord(now.subtract(Duration(hours: 1)), 1800),
];
final recordIds = await connector.writeRecords(records);
print('โ
Wrote ${recordIds.length} records');
// 6. Read health data
final response = await connector.readRecords(
HealthDataType.steps.readInTimeRange(
startTime: now.subtract(Duration(days: 1)),
endTime: now,
),
);
print('๐ Found ${response.records.length} records:');
for (final record in response.records) {
print(' โ ${record.count.value} steps (${record.startTime})');
}
}
// Helper to create step records
StepsRecord _createStepsRecord(DateTime time, int steps) {
return StepsRecord(
startTime: time,
endTime: time.add(Duration(hours: 1)),
count: Number(steps),
metadata: Metadata.automaticallyRecorded(
dataOrigin: DataOrigin('com.example'),
device: Device.fromType(DeviceType.phone),
),
);
}
๐ก What's Next? Check out the Developer Guide for full API documentation, error handling, and advanced features.
๐ Developer Guide #
๐ Permission Management #
Request Permissions
final permissions = [
HealthDataType.steps.readPermission,
HealthDataType.steps.writePermission,
HealthDataType.weight.readPermission,
HealthPlatformFeature.readHealthDataInBackground.permission,
];
final results = await connector.requestPermissions(permissions);
// Process results
for (final result in results) {
if (result.status == PermissionStatus.granted) {
print('โ
${result.permission}');
} else if (result.status == PermissionStatus.unknown) {
print('โ ${result.permission} (iOS read permission)');
}
}
iOS Privacy: Read permissions always return
unknownto prevent apps from inferring whether users have health data.
Check Permission Status
final status = await connector.getPermissionStatus(
HealthDataType.steps.readPermission,
);
switch (status) {
case PermissionStatus.granted:
// Permission granted
case PermissionStatus.denied:
// Permission denied
case PermissionStatus.unknown:
// iOS read permission (cannot determine)
}
iOS Read Permission Workaround
Strategy: Attempt a minimal read operation and catch NotAuthorizedException.
Future<bool> hasReadPermission(HealthDataType dataType) async {
try {
await connector.readRecords(
dataType.readInTimeRange(
startTime: DateTime.now().subtract(Duration(days: 1)),
endTime: DateTime.now(),
pageSize: 1,
),
);
return true; // Read succeeded = permission granted
} on NotAuthorizedException {
return false; // Permission denied
}
}
Disclaimer: Not officially recommended by Apple. Use only if your app genuinely needs to determine read permission status.
Get All Granted Permissions (Android only)
iOS Privacy: HealthKit doesn't allow apps to enumerate granted permissions.
try {
final granted = await connector.getGrantedPermissions();
for (final p in granted) {
print('${p.dataType} (${p.accessType})');
}
} on UnsupportedOperationException {
// iOS doesn't support this API
}
Revoke All Permissions (Android only)
iOS Privacy: Not supported by HealthKit. Users must revoke permissions manually via Settings app.
try {
await connector.revokeAllPermissions();
} on UnsupportedOperationException {
// iOS users must revoke via Settings app
}
๐ Reading Health Data #
Read by ID
final record = await connector.readRecord(
HealthDataType.steps.readRecord(HealthRecordId('record-id')),
);
if (record != null) {
print('โ
Found: ${record.count.value} steps');
}
Read by Time Range
final response = await connector.readRecords(
HealthDataType.steps.readInTimeRange(
startTime: DateTime.now().subtract(Duration(days: 7)),
endTime: DateTime.now(),
pageSize: 100,
),
);
print('๐ Found ${response.records.length} records');
for (final record in response.records) {
print('${record.count.value} steps on ${record.startTime}');
}
Historical Data Access: Android Health Connect defaults to 30 daysโrequest
HealthPlatformFeature.readHealthDataHistorypermission for older data. iOS HealthKit has no restrictions.
Paginate Through All Records
var request = HealthDataType.steps.readInTimeRange(
startTime: DateTime.now().subtract(Duration(days: 30)),
endTime: DateTime.now(),
pageSize: 100,
);
final allRecords = <StepsRecord>[];
// Fetch all pages
while (true) {
final response = await connector.readRecords(request);
allRecords.addAll(response.records.cast<StepsRecord>());
// Check if there are more pages
if (response.nextPageRequest == null) break;
request = response.nextPageRequest!;
}
print('๐ Total: ${allRecords.length} records');
โ๏ธ Writing Health Data #
Write Single Record
final record = StepsRecord(
id: HealthRecordId.none, // Must be .none for new records
startTime: DateTime.now().subtract(Duration(hours: 1)),
endTime: DateTime.now(),
count: Number(5000),
metadata: Metadata.automaticallyRecorded(
device: Device.fromType(DeviceType.phone),
),
);
final recordId = await connector.writeRecord(record);
print('โ
Saved: $recordId');
Batch Write Multiple Records
All records succeed or all fail together:
// Helper to create step records
StepsRecord _createSteps(DateTime time, int steps) => StepsRecord(
id: HealthRecordId.none,
startTime: time,
endTime: time.add(Duration(hours: 1)),
count: Number(steps),
metadata: Metadata.automaticallyRecorded(
device: Device.fromType(DeviceType.phone),
),
);
final now = DateTime.now();
final records = [
_createSteps(now.subtract(Duration(hours: 3)), 1500),
_createSteps(now.subtract(Duration(hours: 2)), 2000),
_createSteps(now.subtract(Duration(hours: 1)), 1800),
];
final ids = await connector.writeRecords(records);
print('โ
Wrote ${ids.length} records');
๐ Updating Health Records #
iOS Note: HealthKit uses an immutable data modelโrecords cannot be updated, only deleted and recreated.
Update Single Record (Android only)
final record = await connector.readRecord(
HealthDataType.steps.readRecord(HealthRecordId('record-id')),
);
if (record != null) {
await connector.updateRecord(
record.copyWith(count: Number(record.count.value + 500)),
);
print('โ
Record updated');
}
Batch Update (Android only)
Update multiple records atomicallyโall succeed or all fail.
// Fetch records to update
final response = await connector.readRecords(
HealthDataType.steps.readInTimeRange(
startTime: DateTime.now().subtract(Duration(days: 7)),
endTime: DateTime.now(),
),
);
// Apply updates
final updated = response.records.map((r) =>
r.copyWith(count: Number(r.count.value + 100))
).toList();
await connector.updateRecords(updated);
print('โ
Updated ${updated.length} records');
iOS Workaround: Delete + Recreate
// Delete existing
await connector.deleteRecords(
HealthDataType.steps.deleteByIds([existingRecord.id]),
);
// Write new record with updated values
final newRecord = existingRecord.copyWith(
id: HealthRecordId.none,
count: Number(newValue),
);
final newId = await connector.writeRecord(newRecord);
// โ ๏ธ Note: ID changes after recreation
๐๏ธ Deleting Health Records #
Limitation: Apps can only delete records they createdโplatform security restriction.
Delete by IDs
try {
await connector.deleteRecords(
HealthDataType.steps.deleteByIds([
HealthRecordId('id-1'),
HealthRecordId('id-2'),
]),
);
print('โ
Deleted');
} on NotAuthorizedException {
print('โ Cannot delete records from other apps');
}
Delete by Time Range
await connector.deleteRecords(
HealthDataType.steps.deleteInTimeRange(
startTime: DateTime.now().subtract(Duration(days: 7)),
endTime: DateTime.now(),
),
);
๐ Aggregating Health Data #
Example: Sum
final response = await connector.aggregate(
HealthDataType.steps.aggregateSum(
startTime: DateTime.now().subtract(Duration(days: 1)),
endTime: DateTime.now(),
),
);
print('๐ Total steps: ${response.value.value}');
Example: Average, Min, Max
final now = DateTime.now();
final thirtyDaysAgo = now.subtract(Duration(days: 30));
// Get average weight
final avg = await connector.aggregate(
HealthDataType.weight.aggregateAvg(
startTime: thirtyDaysAgo,
endTime: now,
),
);
// Get min/max weight
final min = await connector.aggregate(
HealthDataType.weight.aggregateMin(
startTime: thirtyDaysAgo,
endTime: now,
),
);
// Get min/max weight
final max = await connector.aggregate(
HealthDataType.weight.aggregateMax(
startTime: thirtyDaysAgo,
endTime: now,
),
);
print('Avg: ${avg.value.inKilograms} kg');
print('Min: ${min.value.inKilograms} kg');
print('Max: ${max.value.inKilograms} kg');
โ๏ธ Feature Management #
Platform Behavior: iOS HealthKit features are always available (built into iOS). Android Health Connect features depend on app versionโcheck
getFeatureStatus()before requesting permissions.
Check Feature Availability
final status = await connector.getFeatureStatus(
HealthPlatformFeature.readHealthDataInBackground,
);
if (status == HealthPlatformFeatureStatus.available) {
await connector.requestPermissions([
HealthPlatformFeature.readHealthDataInBackground.permission,
]);
print('โ
Feature available and requested');
} else {
print('โ Feature not availableโimplement fallback');
}
// Note: iOS always returns 'available', Android returns actual status
โ ๏ธ Error Handling #
Exception Quick Reference
| Exception | Recovery Strategy |
|---|---|
NotAuthorizedException |
Guide user to System Settings to enable permissions |
HealthPlatformUnavailableException |
Disable health features gracefully (device unsupported) |
InvalidConfigurationException |
Dev error: check AndroidManifest.xml / Info.plist |
UnsupportedOperationException |
Check getFeatureStatus() before calling platform-specific APIs |
Standard Exception Handling
try {
await connector.writeRecord(record);
} on NotAuthorizedException catch (e) {
print('โ Permission denied: ${e.message}');
// Show UI prompting user to check settings
} on HealthPlatformUnavailableException {
print('โ Health API unavailable on this device');
} on HealthConnectorException catch (e) {
print('โ Error [${e.code}]: ${e.message}');
}
๐ Logging #
Zero-intrusion: Logs are emitted to a stream (
HealthConnectorLogger.logs) and never printed automatically. You control the output.
Setup & Subscribing
// 1. Enable logging during initialization
final connector = await HealthConnector.create(
const HealthConnectorConfig(isLoggerEnabled: true),
);
// 2. Subscribe and filter
HealthConnectorLogger.logs
.where((log) => log.level == HealthConnectorLogLevel.error) // Optional filter
.listen((log) {
print(log.structuredMessage);
// OR send to Crashlytics:
// Crashlytics.recordError(log.exception, log.stackTrace, reason: log.message);
});
Log Structure Example
[HEALTHCONNECTOR] [INFO]:
{
datetime: 06-01-2026 18:15:32.456,
message: HealthConnector created successfully,
operation: create,
context: { platform: healthConnect },
}
[HEALTHCONNECTOR] [ERROR]:
{
datetime: 06-01-2026 18:15:34.123,
message: Failed to read records,
exception: { cause: NotAuthorizedException... },
}
๐ง Troubleshooting & FAQ #
| Issue / Question | Platform / Context | Solution / Answer |
|---|---|---|
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 | Check getHealthPlatformStatus() and call launchHealthAppPageInAppStore() to open Play Store |
InvalidConfigurationException |
Android Health Connect | Add required permissions to AndroidManifest.xml |
InvalidConfigurationException |
iOS HealthKit | Add NSHealthShareUsageDescription and NSHealthUpdateUsageDescription to Info.plist |
Why do iOS read permissions return unknown? |
iOS HealthKit | Apple hides read permission status to protect privacy โ apps cannot infer if a user has health data |
What's the difference between heartRateSeriesRecord and heartRateMeasurementRecord? |
Cross-platform | Android uses series records (multiple samples in one record); iOS uses individual measurement records |
| Can I read health data from other apps? | Both platforms | Yes โ with user permission, you can read data from all sources (apps, devices, manual entries) |
| Can I modify/delete data from other apps? | Both platforms | No โ apps can only modify or delete records they created (platform security restriction) |
๐ฏ Real-World Use Cases #
๐ Fitness Dashboard
// Get daily summary: steps & calories
Future<Map<String, double>> getDailySummary(HealthConnector connector) async {
final now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
final tomorrow = today.add(Duration(days: 1));
final steps = await connector.aggregate(
HealthDataType.steps.aggregateSum(startTime: today, endTime: tomorrow),
);
final calories = await connector.aggregate(
HealthDataType.activeCaloriesBurned.aggregateSum(startTime: today, endTime: tomorrow),
);
return {
'steps': steps.value.value,
'calories': calories.value.inKilocalories,
};
}
โค๏ธ Vitals Monitor
Future<void> logVitals(HealthConnector connector) async {
final weekAgo = DateTime.now().subtract(Duration(days: 7));
final now = DateTime.now();
// 1. Get latest weight
final weight = await connector.readRecords(
HealthDataType.weight.readInTimeRange(
startTime: weekAgo, endTime: now, pageSize: 1,
),
);
if (weight.records.isNotEmpty) {
print('โ๏ธ Latest weight: ${(weight.records.first as WeightRecord).weight.inKilograms} kg');
}
// 2. Get avg resting heart rate
final hr = await connector.aggregate(
HealthDataType.restingHeartRate.aggregateAvg(startTime: weekAgo, endTime: now),
);
print('๐ Avg Resting HR: ${hr.value.inBeatsPerMinute} bpm');
}
๐ฅ Nutrition Tracker
Future<void> logLunch(HealthConnector connector) async {
final entry = NutritionRecord(
id: HealthRecordId.none,
startTime: DateTime.now().subtract(Duration(minutes: 30)),
endTime: DateTime.now(),
name: 'Grilled Chicken Salad',
energy: Energy.kilocalories(450),
protein: Mass.grams(40),
totalCarbohydrate: Mass.grams(12),
totalFat: Mass.grams(15),
metadata: Metadata.manual(),
);
await connector.writeRecord(entry);
print('โ
Meal logged');
}
๐ References #
๐ Supported Health Data Types #
๐ Activity
General Activity
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Steps | Number of steps taken | HealthDataType.steps |
Sum | StepsRecord | HKQuantityTypeIdentifier.stepCount |
| Active Calories Burned | Energy burned through active movement | HealthDataType.activeCaloriesBurned |
Sum | ActiveCaloriesBurnedRecord | HKQuantityTypeIdentifier.activeEnergyBurned |
| Floors Climbed | Number of floors (flights of stairs) climbed | HealthDataType.floorsClimbed |
Sum | FloorsClimbedRecord | HKQuantityTypeIdentifier.flightsClimbed |
| Sexual Activity | Sexual activity tracking | HealthDataType.sexualActivity |
- | SexualActivityRecord | HKCategoryTypeIdentifier.sexualActivity |
| Wheelchair Pushes | Number of wheelchair pushes | HealthDataType.wheelchairPushes |
Sum | WheelchairPushesRecord | HKQuantityTypeIdentifier.pushCount |
| Cycling Cadence | Cycling pedaling cadence | HealthDataType.cyclingPedalingCadence |
Avg, Min, Max | CyclingPedalingCadenceRecord | HKQuantityTypeIdentifier.cyclingCadence |
| Total Calories Burned | Total energy burned (active + basal) | HealthDataType.totalCaloriesBurned |
Sum | TotalCaloriesBurnedRecord | - |
| Basal Energy Burned | Energy burned by basal metabolism | HealthDataType.basalEnergyBurned |
Sum | - | HKQuantityTypeIdentifier.basalEnergyBurned |
Distance Types
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Distance (generic) | Generic distance traveled | HealthDataType.distance |
Sum | DistanceRecord | - |
| Walking/Running Distance | Distance covered by walking or running | HealthDataType.walkingRunningDistance |
Sum | - | HKQuantityTypeIdentifier.distanceWalkingRunning |
| Cycling Distance | Distance covered by cycling | HealthDataType.cyclingDistance |
Sum | - | HKQuantityTypeIdentifier.distanceCycling |
| Swimming Distance | Distance covered by swimming | HealthDataType.swimmingDistance |
Sum | - | HKQuantityTypeIdentifier.distanceSwimming |
| Wheelchair Distance | Distance covered using a wheelchair | HealthDataType.wheelchairDistance |
Sum | - | HKQuantityTypeIdentifier.distanceWheelchair |
| Downhill Snow Sports Distance | Distance covered during downhill snow sports | HealthDataType.downhillSnowSportsDistance |
Sum | - | HKQuantityTypeIdentifier.distanceDownhillSnowSports |
| Cross Country Skiing Distance | Distance covered during cross country skiing | HealthDataType.crossCountrySkiingDistance |
Sum | - | HKQuantityTypeIdentifier.distanceCrossCountrySkiing |
| Paddle Sports Distance | Distance covered during paddle sports | HealthDataType.paddleSportsDistance |
Sum | - | HKQuantityTypeIdentifier.distancePaddleSports |
| Rowing Distance | Distance covered during rowing | HealthDataType.rowingDistance |
Sum | - | HKQuantityTypeIdentifier.distanceRowing |
| Skating Sports Distance | Distance covered during skating sports | HealthDataType.skatingSportsDistance |
Sum | - | HKQuantityTypeIdentifier.distanceSkatingSports |
| Six Minute Walk Test Distance | Distance covered during 6-minute walk test | HealthDataType.sixMinuteWalkTestDistance |
Sum | - | HKQuantityTypeIdentifier.sixMinuteWalkTestDistance |
Speed Types
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Speed Series | Speed measurements over time | HealthDataType.speedSeries |
- | SpeedRecord | - |
| Walking Speed | Walking speed measurement | HealthDataType.walkingSpeed |
- | - | HKQuantityTypeIdentifier.walkingSpeed |
| Running Speed | Running speed measurement | HealthDataType.runningSpeed |
- | - | HKQuantityTypeIdentifier.runningSpeed |
| Stair Ascent Speed | Speed while climbing stairs | HealthDataType.stairAscentSpeed |
- | - | HKQuantityTypeIdentifier.stairAscentSpeed |
| Stair Descent Speed | Speed while descending stairs | HealthDataType.stairDescentSpeed |
- | - | HKQuantityTypeIdentifier.stairDescentSpeed |
Power Types
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Power Series | Power measurements over time | HealthDataType.powerSeries |
Avg, Min, Max | PowerRecord | - |
| Cycling Power | Power output during cycling | HealthDataType.cyclingPower |
Avg, Min, Max | - | HKQuantityTypeIdentifier.cyclingPower |
Exercise Sessions
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Exercise Session | Complete workout session with exercise type and stats | HealthDataType.exerciseSession |
Duration | ExerciseSessionRecord | HKWorkout |
Exercise Types
| Exercise Type | Android Health Connect | iOS HealthKit |
|---|---|---|
ExerciseType.other |
โ | โ |
ExerciseType.running |
โ | โ |
ExerciseType.runningTreadmill |
โ | โ |
ExerciseType.walking |
โ | โ |
ExerciseType.cycling |
โ | โ |
ExerciseType.cyclingStationary |
โ | โ |
ExerciseType.hiking |
โ | โ |
ExerciseType.handCycling |
โ | โ |
ExerciseType.trackAndField |
โ | โ |
ExerciseType.swimming |
โ | โ |
ExerciseType.swimmingOpenWater |
โ | โ |
ExerciseType.swimmingPool |
โ | โ |
ExerciseType.surfing |
โ | โ |
ExerciseType.waterPolo |
โ | โ |
ExerciseType.rowing |
โ | โ |
ExerciseType.sailing |
โ | โ |
ExerciseType.paddling |
โ | โ |
ExerciseType.diving |
โ | โ |
ExerciseType.waterFitness |
โ | โ |
ExerciseType.waterSports |
โ | โ |
ExerciseType.strengthTraining |
โ | โ |
ExerciseType.weightlifting |
โ | โ |
ExerciseType.calisthenics |
โ | โ |
ExerciseType.basketball |
โ | โ |
ExerciseType.soccer |
โ | โ |
ExerciseType.americanFootball |
โ | โ |
ExerciseType.frisbeeDisc |
โ | โ |
ExerciseType.australianFootball |
โ | โ |
ExerciseType.baseball |
โ | โ |
ExerciseType.softball |
โ | โ |
ExerciseType.volleyball |
โ | โ |
ExerciseType.rugby |
โ | โ |
ExerciseType.cricket |
โ | โ |
ExerciseType.handball |
โ | โ |
ExerciseType.iceHockey |
โ | โ |
ExerciseType.rollerHockey |
โ | โ |
ExerciseType.hockey |
โ | โ |
ExerciseType.lacrosse |
โ | โ |
ExerciseType.discSports |
โ | โ |
ExerciseType.tennis |
โ | โ |
ExerciseType.tableTennis |
โ | โ |
ExerciseType.badminton |
โ | โ |
ExerciseType.squash |
โ | โ |
ExerciseType.racquetball |
โ | โ |
ExerciseType.pickleball |
โ | โ |
ExerciseType.skiing |
โ | โ |
ExerciseType.snowboarding |
โ | โ |
ExerciseType.snowshoeing |
โ | โ |
ExerciseType.skating |
โ | โ |
ExerciseType.crossCountrySkiing |
โ | โ |
ExerciseType.curling |
โ | โ |
ExerciseType.downhillSkiing |
โ | โ |
ExerciseType.snowSports |
โ | โ |
ExerciseType.boxing |
โ | โ |
ExerciseType.kickboxing |
โ | โ |
ExerciseType.martialArts |
โ | โ |
ExerciseType.wrestling |
โ | โ |
ExerciseType.fencing |
โ | โ |
ExerciseType.taiChi |
โ | โ |
ExerciseType.dancing |
โ | โ |
ExerciseType.gymnastics |
โ | โ |
ExerciseType.barre |
โ | โ |
ExerciseType.cardioDance |
โ | โ |
ExerciseType.socialDance |
โ | โ |
ExerciseType.yoga |
โ | โ |
ExerciseType.pilates |
โ | โ |
ExerciseType.highIntensityIntervalTraining |
โ | โ |
ExerciseType.elliptical |
โ | โ |
ExerciseType.exerciseClass |
โ | โ |
ExerciseType.bootCamp |
โ | โ |
ExerciseType.guidedBreathing |
โ | โ |
ExerciseType.stairClimbing |
โ | โ |
ExerciseType.crossTraining |
โ | โ |
ExerciseType.jumpRope |
โ | โ |
ExerciseType.fitnessGaming |
โ | โ |
ExerciseType.mixedCardio |
โ | โ |
ExerciseType.cooldown |
โ | โ |
ExerciseType.flexibility |
โ | โ |
ExerciseType.mindAndBody |
โ | โ |
ExerciseType.preparationAndRecovery |
โ | โ |
ExerciseType.stepTraining |
โ | โ |
ExerciseType.coreTraining |
โ | โ |
ExerciseType.golf |
โ | โ |
ExerciseType.archery |
โ | โ |
ExerciseType.bowling |
โ | โ |
ExerciseType.paragliding |
โ | โ |
ExerciseType.climbing |
โ | โ |
ExerciseType.equestrianSports |
โ | โ |
ExerciseType.fishing |
โ | โ |
ExerciseType.hunting |
โ | โ |
ExerciseType.play |
โ | โ |
ExerciseType.wheelchair |
โ | โ |
ExerciseType.wheelchairWalkPace |
โ | โ |
ExerciseType.wheelchairRunPace |
โ | โ |
ExerciseType.transition |
โ | โ |
ExerciseType.swimBikeRun |
โ | โ |
๐ Body Measurements
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Weight | Body weight measurement | HealthDataType.weight |
Avg, Min, Max | WeightRecord | HKQuantityTypeIdentifier.bodyMass |
| Height | Body height measurement | HealthDataType.height |
Avg, Min, Max | HeightRecord | HKQuantityTypeIdentifier.height |
| Body Fat Percentage | Percentage of body fat | HealthDataType.bodyFatPercentage |
Avg, Min, Max | BodyFatRecord | HKQuantityTypeIdentifier.bodyFatPercentage |
| Lean Body Mass | Mass of body excluding fat | HealthDataType.leanBodyMass |
Avg, Min, Max | LeanBodyMassRecord | HKQuantityTypeIdentifier.leanBodyMass |
| Body Temperature | Core body temperature | HealthDataType.bodyTemperature |
Avg, Min, Max | BodyTemperatureRecord | HKQuantityTypeIdentifier.bodyTemperature |
| Body Water Mass | Mass of body water | HealthDataType.bodyWaterMass |
Avg, Min, Max | BodyWaterMassRecord | - |
| Bone Mass | Mass of bone mineral | HealthDataType.boneMass |
Avg, Min, Max | BoneMassRecord | - |
| Body Mass Index | Body Mass Index (BMI) | HealthDataType.bodyMassIndex |
Avg, Min, Max | - | HKQuantityTypeIdentifier.bodyMassIndex |
| Waist Circumference | Waist circumference measurement | HealthDataType.waistCircumference |
Avg, Min, Max | - | HKQuantityTypeIdentifier.waistCircumference |
โค๏ธ Vitals
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Heart Rate Series | Heart rate measurements over time | HealthDataType.heartRateSeriesRecord |
Avg, Min, Max | HeartRateRecord | - |
| Heart Rate Measurement | Single heart rate measurement | HealthDataType.heartRateMeasurementRecord |
Avg, Min, Max | - | HKQuantityTypeIdentifier.heartRate |
| Resting Heart Rate | Heart rate while at rest | HealthDataType.restingHeartRate |
Avg, Min, Max | RestingHeartRateRecord | HKQuantityTypeIdentifier.restingHeartRate |
| Blood Pressure | Systolic and diastolic blood pressure | HealthDataType.bloodPressure |
Avg, Min, Max | BloodPressureRecord | HKCorrelationTypeIdentifier.bloodPressure |
| Systolic Blood Pressure | Upper blood pressure value | HealthDataType.systolicBloodPressure |
Avg, Min, Max | - | HKQuantityTypeIdentifier.bloodPressureSystolic |
| Diastolic Blood Pressure | Lower blood pressure value | HealthDataType.diastolicBloodPressure |
Avg, Min, Max | - | HKQuantityTypeIdentifier.bloodPressureDiastolic |
| Oxygen Saturation | Blood oxygen saturation percentage | HealthDataType.oxygenSaturation |
Avg, Min, Max | OxygenSaturationRecord | HKQuantityTypeIdentifier.oxygenSaturation |
| Respiratory Rate | Breathing rate (breaths per minute) | HealthDataType.respiratoryRate |
Avg, Min, Max | RespiratoryRateRecord | HKQuantityTypeIdentifier.respiratoryRate |
| VOโ Max | Maximum oxygen consumption | HealthDataType.vo2Max |
Avg, Min, Max | Vo2MaxRecord | HKQuantityTypeIdentifier.vo2Max |
| Blood Glucose | Blood glucose concentration | HealthDataType.bloodGlucose |
Avg, Min, Max | BloodGlucoseRecord | HKQuantityTypeIdentifier.bloodGlucose |
| HRV RMSSD | Heart Rate Variability (RMSSD) | HealthDataType.heartRateVariabilityRmssd |
- | HeartRateVariabilityRmssdRecord | - |
| HRV SDNN | Heart Rate Variability (SDNN) | HealthDataType.heartRateVariabilitySdnn |
- | - | HKQuantityTypeIdentifier.heartRateVariabilitySDNN |
๐ด Sleep
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Sleep Session | Complete sleep session with sleep stages | HealthDataType.sleepSession |
- | SleepSessionRecord | - |
| Sleep Stage Record | Individual sleep stage measurement | HealthDataType.sleepStageRecord |
- | - | HKCategoryTypeIdentifier.sleepAnalysis |
๐ Nutrition
Core & Hydration
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Nutrition (composite) | Complete nutrition record with macros and micronutrients | HealthDataType.nutrition |
- | NutritionRecord | HKCorrelationType.food |
| Energy | Total energy intake from food | HealthDataType.energyNutrient (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.energy field) | HKQuantityTypeIdentifier.dietaryEnergyConsumed |
| Hydration/Water | Water and fluid intake | HealthDataType.hydration |
Sum | HydrationRecord | HKQuantityTypeIdentifier.dietaryWater |
Macronutrients
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Protein | Protein intake | HealthDataType.protein (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.protein) | HKQuantityTypeIdentifier.dietaryProtein |
| Total Carbohydrate | Total carbs intake | HealthDataType.totalCarbohydrate (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.carbs) | HKQuantityType Identifier.dietaryCarbohydrates |
| Total Fat | Total fat intake | HealthDataType.totalFat (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.totalFat) | HKQuantityTypeIdentifier.dietaryFatTotal |
| Caffeine | Caffeine intake | HealthDataType.caffeine (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.caffeine) | HKQuantityTypeIdentifier.dietaryCaffeine |
Fats
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Saturated Fat | Saturated fat intake | HealthDataType.saturatedFat (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.saturatedFat) | HKQuantityTypeIdentifier.dietaryFatSaturated |
| Monounsaturated Fat | Monounsaturated fat intake | HealthDataType.monounsaturatedFat (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.monounsaturatedFat) | HKQuantityTypeIdentifier.dietaryFatMonounsaturated |
| Polyunsaturated Fat | Polyunsaturated fat intake | HealthDataType.polyunsaturatedFat (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.polyunsaturatedFat) | HKQuantityTypeIdentifier.dietaryFatPolyunsaturated |
| Cholesterol | Cholesterol intake | HealthDataType.cholesterol (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.cholesterol) | HKQuantityTypeIdentifier.dietaryCholesterol |
Fiber & Sugar
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Dietary Fiber | Dietary fiber intake | HealthDataType.dietaryFiber (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.dietaryFiber) | HKQuantityTypeIdentifier.dietaryFiber |
| Sugar | Sugar intake | HealthDataType.sugar (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.sugar) | HKQuantityTypeIdentifier.dietarySugar |
Minerals
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Calcium | Calcium intake | HealthDataType.calcium (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.calcium) | HKQuantityTypeIdentifier.dietaryCalcium |
| Iron | Iron intake | HealthDataType.iron (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.iron) | HKQuantityTypeIdentifier.dietaryIron |
| Magnesium | Magnesium intake | HealthDataType.magnesium (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.magnesium) | HKQuantityTypeIdentifier.dietaryMagnesium |
| Manganese | Manganese intake | HealthDataType.manganese (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.manganese) | HKQuantityTypeIdentifier.dietaryManganese |
| Phosphorus | Phosphorus intake | HealthDataType.phosphorus (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.phosphorus) | HKQuantityTypeIdentifier.dietaryPhosphorus |
| Potassium | Potassium intake | HealthDataType.potassium (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.potassium) | HKQuantityTypeIdentifier.dietaryPotassium |
| Selenium | Selenium intake | HealthDataType.selenium (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.selenium) | HKQuantityTypeIdentifier.dietarySelenium |
| Sodium | Sodium intake | HealthDataType.sodium (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.sodium) | HKQuantityTypeIdentifier.dietarySodium |
| Zinc | Zinc intake | HealthDataType.zinc (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.zinc) | HKQuantityTypeIdentifier.dietaryZinc |
B Vitamins
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Thiamin (B1) | Thiamin (vitamin B1) intake | HealthDataType.thiamin (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.thiamin) | HKQuantityTypeIdentifier.dietaryThiamin |
| Riboflavin (B2) | Riboflavin (vitamin B2) | HealthDataType.riboflavin (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.riboflavin) | HKQuantityTypeIdentifier.dietaryRiboflavin |
| Niacin (B3) | Niacin (vitamin B3) intake | HealthDataType.niacin (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.niacin) | HKQuantityTypeIdentifier.dietaryNiacin |
| Pantothenic Acid (B5) | Pantothenic acid (vitamin B5) | HealthDataType.pantothenicAcid (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.pantothenicAcid) | HKQuantityTypeIdentifier.dietaryPantothenicAcid |
| Vitamin B6 | Vitamin B6 intake | HealthDataType.vitaminB6 (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.vitaminB6) | HKQuantityTypeIdentifier.dietaryVitaminB6 |
| Biotin (B7) | Biotin (vitamin B7) intake | HealthDataType.biotin (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.biotin) | HKQuantityTypeIdentifier.dietaryBiotin |
| Folate (B9) | Folate (vitamin B9) intake | HealthDataType.folate (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.folate) | HKQuantityTypeIdentifier.dietaryFolate |
| Vitamin B12 | Vitamin B12 intake | HealthDataType.vitaminB12 (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.vitaminB12) | HKQuantityTypeIdentifier.dietaryVitaminB12 |
Other Vitamins
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Vitamin A | Vitamin A intake | HealthDataType.vitaminA (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.vitaminA) | HKQuantityTypeIdentifier.dietaryVitaminA |
| Vitamin C | Vitamin C intake | HealthDataType.vitaminC (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.vitaminC) | HKQuantityTypeIdentifier.dietaryVitaminC |
| Vitamin D | Vitamin D intake | HealthDataType.vitaminD (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.vitaminD) | HKQuantityTypeIdentifier.dietaryVitaminD |
| Vitamin E | Vitamin E intake | HealthDataType.vitaminE (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.vitaminE) | HKQuantityTypeIdentifier.dietaryVitaminE |
| Vitamin K | Vitamin K intake | HealthDataType.vitaminK (iOS HealthKit Only) |
Sum | NutritionRecord (NutritionRecord.vitaminK) | HKQuantityTypeIdentifier.dietaryVitaminK |
๐ง Wellness
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Mindfulness Session | Meditation and mindfulness sessions | HealthDataType.mindfulnessSession |
Sum | MindfulnessSessionRecord | HKCategoryTypeIdentifier.mindfulSession |
๐ชท Cycle Tracking
| Data Type | Description | Data Type | Supported Aggregation | Android Health Connect API | iOS HealthKit API |
|---|---|---|---|---|---|
| Cervical Mucus | Cervical mucus observations for fertility | HealthDataType.cervicalMucus |
- | CervicalMucusRecord | HKCategoryTypeIdentifier.cervicalMucusQuality |
| Basal Body Temperature | Basal body temperature | HealthDataType.basalBodyTemperature |
Avg, Min, Max | BasalBodyTemperatureRecord | HKQuantityTypeIdentifier.basalBodyTemperature |
| Menstruation Flow | Menstrual flow intensity | HealthDataType.menstrualFlow |
- | MenstruationFlowRecord | HKCategoryTypeIdentifier.menstrualFlow |
| Ovulation Test | Ovulation test result | HealthDataType.ovulationTest |
- | OvulationTestRecord | HKCategoryTypeIdentifier.ovulationTestResult |
| Intermenstrual Bleeding | Intermenstrual bleeding spotting | HealthDataType.intermenstrualBleeding |
- | - | HKCategoryTypeIdentifier.persistentIntermenstrualBleeding |
๐ Migration Guides #
๐ค 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.









