This guide will get you reading and writing health data in under 5 minutes. For a complete working example, check out the example app in carp-health-flutter/example.
Prerequisites
Flutter Installed Make sure Flutter SDK is installed on your machine
Platform Setup Complete iOS and Android setup steps
Step 1: Create Health Instance
First, import the package and create a Health instance:
Main Setup
In a StatefulWidget
import 'package:health/health.dart' ;
final health = Health ();
await health. configure ();
class HealthPage extends StatefulWidget {
@override
_HealthPageState createState () => _HealthPageState ();
}
class _HealthPageState extends State < HealthPage > {
final health = Health ();
@override
void initState () {
super . initState ();
_configureHealth ();
}
Future < void > _configureHealth () async {
await health. configure ();
}
}
Call configure() once when your app starts. This initializes the health plugin for your platform.
Step 2: Request Permissions
Request basic read permissions for common health data: final types = [
HealthDataType . STEPS ,
HealthDataType . HEART_RATE ,
];
final granted = await health. requestAuthorization (types);
if (granted) {
print ( '✓ Permissions granted!' );
} else {
print ( '✗ Permissions denied' );
}
Start with just STEPS and HEART_RATE to keep things simple. You can add more types later.
Request specific read/write permissions for multiple data types: final types = [
HealthDataType . STEPS ,
HealthDataType . HEART_RATE ,
HealthDataType . WORKOUT ,
HealthDataType . WEIGHT ,
];
final permissions = [
HealthDataAccess . READ , // Steps: read only
HealthDataAccess . READ , // Heart rate: read only
HealthDataAccess . READ_WRITE , // Workout: read and write
HealthDataAccess . READ_WRITE , // Weight: read and write
];
final granted = await health. requestAuthorization (
types,
permissions : permissions,
);
On Android, if using STEPS or workout data, you also need to request runtime permissions for activity recognition and location. Use the permission_handler package.
Android: Check Health Connect
Health Connect Setup (Android Only)
On Android, users need Google Health Connect installed: // Check if Health Connect is available
final available = await health. isHealthConnectAvailable ();
if ( ! available) {
// Open Play Store to install Health Connect
await health. installHealthConnect ();
}
// Check detailed status
final status = await health. getHealthConnectSdkStatus ();
print ( 'Health Connect status: $ status ' );
Health Connect is the modern replacement for Google Fit on Android. Most devices running Android 14+ have it pre-installed.
Step 3: Read Health Data
Read your step count from the last 24 hours: final now = DateTime . now ();
final yesterday = now. subtract ( const Duration (hours : 24 ));
final healthData = await health. getHealthDataFromTypes (
types : [ HealthDataType . STEPS ],
startDate : yesterday,
endDate : now,
);
for ( var point in healthData) {
print ( 'Steps: ${ point . value } ' );
}
Read multiple data types with filtering: final now = DateTime . now ();
final yesterday = now. subtract ( const Duration (hours : 24 ));
final healthData = await health. getHealthDataFromTypes (
types : [
HealthDataType . STEPS ,
HealthDataType . HEART_RATE ,
HealthDataType . ACTIVE_ENERGY_BURNED ,
],
startDate : yesterday,
endDate : now,
includeManualEntry : false , // Exclude manual entries
);
// Group by type
final stepData = healthData
. where ((p) => p.type == HealthDataType . STEPS )
. toList ();
final heartRateData = healthData
. where ((p) => p.type == HealthDataType . HEART_RATE )
. toList ();
// Calculate total steps
final totalSteps = stepData
. map ((p) => (p.value as NumericHealthValue ).numericValue)
. fold ( 0.0 , (sum, value) => sum + value);
print ( 'Total steps: $ totalSteps ' );
print ( 'Heart rate readings: ${ heartRateData . length } ' );
Quick Step Count
Get Today's Steps Use the optimized method for step counting: final now = DateTime . now ();
final midnight = DateTime (now.year, now.month, now.day);
final steps = await health. getTotalStepsInInterval (midnight, now);
print ( 'Steps today: ${ steps ?? 0 } ' );
Step 4: Write Health Data
Save a simple health measurement like weight: final now = DateTime . now ();
final success = await health. writeHealthData (
value : 70.5 , // 70.5 kg
type : HealthDataType . WEIGHT ,
startTime : now,
);
if (success) {
print ( '✓ Weight saved!' );
} else {
print ( '✗ Failed to save weight' );
}
Make sure you requested WRITE permission for the data type you want to save!
Save a workout session with detailed metrics: final workoutEnd = DateTime . now ();
final workoutStart = workoutEnd. subtract ( Duration (minutes : 30 ));
final success = await health. writeWorkoutData (
activityType : HealthWorkoutActivityType . RUNNING ,
start : workoutStart,
end : workoutEnd,
totalDistance : 5000.0 , // 5 km in meters
totalEnergyBurned : 350.0 , // 350 kcal
);
if (success) {
print ( '✓ Workout saved!' );
}
writeBloodPressure() - For systolic/diastolic readings
writeBloodOxygen() - For SpO2 measurements
writeMeal() - For nutrition tracking
writeMenstruationFlow() - For cycle tracking
Step 5: Delete Data (Optional)
Delete data you’ve previously written: final now = DateTime . now ();
final yesterday = now. subtract ( Duration (hours : 24 ));
final success = await health. delete (
type : HealthDataType . STEPS ,
startTime : yesterday,
endTime : now,
);
if (success) {
print ( '✓ Data deleted' );
}
Deletion is permanent and cannot be undone. Always confirm with the user before deleting health data.
Complete Example
import 'package:flutter/material.dart' ;
import 'package:health/health.dart' ;
class SimpleHealthExample extends StatefulWidget {
@override
_SimpleHealthExampleState createState () => _SimpleHealthExampleState ();
}
class _SimpleHealthExampleState extends State < SimpleHealthExample > {
final health = Health ();
int ? steps;
@override
void initState () {
super . initState ();
_initHealth ();
}
Future < void > _initHealth () async {
// Configure
await health. configure ();
// Request permissions
final types = [ HealthDataType . STEPS ];
final granted = await health. requestAuthorization (types);
if (granted) {
_fetchSteps ();
}
}
Future < void > _fetchSteps () async {
final now = DateTime . now ();
final midnight = DateTime (now.year, now.month, now.day);
final stepCount = await health. getTotalStepsInInterval (midnight, now);
setState (() {
steps = stepCount;
});
}
@override
Widget build ( BuildContext context) {
return Scaffold (
appBar : AppBar (title : Text ( 'Health Example' )),
body : Center (
child : Column (
mainAxisAlignment : MainAxisAlignment .center,
children : [
Text (
'Steps Today' ,
style : TextStyle (fontSize : 24 ),
),
SizedBox (height : 16 ),
Text (
' ${ steps ?? '...' } ' ,
style : TextStyle (fontSize : 48 , fontWeight : FontWeight .bold),
),
SizedBox (height : 24 ),
ElevatedButton (
onPressed : _fetchSteps,
child : Text ( 'Refresh' ),
),
],
),
),
);
}
}
Next Steps
Reading Data Learn about different reading methods and data processing
Writing Data Explore writing workouts, meals, and specialized data
Permissions Understand permission management in depth
Data Types See all 100+ supported health data types
Common Issues
On iOS, if permissions are denied once, they can only be changed in the Settings app. Guide users to:
Open Settings app
Scroll to your app
Tap Health
Enable the data types you need
Health Connect Not Installed (Android)
Use the installation helper: if ( ! await health. isHealthConnectAvailable ()) {
await health. installHealthConnect ();
}
Common causes:
Permissions not granted
No data exists for the time range
On iOS: device is locked
On Android: Health Connect not synced
Need help? Check out the full example app for a complete implementation with UI.