Skip to content
Introducing AI Conversations: Natural Language Interaction for Your Apps! Learn More

Reading Data

You can query health data from Apple HealthKit and Android Health Connect using the IHealthService interface. Always request read permissions first.

public class HealthDashboardViewModel(IHealthService health)
{
async Task LoadDataAsync()
{
// 1. Request permissions (read-only shorthand)
var result = await health.RequestPermissions(
DataType.StepCount,
DataType.HeartRate,
DataType.Calories,
DataType.Distance
);
// Or request per-metric read/write permissions in a single call
// await health.RequestPermissions(
// (PermissionType.Read, DataType.StepCount),
// (PermissionType.Read, DataType.HeartRate),
// (PermissionType.Write, DataType.Weight),
// (PermissionType.ReadWrite, DataType.BloodPressure)
// );
// 2. Check which permissions were granted
foreach (var (type, success) in result)
{
if (!success)
Console.WriteLine($"Permission denied for {type}");
}
// 3. Query data for the last 24 hours
var end = DateTimeOffset.Now;
var start = end.AddDays(-1);
var steps = (await health.GetStepCounts(start, end, Interval.Days)).Sum(x => x.Value);
var calories = (await health.GetCalories(start, end, Interval.Days)).Sum(x => x.Value);
var distance = (await health.GetDistances(start, end, Interval.Days)).Sum(x => x.Value);
var heartRate = (await health.GetAverageHeartRate(start, end, Interval.Days)).Average(x => x.Value);
// 4. Blood pressure returns a special result type
var bp = await health.GetBloodPressure(start, end, Interval.Days);
if (bp.Any())
{
var avgSystolic = bp.Average(x => x.Systolic);
var avgDiastolic = bp.Average(x => x.Diastolic);
}
// 5. Hourly breakdown
var hourlySteps = await health.GetStepCounts(start, end, Interval.Hours);
foreach (var bucket in hourlySteps)
{
Console.WriteLine($"{bucket.Start:g} - {bucket.End:g}: {bucket.Value:N0} steps");
}
}
}

See the dedicated Observing Data page for streaming health data changes via IAsyncEnumerable<HealthResult>.

  1. Always request permissions first — Call RequestPermissions before reading data
  2. Use appropriate intervalsInterval.Days for summaries, Interval.Hours for detailed breakdowns
  3. Handle empty results — Check .Any() before calling .Average() to avoid InvalidOperationException
  4. Use CancellationToken — Pass cancellation tokens for long-running queries
  5. Sum vs Average — Use .Sum() for cumulative metrics (steps, calories, distance, hydration, sleep) and .Average() for point-in-time metrics (heart rate, weight, height, body fat, O2 sat, resting HR)
  6. Blood pressure is special — It returns BloodPressureResult (not NumericHealthResult) with separate Systolic and Diastolic values