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,