Skip to content
Shiny .NET v4 is here with BLE Windows Support, Improved GPS, & More! Check It Out

Getting Started

  • GitHub stars for shinyorg/health
  • NuGet downloads for Shiny.Health
Frameworks
.NET MAUI
Operating Systems
Android
iOS

Shiny Health provides a unified API for querying health data from Apple HealthKit (iOS) and Android Health Connect. It supports permission management, time-bucketed aggregate queries, and 12 cross-platform health metrics.

  • Single IHealthService interface that works on both iOS and Android
  • 12 cross-platform health metrics — activity, body, vitals, and lifestyle
  • Time-bucketed aggregate queries at minute, hour, or day intervals
  • Permission management for both platforms
  • AOT-compatible implementation (no .NET reflection)
  • Blood pressure returns a dedicated BloodPressureResult with separate systolic/diastolic values
MetricUnitiOS (HealthKit)Android (Health Connect)
Step CountcountHKQuantityType.StepCountStepsRecord
Heart RatebpmHKQuantityType.HeartRateHeartRateRecord
CalorieskcalHKQuantityType.ActiveEnergyBurnedTotalCaloriesBurnedRecord
DistancemetersHKQuantityType.DistanceWalkingRunningDistanceRecord
WeightkgHKQuantityType.BodyMassWeightRecord
HeightmetersHKQuantityType.HeightHeightRecord
Body Fat %%HKQuantityType.BodyFatPercentageBodyFatRecord
Resting Heart RatebpmHKQuantityType.RestingHeartRateRestingHeartRateRecord
Blood PressuremmHgHKQuantityType.BloodPressureSystolic/DiastolicBloodPressureRecord
Oxygen Saturation%HKQuantityType.OxygenSaturationOxygenSaturationRecord
Sleep DurationhoursHKCategoryType.SleepAnalysisSleepSessionRecord
HydrationlitersHKQuantityType.DietaryWaterHydrationRecord
Shiny.HealthNuGet package Shiny.Health
public class HealthDashboardViewModel(IHealthService health)
{
async Task LoadDataAsync()
{
// 1. Request permissions
var result = await health.RequestPermissions(
DataType.StepCount,
DataType.HeartRate,
DataType.Calories,
DataType.Distance
);
// 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");
}
}
}
  1. Always request permissions first — Call RequestPermissions before querying 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
  • HealthKit requires a real device (not simulator) for most data types
  • RequestPermissions on iOS does NOT tell you if the user denied access (Apple privacy policy) — it may return true even when denied
  • Percentage values (body fat, O2 saturation) are returned as 0–100, not 0–1
  • Your app requires a provisioning profile with HealthKit capabilities enabled
  • The Health Connect app must be installed on the device
  • Minimum SDK version must be 28 (Android 9) or higher
  • Body fat percentage and oxygen saturation use individual record queries (Health Connect does not provide aggregate metrics for these types)
claude plugin marketplace add shinyorg/skills
claude plugin install shiny-client@shiny
copilot plugin marketplace add https://github.com/shinyorg/skills
copilot plugin install shiny-client@shiny
View shiny-client Plugin