diff --git a/packages/health/CHANGELOG.md b/packages/health/CHANGELOG.md index c07bafbf5..093d10da9 100644 --- a/packages/health/CHANGELOG.md +++ b/packages/health/CHANGELOG.md @@ -1,13 +1,19 @@ ## 12.0.0 -* Fix of [#1072](https://github.com/cph-cachet/flutter-plugins/issues/1072) and [#1074](https://github.com/cph-cachet/flutter-plugins/issues/1074) +* Add `LEAN_BODY_MASS` data type [#1078](https://github.com/cph-cachet/flutter-plugins/issues/1078) - PR [#1097](https://github.com/cph-cachet/flutter-plugins/pull/1097) + * The following AndroidManifest values are required to READ/WRITE `LEAN_BODY_MASS`: + ```XML + + + ``` +* iOS: Add `WATER_TEMPERATURE` and `UNDERWATER_DEPTH` health values [#1096](https://github.com/cph-cachet/flutter-plugins/issues/1096) +* iOS: Add support for `Underwater Diving` workout [#1096](https://github.com/cph-cachet/flutter-plugins/issues/1096) +* Fix [#1072](https://github.com/cph-cachet/flutter-plugins/issues/1072) and [#1074](https://github.com/cph-cachet/flutter-plugins/issues/1074) * Fix issue where iOS delete not deleting own records - PR [#1104](https://github.com/cph-cachet/flutter-plugins/pull/1104) -* Fix of [#950](https://github.com/cph-cachet/flutter-plugins/issues/950) - PR [#1103](https://github.com/cph-cachet/flutter-plugins/pull/1103) -* Updated `intl` to ^0.20.1 - Closes [#1092](https://github.com/cph-cachet/flutter-plugins/issues/1092) +* Fix [#950](https://github.com/cph-cachet/flutter-plugins/issues/950) - PR [#1103](https://github.com/cph-cachet/flutter-plugins/pull/1103) +* Updated `intl` to ^0.20.1 [#1092](https://github.com/cph-cachet/flutter-plugins/issues/1092) * Updated `device_info_plus` to ^11.2.0 * Example app: Updated `permission_handler` to ^11.3.1 -* iOS: Add `WATER_TEMPERATURE` and `UNDERWATER_DEPTH` health values - Closes [#1096](https://github.com/cph-cachet/flutter-plugins/issues/1096) -* iOS: Add support for `Underwater Diving` workout - Closes [#1096](https://github.com/cph-cachet/flutter-plugins/issues/1096) ## 11.1.1 diff --git a/packages/health/README.md b/packages/health/README.md index e10b90ab5..eea60737c 100644 --- a/packages/health/README.md +++ b/packages/health/README.md @@ -358,6 +358,7 @@ The plugin supports the following [`HealthDataType`](https://pub.dev/documentati | MENSTRUATION_FLOW | NO_UNIT | yes | yes | | | WATER_TEMPERATURE | DEGREE_CELSIUS | yes | | Related to/Requires Apple Watch Ultra's Underwater Diving Workout | | UNDERWATER_DEPTH | METER | yes | | Related to/Requires Apple Watch Ultra's Underwater Diving Workout | +| LEAN_BODY_MASS | KILOGRAMS | yes | yes | | ## Workout Types diff --git a/packages/health/android/src/main/kotlin/cachet/plugins/health/HealthPlugin.kt b/packages/health/android/src/main/kotlin/cachet/plugins/health/HealthPlugin.kt index 94c0fce99..97e217d9f 100644 --- a/packages/health/android/src/main/kotlin/cachet/plugins/health/HealthPlugin.kt +++ b/packages/health/android/src/main/kotlin/cachet/plugins/health/HealthPlugin.kt @@ -48,6 +48,7 @@ const val BLOOD_OXYGEN = "BLOOD_OXYGEN" const val BLOOD_PRESSURE_DIASTOLIC = "BLOOD_PRESSURE_DIASTOLIC" const val BLOOD_PRESSURE_SYSTOLIC = "BLOOD_PRESSURE_SYSTOLIC" const val BODY_FAT_PERCENTAGE = "BODY_FAT_PERCENTAGE" +const val LEAN_BODY_MASS = "LEAN_BODY_MASS" const val BODY_TEMPERATURE = "BODY_TEMPERATURE" const val BODY_WATER_MASS = "BODY_WATER_MASS" const val DISTANCE_DELTA = "DISTANCE_DELTA" @@ -1083,6 +1084,29 @@ class HealthPlugin(private var channel: MethodChannel? = null) : ), ) + is LeanBodyMassRecord -> + return listOf( + mapOf( + "uuid" to + metadata.id, + "value" to + record.mass + .inKilograms, + "date_from" to + record.time + .toEpochMilli(), + "date_to" to + record.time + .toEpochMilli(), + "source_id" to "", + "source_name" to + metadata.dataOrigin + .packageName, + "recording_method" to + metadata.recordingMethod + ), + ) + is StepsRecord -> return listOf( mapOf( @@ -1596,6 +1620,22 @@ class HealthPlugin(private var channel: MethodChannel? = null) : ), ) + LEAN_BODY_MASS -> + LeanBodyMassRecord( + time = + Instant.ofEpochMilli( + startTime + ), + mass = + Mass.kilograms( + value + ), + zoneOffset = null, + metadata = Metadata( + recordingMethod = recordingMethod, + ), + ) + HEIGHT -> HeightRecord( time = @@ -2398,6 +2438,7 @@ class HealthPlugin(private var channel: MethodChannel? = null) : private val mapToType = hashMapOf( BODY_FAT_PERCENTAGE to BodyFatRecord::class, + LEAN_BODY_MASS to LeanBodyMassRecord::class, HEIGHT to HeightRecord::class, WEIGHT to WeightRecord::class, STEPS to StepsRecord::class, @@ -2438,7 +2479,6 @@ class HealthPlugin(private var channel: MethodChannel? = null) : // "BasalMetabolicRate" to BasalMetabolicRateRecord::class, // "BloodGlucose" to BloodGlucoseRecord::class, // "BloodPressure" to BloodPressureRecord::class, - // "BodyFat" to BodyFatRecord::class, // "BodyTemperature" to BodyTemperatureRecord::class, // "BoneMass" to BoneMassRecord::class, // "CervicalMucus" to CervicalMucusRecord::class, @@ -2451,7 +2491,6 @@ class HealthPlugin(private var channel: MethodChannel? = null) : // "HeartRate" to HeartRateRecord::class, // "Height" to HeightRecord::class, // "Hydration" to HydrationRecord::class, - // "LeanBodyMass" to LeanBodyMassRecord::class, // "MenstruationPeriod" to MenstruationPeriodRecord::class, // "Nutrition" to NutritionRecord::class, // "OvulationTest" to OvulationTestRecord::class, diff --git a/packages/health/example/android/app/src/main/AndroidManifest.xml b/packages/health/example/android/app/src/main/AndroidManifest.xml index f6d185ace..996adaf97 100644 --- a/packages/health/example/android/app/src/main/AndroidManifest.xml +++ b/packages/health/example/android/app/src/main/AndroidManifest.xml @@ -65,6 +65,8 @@ + + diff --git a/packages/health/example/ios/Runner.xcodeproj/project.pbxproj b/packages/health/example/ios/Runner.xcodeproj/project.pbxproj index a64ef83b6..77f2ffb80 100644 --- a/packages/health/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/health/example/ios/Runner.xcodeproj/project.pbxproj @@ -312,6 +312,24 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + FEE6262278064D703A8D8D21 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/permission_handler_apple/permission_handler_apple_privacy.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/permission_handler_apple_privacy.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/packages/health/example/lib/main.dart b/packages/health/example/lib/main.dart index e02c1e037..e86985d6c 100644 --- a/packages/health/example/lib/main.dart +++ b/packages/health/example/lib/main.dart @@ -285,6 +285,12 @@ class _HealthAppState extends State { type: HealthDataType.SLEEP_DEEP, startTime: earlier, endTime: now); + success &= await Health().writeHealthData( + value: 22, + type: HealthDataType.LEAN_BODY_MASS, + startTime: earlier, + endTime: now, + ); // specialized write methods success &= await Health().writeBloodOxygen( diff --git a/packages/health/example/lib/util.dart b/packages/health/example/lib/util.dart index 24168041f..5c6f70be8 100644 --- a/packages/health/example/lib/util.dart +++ b/packages/health/example/lib/util.dart @@ -44,6 +44,7 @@ const List dataTypesIOS = [ HealthDataType.HEADACHE_MODERATE, HealthDataType.HEADACHE_SEVERE, HealthDataType.HEADACHE_UNSPECIFIED, + HealthDataType.LEAN_BODY_MASS, // note that a phone cannot write these ECG-based types - only read them // HealthDataType.ELECTROCARDIOGRAM, @@ -78,6 +79,7 @@ const List dataTypesAndroid = [ HealthDataType.BODY_FAT_PERCENTAGE, HealthDataType.HEIGHT, HealthDataType.WEIGHT, + HealthDataType.LEAN_BODY_MASS, // HealthDataType.BODY_MASS_INDEX, HealthDataType.BODY_TEMPERATURE, HealthDataType.HEART_RATE, diff --git a/packages/health/ios/Classes/SwiftHealthPlugin.swift b/packages/health/ios/Classes/SwiftHealthPlugin.swift index ebb1f5d40..491888e7e 100644 --- a/packages/health/ios/Classes/SwiftHealthPlugin.swift +++ b/packages/health/ios/Classes/SwiftHealthPlugin.swift @@ -35,6 +35,7 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin { let BLOOD_PRESSURE_DIASTOLIC = "BLOOD_PRESSURE_DIASTOLIC" let BLOOD_PRESSURE_SYSTOLIC = "BLOOD_PRESSURE_SYSTOLIC" let BODY_FAT_PERCENTAGE = "BODY_FAT_PERCENTAGE" + let LEAN_BODY_MASS = "LEAN_BODY_MASS" let BODY_MASS_INDEX = "BODY_MASS_INDEX" let BODY_TEMPERATURE = "BODY_TEMPERATURE" // Nutrition @@ -1422,6 +1423,7 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin { forIdentifier: .bloodPressureSystolic)! dataTypesDict[BODY_FAT_PERCENTAGE] = HKSampleType.quantityType( forIdentifier: .bodyFatPercentage)! + dataTypesDict[LEAN_BODY_MASS] = HKSampleType.quantityType(forIdentifier: .leanBodyMass)! dataTypesDict[BODY_MASS_INDEX] = HKSampleType.quantityType(forIdentifier: .bodyMassIndex)! dataTypesDict[BODY_TEMPERATURE] = HKSampleType.quantityType(forIdentifier: .bodyTemperature)! @@ -1520,6 +1522,7 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin { dataQuantityTypesDict[BLOOD_PRESSURE_DIASTOLIC] = HKQuantityType.quantityType(forIdentifier: .bloodPressureDiastolic)! dataQuantityTypesDict[BLOOD_PRESSURE_SYSTOLIC] = HKQuantityType.quantityType(forIdentifier: .bloodPressureSystolic)! dataQuantityTypesDict[BODY_FAT_PERCENTAGE] = HKQuantityType.quantityType(forIdentifier: .bodyFatPercentage)! + dataQuantityTypesDict[LEAN_BODY_MASS] = HKSampleType.quantityType(forIdentifier: .leanBodyMass)! dataQuantityTypesDict[BODY_MASS_INDEX] = HKQuantityType.quantityType(forIdentifier: .bodyMassIndex)! dataQuantityTypesDict[BODY_TEMPERATURE] = HKQuantityType.quantityType(forIdentifier: .bodyTemperature)! diff --git a/packages/health/lib/health.g.dart b/packages/health/lib/health.g.dart index c61f0d2e5..70feb2de1 100644 --- a/packages/health/lib/health.g.dart +++ b/packages/health/lib/health.g.dart @@ -57,6 +57,7 @@ const _$HealthDataTypeEnumMap = { HealthDataType.BLOOD_PRESSURE_DIASTOLIC: 'BLOOD_PRESSURE_DIASTOLIC', HealthDataType.BLOOD_PRESSURE_SYSTOLIC: 'BLOOD_PRESSURE_SYSTOLIC', HealthDataType.BODY_FAT_PERCENTAGE: 'BODY_FAT_PERCENTAGE', + HealthDataType.LEAN_BODY_MASS: 'LEAN_BODY_MASS', HealthDataType.BODY_MASS_INDEX: 'BODY_MASS_INDEX', HealthDataType.BODY_TEMPERATURE: 'BODY_TEMPERATURE', HealthDataType.BODY_WATER_MASS: 'BODY_WATER_MASS', diff --git a/packages/health/lib/src/heath_data_types.dart b/packages/health/lib/src/heath_data_types.dart index 878bbc00f..0a1f8c400 100644 --- a/packages/health/lib/src/heath_data_types.dart +++ b/packages/health/lib/src/heath_data_types.dart @@ -11,6 +11,7 @@ enum HealthDataType { BLOOD_PRESSURE_DIASTOLIC, BLOOD_PRESSURE_SYSTOLIC, BODY_FAT_PERCENTAGE, + LEAN_BODY_MASS, BODY_MASS_INDEX, BODY_TEMPERATURE, BODY_WATER_MASS, @@ -127,6 +128,7 @@ const List dataTypeKeysIOS = [ HealthDataType.BLOOD_PRESSURE_DIASTOLIC, HealthDataType.BLOOD_PRESSURE_SYSTOLIC, HealthDataType.BODY_FAT_PERCENTAGE, + HealthDataType.LEAN_BODY_MASS, HealthDataType.BODY_MASS_INDEX, HealthDataType.BODY_TEMPERATURE, HealthDataType.DIETARY_CARBS_CONSUMED, @@ -220,6 +222,7 @@ const List dataTypeKeysAndroid = [ HealthDataType.BLOOD_PRESSURE_DIASTOLIC, HealthDataType.BLOOD_PRESSURE_SYSTOLIC, HealthDataType.BODY_FAT_PERCENTAGE, + HealthDataType.LEAN_BODY_MASS, HealthDataType.BODY_MASS_INDEX, HealthDataType.BODY_TEMPERATURE, HealthDataType.BODY_WATER_MASS, @@ -260,6 +263,7 @@ const Map dataTypeToUnit = { HealthDataType.BLOOD_PRESSURE_DIASTOLIC: HealthDataUnit.MILLIMETER_OF_MERCURY, HealthDataType.BLOOD_PRESSURE_SYSTOLIC: HealthDataUnit.MILLIMETER_OF_MERCURY, HealthDataType.BODY_FAT_PERCENTAGE: HealthDataUnit.PERCENT, + HealthDataType.LEAN_BODY_MASS: HealthDataUnit.KILOGRAM, HealthDataType.BODY_MASS_INDEX: HealthDataUnit.NO_UNIT, HealthDataType.BODY_TEMPERATURE: HealthDataUnit.DEGREE_CELSIUS, HealthDataType.BODY_WATER_MASS: HealthDataUnit.KILOGRAM,