health_connector_hc_android 1.4.0
health_connector_hc_android: ^1.4.0 copied to clipboard
Android implementation of health_connector using Health Connect
health_connector_hc_android #
📖 Overview #
health_connector_hc_android is the Android platform implementation for the Health Connector plugin.
It provides integration with Android's Health Connect SDK, enabling Flutter apps to read, write, and
aggregate health data on Android devices.
✨ Features #
| Feature | Description |
|---|---|
| 🔐 Permission Management | Request/check/revoke permissions |
| 📖 Reading Health Data | Read a single health record by ID or multiple health records within a date/time range with pagination |
| ✍️ Writing Health Data | Write health records |
| 🔄 Updating Health Records | Native in-place record updates with preserved IDs |
| 🗑️ Deleting Health Records | Remove specific records by their IDs or within a date/time range |
| ➕ Aggregating Health Data | Sum/Avg/Min/Max Aggregation |
🎯 Requirements #
- Flutter >=3.3.0
- Dart >=3.9.2
- Android SDK: API level 26+ (Android 8.0)
- Kotlin: 1.9.0+
- Java: 11+
🚀 Getting Started #
📦 Installation #
Add to your pubspec.yaml:
flutter pub add health_connector_hc_android
Or manually add:
dependencies:
health_connector_hc_android: [latest_version]
⚙️ Android Setup #
AndroidManifest.xml Configuration
Update AndroidManifest.xml
Add Health Connect permissions and intent filter 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 -->
<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 -->
<!-- Read permissions -->
<uses-permission android:name="android.permission.health.READ_STEPS" />
<uses-permission android:name="android.permission.health.READ_WEIGHT" />
<!-- Write permissions -->
<uses-permission android:name="android.permission.health.WRITE_STEPS" />
<uses-permission android:name="android.permission.health.WRITE_WEIGHT" />
</manifest>
Important: Add permissions for each health data type you plan to use.
Health Connect Availability
📚 Usage #
Import Package
import 'package:health_connector/health_connector.dart';
Create HealthConnectorHCClient Instance
final client = HealthConnectorHCClient();
Check Health Connect Availability
final status = await client.getHealthPlatformStatus();
switch (status) {
case HealthPlatformStatus.available:
print('Health Connect ready');
break;
case HealthPlatformStatus.installationOrUpdateRequired:
print('Please install or update Health Connect');
break;
case HealthPlatformStatus.unavailable:
print('Health Connect not supported on this device');
break;
}
Check Health Platform Feature Status
final featureStatus = await client.getFeatureStatus(
HealthPlatformFeature.readHealthDataInBackground,
);
if (featureStatus == HealthPlatformFeatureStatus.available) {
// Request feature permission if needed
}
Permissions
Request Permissions
final permissions = [
// Health data permissions
HealthDataType.steps.readPermission,
HealthDataType.steps.writePermission,
HealthDataType.weight.readPermission,
HealthDataType.weight.writePermission,
// ...
// Feature permissions
HealthPlatformFeature.readHealthDataInBackground,
HealthPlatformFeature.readHealthDataHistory,
// ...
];
final results = await client.requestPermissions(permissions);
for (final result in results) {
print('${result.permission}: ${result.status}');
}
Check All Granted Permissions
final grantedPermissions = await client.getGrantedPermissions();
print('Granted permissions: ${grantedPermissions.length}');
Revoke All Granted Permissions
await client.revokeAllPermissions();
Read Health Records
Read Health Record by ID
final recordId = HealthRecordId('existing-record-id');
final readRequest = HealthDataType.steps.readRecord(recordId);
final record = await client.readRecord(readRequest);
if (record != null) {
print('Steps: ${record.count.value} from ${record.startTime} to ${record.endTime}');
} else {
print('Record not found');
}
Read Multiple Health Records
final request = HealthDataType.steps.readRecords(
startTime: DateTime.now().subtract(Duration(days: 7)),
endTime: DateTime.now(),
pageSize: 100,
);
final response = await client.readRecords(request);
for (final record in response.records) {
print('Steps: ${record.count.value} from ${record.startTime} to ${record.endTime}');
}
Read Multiple Health Records with Pagination
var request = HealthDataType.steps.readRecords(
startTime: DateTime.now().subtract(Duration(days: 30)),
endTime: DateTime.now(),
pageSize: 100,
);
var allRecords = <StepRecord>[];
var pageNumber = 1;
while (true) {
final response = await client.readRecords(request);
allRecords.addAll(response.records.cast<StepRecord>());
if (response.nextPageRequest == null) {
break;
}
request = response.nextPageRequest!;
pageNumber++;
}
print('Total records fetched: ${allRecords.length}');
Write Health Records
Write Single Health Record
final stepRecord = StepRecord(
id: HealthRecordId.none,
startTime: DateTime.now().subtract(Duration(hours: 1)),
endTime: DateTime.now(),
count: Numeric(5000),
metadata: Metadata.automaticallyRecorded(
device: Device.fromType(DeviceType.phone),
),
);
final recordId = await client.writeRecord(stepRecord);
print('Record written with ID: $recordId');
Write Multiple Health Records
final records = [
StepRecord(
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),
),
),
DistanceRecord(
id: HealthRecordId.none,
startTime: DateTime.now().subtract(Duration(hours: 1)),
endTime: DateTime.now(),
distance: Length(5000),
metadata: Metadata.automaticallyRecorded(
device: Device.fromType(DeviceType.phone),
),
),
// ...
];
final recordIds = await client.writeRecords(records);
print('Wrote ${recordIds.length} records');
Update Health Records
final recordId = HealthRecordId('existing-record-id');
final readRequest = HealthDataType.steps.readRecord(recordId);
final existingRecord = await client.readRecord(readRequest);
if (existingRecord != null) {
final updatedRecord = existingRecord.copyWith(
startTime: existingRecord.startTime,
endTime: existingRecord.endTime,
count: Numeric(existingRecord.count.value + 100),
metadata: existingRecord.metadata,
);
final updatedId = await client.updateRecord(updatedRecord);
print('Original ID: $recordId');
print('Updated ID: $updatedId');
// originalId == updatedId on Android
}
Delete Health Records
Delete Health Records by IDs
await client.deleteRecordsByIds(
dataType: HealthDataType.steps,
recordIds: [
HealthRecordId('id-1'),
HealthRecordId('id-2'),
],
);
print('Records deleted');
Delete Health Records by Date Range
await client.deleteRecords(
dataType: HealthDataType.steps,
startTime: DateTime.now().subtract(Duration(days: 7)),
endTime: DateTime.now(),
);
print('Records deleted');
Aggregate Health Data
final sumRequest = HealthDataType.steps.aggregateSum(
startTime: DateTime.now().startOfDay,
endTime: DateTime.now(),
);
final sumResponse = await client.aggregate(sumRequest);
print('Total steps today: ${sumResponse.value.value}');
final avgRequest = HealthDataType.weight.aggregateAvg(
startTime: DateTime.now().subtract(Duration(days: 30)),
endTime: DateTime.now(),
);
final avgResponse = await client.aggregate(avgRequest);
print('Average weight: ${avgResponse.value.inKilograms} kg');
final minRequest = HealthDataType.weight.aggregateMin(
startTime: DateTime.now().subtract(Duration(days: 30)),
endTime: DateTime.now(),
);
final minResponse = await client.aggregate(minRequest);
print('Min weight: ${minResponse.value.inKilograms} kg');
final maxRequest = HealthDataType.weight.aggregateMax(
startTime: DateTime.now().subtract(Duration(days: 30)),
endTime: DateTime.now(),
);
final maxResponse = await client.aggregate(maxRequest);
print('Max weight: ${maxResponse.value.inKilograms} kg');
📋 Supported Health Data Types #
Note: For a complete list of all Health Connect data types, see the official Health Connect documentation.
🏃 Activity #
| Data Type | Supported | Documentation |
|---|---|---|
| Steps | ✅ | StepsRecord |
| Distance | ✅ | DistanceRecord |
| Active Calories Burned | ✅ | ActiveCaloriesBurnedRecord |
| Floors Climbed | ✅ | FloorsClimbedRecord |
| Wheelchair Pushes | ✅ | WheelchairPushesRecord |
| Exercise Session | ❌ | ExerciseSessionRecord |
| Total Calories Burned | ❌ | TotalCaloriesBurnedRecord |
| Cycling Pedaling Cadence | ❌ | CyclingPedalingCadenceRecord |
| Power | ❌ | PowerRecord |
| Speed | ❌ | SpeedRecord |
📏 Body Measurements #
| Data Type | Supported | Documentation |
|---|---|---|
| Weight | ✅ | WeightRecord |
| Height | ✅ | HeightRecord |
| Body Fat Percentage | ✅ | BodyFatRecord |
| Lean Body Mass | ✅ | LeanBodyMassRecord |
| Bone Mass | ❌ | BoneMassRecord |
| Basal Metabolic Rate | ❌ | BasalMetabolicRateRecord |
🩸 Cycle Tracking / Reproductive Health #
| Data Type | Supported | Documentation |
|---|---|---|
| Menstruation Flow | ❌ | MenstruationFlowRecord |
| Cervical Mucus | ❌ | CervicalMucusRecord |
| Ovulation Test | ❌ | OvulationTestRecord |
| Basal Body Temperature | ❌ | BasalBodyTemperatureRecord |
| Sexual Activity | ❌ | SexualActivityRecord |
🍎 Nutrition #
| Data Type | Supported | Documentation |
|---|---|---|
| Hydration / Water | ✅ | HydrationRecord |
| Nutrition / Dietary Energy | ✅ | NutritionRecord |
😴 Sleep #
| Data Type | Supported | Documentation |
|---|---|---|
| Sleep Session | ✅ | SleepSessionRecord |
| Sleep Stage | ❌ | SleepStageRecord |
❤️ Vitals #
| Data Type | Supported | Documentation |
|---|---|---|
| Heart Rate (Series) | ✅ | HeartRateSeriesRecord |
| Resting Heart Rate | ✅ | RestingHeartRateRecord |
| Blood Pressure | ✅ | BloodPressureRecord |
| Body Temperature | ✅ | BodyTemperatureRecord |
| Oxygen Saturation | ✅ | OxygenSaturationRecord |
| Respiratory Rate | ✅ | RespiratoryRateRecord |
| Vo2 Max | ✅ | Vo2MaxRecord |
| Blood Glucose | ✅ | BloodGlucoseRecord |
🧘 Wellness / Mental Health #
| Data Type | Supported | Documentation |
|---|---|---|
| Mindfulness Session | ❌ | MindfulnessSessionRecord |
🤝 Contributing #
Contributions are welcome!
To report issues or request features, please visit our GitHub Issues.