Skip to content

Commit

Permalink
Merge pull request #1109 from cph-cachet/health-12/1096-underwater-di…
Browse files Browse the repository at this point in the history
…ving

Add support for WaterTemperature and UnderwaterDepth data types and UnderwaterDiving workout in iOS
  • Loading branch information
iarata authored Jan 6, 2025
2 parents 7a98254 + 54b8fbf commit 4017e03
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 211 deletions.
2 changes: 2 additions & 0 deletions packages/health/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* Updated `intl` to ^0.20.1 - Closes [#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
4 changes: 4 additions & 0 deletions packages/health/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,9 @@ The plugin supports the following [`HealthDataType`](https://pub.dev/documentati
| ELECTROCARDIOGRAM | VOLT | yes | | Requires Apple Watch to write the data |
| NUTRITION | NO_UNIT | yes | yes | |
| INSULIN_DELIVERY | INTERNATIONAL_UNIT | yes | | |
| 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 |

## Workout Types

Expand Down Expand Up @@ -443,6 +446,7 @@ The plugin supports the following [`HealthWorkoutActivityType`](https://pub.dev/
| TENNIS | yes | yes | |
| TRACK_AND_FIELD | yes | | |
| TRADITIONAL_STRENGTH_TRAINING | yes | (yes) | on Android this will be stored as STRENGTH_TRAINING |
| UNDERWATER_DIVING | yes | | |
| VOLLEYBALL | yes | yes | |
| WALKING | yes | yes | |
| WATER_FITNESS | yes | | |
Expand Down
34 changes: 31 additions & 3 deletions packages/health/example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
8AB8966E9F27B6C816D51EA9 /* [CP] Embed Pods Frameworks */,
99FD4B47838A33EC942FDC35 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand Down Expand Up @@ -271,6 +272,24 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
99FD4B47838A33EC942FDC35 /* [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;
};
AFF7CCF5217A091E1625CD54 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -394,7 +413,10 @@
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
Expand Down Expand Up @@ -531,7 +553,10 @@
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
Expand Down Expand Up @@ -564,7 +589,10 @@
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
Expand Down
19 changes: 19 additions & 0 deletions packages/health/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,25 @@ class _HealthAppState extends State<HealthApp> {
endTime: now,
);

// Available on iOS 16.0+ only
if (Platform.isIOS) {
success &= await Health().writeHealthData(
value: 22,
type: HealthDataType.WATER_TEMPERATURE,
startTime: earlier,
endTime: now,
recordingMethod: RecordingMethod.manual
);

success &= await Health().writeHealthData(
value: 55,
type: HealthDataType.UNDERWATER_DEPTH,
startTime: earlier,
endTime: now,
recordingMethod: RecordingMethod.manual
);
}

setState(() {
_state = success ? AppState.DATA_ADDED : AppState.DATA_NOT_ADDED;
});
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 @@ -59,6 +59,8 @@ const List<HealthDataType> dataTypesIOS = [
HealthDataType.BLOOD_TYPE,
HealthDataType.BIRTH_DATE,
HealthDataType.MENSTRUATION_FLOW,
HealthDataType.WATER_TEMPERATURE,
HealthDataType.UNDERWATER_DEPTH,
];

/// List of data types available on Android.
Expand Down
14 changes: 13 additions & 1 deletion packages/health/ios/Classes/SwiftHealthPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin {
let GENDER = "GENDER"
let BLOOD_TYPE = "BLOOD_TYPE"
let MENSTRUATION_FLOW = "MENSTRUATION_FLOW"
let WATER_TEMPERATURE = "WATER_TEMPERATURE"
let UNDERWATER_DEPTH = "UNDERWATER_DEPTH"


// Health Unit types
Expand Down Expand Up @@ -857,7 +859,8 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin {
"recording_method": (sample.metadata?[HKMetadataKeyWasUserEntered] as? Bool == true)
? RecordingMethod.manual.rawValue
: RecordingMethod.automatic.rawValue,
"metadata": dataTypeKey == INSULIN_DELIVERY ? sample.metadata : nil
"metadata": dataTypeKey == INSULIN_DELIVERY ? sample.metadata : nil,
"dataUnitKey": unit?.unitString
]
}
DispatchQueue.main.async {
Expand Down Expand Up @@ -1384,6 +1387,10 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin {
workoutActivityTypeMap["TAI_CHI"] = .taiChi
workoutActivityTypeMap["WRESTLING"] = .wrestling
workoutActivityTypeMap["OTHER"] = .other
if #available(iOS 17.0, *) {
workoutActivityTypeMap["UNDERWATER_DIVING"] = .underwaterDiving
}

nutritionList = [
DIETARY_ENERGY_CONSUMED, DIETARY_CARBS_CONSUMED, DIETARY_PROTEIN_CONSUMED,
DIETARY_FATS_CONSUMED, DIETARY_CAFFEINE, DIETARY_FIBER, DIETARY_SUGAR,
Expand Down Expand Up @@ -1617,6 +1624,9 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin {

if #available(iOS 16.0, *) {
dataTypesDict[ATRIAL_FIBRILLATION_BURDEN] = HKQuantityType.quantityType(forIdentifier: .atrialFibrillationBurden)!

dataTypesDict[WATER_TEMPERATURE] = HKQuantityType.quantityType(forIdentifier: .waterTemperature)!
dataTypesDict[UNDERWATER_DEPTH] = HKQuantityType.quantityType(forIdentifier: .underwaterDepth)!
}

// Concatenate heart events, headache and health data types (both may be empty)
Expand Down Expand Up @@ -1774,6 +1784,8 @@ public class SwiftHealthPlugin: NSObject, FlutterPlugin {
return "mixedCardio"
case .handCycling:
return "handCycling"
case .underwaterDiving:
return "underwaterDiving"
default:
return "other"
}
Expand Down
4 changes: 2 additions & 2 deletions packages/health/ios/health.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
#
Pod::Spec.new do |s|
s.name = 'health'
s.version = '1.0.4'
s.version = '12.0.0'
s.summary = 'Wrapper for Apple\'s HealthKit on iOS and Google\'s Health Connect on Android.'
s.description = <<-DESC
Wrapper for Apple's HealthKit on iOS and Google's Health Connect on Android.
DESC
s.homepage = 'https://pub.dev/packages/health'
s.license = { :file => '../LICENSE' }
s.author = { 'Copenhagen Center for Health Technology' => '[email protected]' }
s.author = { 'Copenhagen Research Platform at DTU' => '[email protected]' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
Expand Down
Loading

0 comments on commit 4017e03

Please sign in to comment.