Shiny Controls v1.0 - The Ultra Control Suite for .NET MAUI & BlazorO...M...G!
Platform Notes
- HealthKit requires a real device (not simulator) for most data types
RequestPermissionson iOS does NOT tell you if the user denied access (Apple privacy policy) — it may returntrueeven 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
ObserveusesHKAnchoredObjectQueryfor push-based real-time delivery — no polling needed- Menstruation flow uses
HKCategoryType.MenstrualFlow; theMenstruationFlowResult.IsCycleStartflag maps to theHKMetadataKeyMenstrualCycleStartsample metadata, and theMenstrualFlow.Nonelevel is supported - Heart rate variability uses
HKQuantityTypeIdentifier.HeartRateVariabilitySDNN(SDNN, in ms) Speedmaps toWalkingSpeedandPowermaps toCyclingPower(HealthKit has no generic speed/power types)- Workouts use
HKWorkoutwithWorkoutTypemapped toHKWorkoutActivityType; nutrition is written as anHKCorrelationof typeFoodcontaining the individual dietary quantity samples - Sexual activity protection is stored via the
HKMetadataKeySexualActivityProtectionUsedmetadata key
Android
Section titled “Android”- The Health Connect app must be installed on the device — on Android 14+ (API 34) it ships as part of the platform
- Minimum SDK version must be 28 (Android 9) or higher
- Set
targetSdkVersionto the platform you build against. An empty<uses-sdk />element inAndroidManifest.xmlsuppresses it and falls back tominSdkVersion— recent Android versions then block the install with “Unsafe app blocked — this app was built for an older version of Android” - The permission flow differs by OS version and
RequestPermissionshandles both: on Android 14+ the health permissions are ordinary runtime permissions, while on earlier versions they belong to the Health Connect APK and are granted through its own permission activity. Never request them yourself withPermissions.RequestAsync<>or the AndroidX activity-result contracts - Android 14+ additionally requires a
ViewPermissionUsageActivityactivity-alias(with theandroid.intent.category.HEALTH_PERMISSIONScategory) plus anandroidx.health.ACTION_SHOW_PERMISSIONS_RATIONALEintent filter on yourMainActivity. Without them Health Connect refuses to grant health permissions — the Setup builder emits both - Body fat percentage and oxygen saturation use individual record queries (Health Connect does not provide aggregate metrics for these types)
Observeuses Health Connect change tokens with polling (default 5 seconds) — Health Connect does not support push-based observation- Menstruation flow uses the
MenstruationFlowRecordwith theandroid.permission.health.READ_MENSTRUATION/WRITE_MENSTRUATIONpermissions. There is noNoneflow value (written asUnspecified), andIsCycleStartis ignored — Health Connect models the period span as a separateMenstruationPeriodRecord - Heart rate variability uses
HeartRateVariabilityRmssdRecord(RMSSD, in ms) — a different computation than iOS’s SDNN, so the values are not directly comparable - Each new type needs its own permission, e.g.
READ_BLOOD_GLUCOSE,READ_VO2_MAX,READ_EXERCISE(workouts),READ_NUTRITION,READ_SEXUAL_ACTIVITY(and theWRITE_…equivalents) — declare them inAndroidManifest.xml - Permission names follow the Health Connect record, not the HealthKit type.
DataType.CaloriesreadsTotalCaloriesBurnedRecord, so it needsREAD_TOTAL_CALORIES_BURNED— there is no…_TOTAL_ENERGY_BURNEDpermission on Android even though HealthKit calls the equivalent typeActiveEnergyBurned. A permission the platform does not recognize is silently unknown: it can never be granted, and every read of that type fails - Health Connect lets the user grant a subset of what you asked for, so treat a partial grant as the normal case: check the per-
DataTyperesults fromRequestPermissionsand only query what came backtrue. Querying a type whose permission was not granted throws — it does not return an empty list - Instantaneous records without aggregate metrics (blood glucose, body/basal temperature, respiratory rate, VO2 max, HRV, lean body mass) are read with
ReadRecordsand bucketed in-memory, like body fat and oxygen saturation - Workouts use
ExerciseSessionRecord; itsWorkoutResultenergy and distance arenullon read because Health Connect stores those as separateActiveCaloriesBurnedRecord/DistanceRecordentries BasalEnergyBurnedis derived fromBasalMetabolicRateRecord(a rate); on write the value is treated as kcal/day


