Skip to content

Aggregate Data

Future<List<HealthDataPoint>> getHealthAggregateDataFromTypes({
required List<HealthDataType> types,
required DateTime startDate,
required DateTime endDate,
int activitySegmentDuration = 1,
bool includeManualEntry = true,
})
Parameter Type Required Default Description
types List<HealthDataType> Yes - Health data types to query
startDate DateTime Yes - Start of time range
endDate DateTime Yes - End of time range
activitySegmentDuration int No 1 Activity segment duration in minutes
includeManualEntry bool No true Include manually entered data

This method is optimized for workout and activity data:

final workoutSummaries = await health.getHealthAggregateDataFromTypes(
types: [
HealthDataType.WORKOUT,
HealthDataType.TOTAL_CALORIES_BURNED,
HealthDataType.DISTANCE_WALKING_RUNNING,
],
startDate: DateTime.now().subtract(Duration(days: 7)),
endDate: DateTime.now(),
activitySegmentDuration: 1,
includeManualEntry: true,
);
for (var point in workoutSummaries) {
if (point.type == HealthDataType.WORKOUT) {
final workout = point.value as WorkoutHealthValue;
print('Workout: ${workout.workoutActivityType.name}');
print('Duration: ${point.dateTo.difference(point.dateFrom)}');
if (workout.totalEnergyBurned != null) {
print('Calories: ${workout.totalEnergyBurned}');
}
}
}

Controls the granularity of activity data aggregation:

// 1-minute segments (most detailed)
final detailed = await health.getHealthAggregateDataFromTypes(
types: [HealthDataType.WORKOUT],
startDate: start,
endDate: end,
activitySegmentDuration: 1,
);
// 5-minute segments (balanced)
final balanced = await health.getHealthAggregateDataFromTypes(
types: [HealthDataType.WORKOUT],
startDate: start,
endDate: end,
activitySegmentDuration: 5,
);
// 15-minute segments (coarse)
final coarse = await health.getHealthAggregateDataFromTypes(
types: [HealthDataType.WORKOUT],
startDate: start,
endDate: end,
activitySegmentDuration: 15,
);
// Exclude manual entries
final autoOnly = await health.getHealthAggregateDataFromTypes(
types: [HealthDataType.WORKOUT],
startDate: start,
endDate: end,
includeManualEntry: false,
);
// Include manual entries (default)
final all = await health.getHealthAggregateDataFromTypes(
types: [HealthDataType.WORKOUT],
startDate: start,
endDate: end,
includeManualEntry: true,
);

Query multiple related metrics:

final activityData = await health.getHealthAggregateDataFromTypes(
types: [
HealthDataType.WORKOUT,
HealthDataType.ACTIVE_ENERGY_BURNED,
HealthDataType.DISTANCE_WALKING_RUNNING,
HealthDataType.STEPS,
HealthDataType.HEART_RATE,
],
startDate: DateTime.now().subtract(Duration(days: 30)),
endDate: DateTime.now(),
);
// Group by type
final byType = <HealthDataType, List<HealthDataPoint>>{};
for (var point in activityData) {
byType.putIfAbsent(point.type, () => []).add(point);
}
print('Workouts: ${byType[HealthDataType.WORKOUT]?.length ?? 0}');
print('Energy data points: ${byType[HealthDataType.ACTIVE_ENERGY_BURNED]?.length ?? 0}');
class WorkoutStats {
final int totalWorkouts;
final Duration totalDuration;
final double totalCalories;
final double totalDistance;
WorkoutStats({
required this.totalWorkouts,
required this.totalDuration,
required this.totalCalories,
required this.totalDistance,
});
}
Future<WorkoutStats> getWorkoutStats(DateTime start, DateTime end) async {
final data = await health.getHealthAggregateDataFromTypes(
types: [HealthDataType.WORKOUT],
startDate: start,
endDate: end,
);
int workoutCount = 0;
Duration totalDuration = Duration.zero;
double totalCalories = 0;
double totalDistance = 0;
for (var point in data) {
if (point.type == HealthDataType.WORKOUT) {
workoutCount++;
totalDuration += point.dateTo.difference(point.dateFrom);
final workout = point.value as WorkoutHealthValue;
totalCalories += workout.totalEnergyBurned ?? 0;
totalDistance += workout.totalDistance ?? 0;
}
}
return WorkoutStats(
totalWorkouts: workoutCount,
totalDuration: totalDuration,
totalCalories: totalCalories,
totalDistance: totalDistance,
);
}
Future<Map<HealthWorkoutActivityType, int>> getWorkoutTypeBreakdown(
DateTime start,
DateTime end,
) async {
final workouts = await health.getHealthAggregateDataFromTypes(
types: [HealthDataType.WORKOUT],
startDate: start,
endDate: end,
);
final breakdown = <HealthWorkoutActivityType, int>{};
for (var point in workouts) {
final workout = point.value as WorkoutHealthValue;
breakdown[workout.workoutActivityType] =
(breakdown[workout.workoutActivityType] ?? 0) + 1;
}
return breakdown;
}
// Usage
final breakdown = await getWorkoutTypeBreakdown(
DateTime.now().subtract(Duration(days: 30)),
DateTime.now(),
);
breakdown.forEach((type, count) {
print('${type.name}: $count workouts');
});
  • iOS: Returns workout sessions with summary data
  • Android: Returns aggregate workout data from Health Connect
  • Data structure may vary between platforms