Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Health 12/1097 Lean Body Mass Type #1108

Merged
merged 11 commits into from
Jan 6, 2025
16 changes: 11 additions & 5 deletions packages/health/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
<uses-permission android:name="android.permission.health.READ_LEAN_BODY_MASS"/>
<uses-permission android:name="android.permission.health.WRITE_LEAN_BODY_MASS"/>
```
* 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

Expand Down
1 change: 1 addition & 0 deletions packages/health/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1083,6 +1084,29 @@ class HealthPlugin(private var channel: MethodChannel? = null) :
),
)

is LeanBodyMassRecord ->
return listOf(
mapOf<String, Any>(
"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<String, Any>(
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
<uses-permission android:name="android.permission.health.BODY_SENSORS"/>
<uses-permission android:name="android.permission.health.READ_MENSTRUATION"/>
<uses-permission android:name="android.permission.health.WRITE_MENSTRUATION"/>
<uses-permission android:name="android.permission.health.READ_LEAN_BODY_MASS"/>
<uses-permission android:name="android.permission.health.WRITE_LEAN_BODY_MASS"/>

<application android:label="health_example"
android:icon="@mipmap/ic_launcher">
Expand Down
18 changes: 18 additions & 0 deletions packages/health/example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
6 changes: 6 additions & 0 deletions packages/health/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@ class _HealthAppState extends State<HealthApp> {
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(
Expand Down
2 changes: 2 additions & 0 deletions packages/health/example/lib/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const List<HealthDataType> 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,
Expand Down Expand Up @@ -78,6 +79,7 @@ const List<HealthDataType> dataTypesAndroid = [
HealthDataType.BODY_FAT_PERCENTAGE,
HealthDataType.HEIGHT,
HealthDataType.WEIGHT,
HealthDataType.LEAN_BODY_MASS,
// HealthDataType.BODY_MASS_INDEX,
HealthDataType.BODY_TEMPERATURE,
HealthDataType.HEART_RATE,
Expand Down
3 changes: 3 additions & 0 deletions packages/health/ios/Classes/SwiftHealthPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)!

Expand Down Expand Up @@ -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)!

Expand Down
1 change: 1 addition & 0 deletions packages/health/lib/health.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions packages/health/lib/src/heath_data_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -127,6 +128,7 @@ const List<HealthDataType> 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,
Expand Down Expand Up @@ -220,6 +222,7 @@ const List<HealthDataType> 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,
Expand Down Expand Up @@ -260,6 +263,7 @@ const Map<HealthDataType, HealthDataUnit> 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,
Expand Down
Loading