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]: Improve support for RecordingMethod on Health Connect and HKWasUserEntered on iOS #1023

Merged
merged 35 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c582918
Remove Google Fit and imports from Android code
SlimShadyIAm Aug 6, 2024
2590ffe
Formatting
SlimShadyIAm Aug 6, 2024
58159bf
Merge branch 'master' into feature/remove-google-fit
SlimShadyIAm Aug 6, 2024
401fa75
Remove Google Fit column from readme
SlimShadyIAm Aug 6, 2024
aa4c763
Remove support for Google Fit types not supported by Health Connect
SlimShadyIAm Aug 6, 2024
2acaaf6
Remove more Google Fit workout types
SlimShadyIAm Aug 6, 2024
58a6ae7
Remove references to Google Fit, remove `useHealthConnectIfAvailable`
SlimShadyIAm Aug 7, 2024
f8bbc42
Remove `disconect` method channel
SlimShadyIAm Aug 7, 2024
99eae33
Remove `flowRate` from `writeBloodOxygen` as it is not supported in H…
SlimShadyIAm Aug 7, 2024
99ae5dd
Remove more unsupported workout types
SlimShadyIAm Aug 7, 2024
d604507
Add missing import
SlimShadyIAm Aug 8, 2024
458d323
Remove Google Fit as dependency
SlimShadyIAm Aug 8, 2024
c732a9e
Add notice in README
SlimShadyIAm Aug 8, 2024
0e248a6
Improve logging for HC permission callback
SlimShadyIAm Aug 8, 2024
0f5fb5a
Update some documentation
SlimShadyIAm Aug 8, 2024
3979573
Android: Fix `requestAuthorization` not returning a result on success
SlimShadyIAm Aug 8, 2024
d663b25
Remove additional workout types that are not supported
SlimShadyIAm Aug 8, 2024
1bb375c
Remove another workout type
SlimShadyIAm Aug 8, 2024
94aceae
Add missing unimplemented method
SlimShadyIAm Aug 8, 2024
240d427
Include recording method from Android metadata in HealthDataPoint
SlimShadyIAm Aug 14, 2024
fa69767
Support writing data with custom recording method on Android
SlimShadyIAm Aug 14, 2024
cedfd0b
Improve RecordingMethod enum
SlimShadyIAm Aug 14, 2024
2267115
Support filtering by recording method when fetching data
SlimShadyIAm Aug 14, 2024
f8a3017
Fix `includeManualEntry` for `getTotalStepsInInterval`
SlimShadyIAm Aug 15, 2024
373799a
Support recording method on iOS
SlimShadyIAm Aug 15, 2024
885a929
Recording method when writing on iOS (WIP)
SlimShadyIAm Aug 15, 2024
468eaa1
Fix filtering manual entries when fetching data on iOS
SlimShadyIAm Aug 15, 2024
9c7b1b8
Rename variable in example app
SlimShadyIAm Aug 15, 2024
041bb22
Update documentation
SlimShadyIAm Aug 15, 2024
d5f235c
Improvements to example app
SlimShadyIAm Aug 15, 2024
31b6e3c
Merge branch 'master' into feature/recording-method
SlimShadyIAm Aug 29, 2024
f3a7276
Quick fix
SlimShadyIAm Aug 29, 2024
cac7736
Update documentation
SlimShadyIAm Aug 29, 2024
7d4d1e1
Merge branch 'master' into feature/recording-method
SlimShadyIAm Aug 30, 2024
8d398ba
Update iOS docs
SlimShadyIAm Aug 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions packages/health/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ Below is a simplified flow of how to use the plugin.
bool success = await Health().writeHealthData(10, HealthDataType.STEPS, now, now);
success = await Health().writeHealthData(3.1, HealthDataType.BLOOD_GLUCOSE, now, now);
// you can also specify the recording method to store in the metadata (default is RecordingMethod.automatic)
// on iOS only `RecordingMethod.automatic` and `RecordingMethod.manual` are supported
// Android additionally supports `RecordingMethod.active` and `RecordingMethod.unknown`
success &= await Health().writeHealthData(10, HealthDataType.STEPS, now, now, recordingMethod: RecordingMethod.manual);
// get the number of steps for today
var midnight = DateTime(now.year, now.month, now.day);
int? steps = await Health().getTotalStepsInInterval(midnight, now);
Expand All @@ -201,7 +206,7 @@ HealthPlatformType sourcePlatform;
String sourceDeviceId;
String sourceId;
String sourceName;
bool isManualEntry;
RecordingMethod recordingMethod;
WorkoutSummary? workoutSummary;
```

Expand All @@ -223,7 +228,7 @@ A `HealthDataPoint` object can be serialized to and from JSON using the `toJson(
"source_device_id": "F74938B9-C011-4DE4-AA5E-CF41B60B96E7",
"source_id": "com.apple.health.81AE7156-EC05-47E3-AC93-2D6F65C717DF",
"source_name": "iPhone12.bardram.net",
"is_manual_entry": false
"recording_method": 3
"value": {
"__type": "NumericHealthValue",
"numeric_value": 141.0
Expand All @@ -236,7 +241,7 @@ A `HealthDataPoint` object can be serialized to and from JSON using the `toJson(
"source_device_id": "F74938B9-C011-4DE4-AA5E-CF41B60B96E7",
"source_id": "com.apple.health.81AE7156-EC05-47E3-AC93-2D6F65C717DF",
"source_name": "iPhone12.bardram.net",
"is_manual_entry": false
"recording_method": 2
}
```

Expand All @@ -251,6 +256,28 @@ flutter: Health Plugin Error:
flutter: PlatformException(FlutterHealth, Results are null, Optional(Error Domain=com.apple.healthkit Code=6 "Protected health data is inaccessible" UserInfo={NSLocalizedDescription=Protected health data is inaccessible}))
```

### Filtering by recording method
Google Health Connect and Apple HealthKit both provide ways to distinguish samples collected "automatically" and manually entered data by the user.

- Android provides an enum with 4 variations: https://developer.android.com/reference/kotlin/androidx/health/connect/client/records/metadata/Metadata#summary
- iOS has a boolean value: https://developer.apple.com/documentation/healthkit/hkmetadatakeywasuserentered

As such, when fetching data you have the option to filter the fetched data by recording method as such:

```dart
List<HealthDataPoint> healthData = await Health().getHealthDataFromTypes(
types: types,
startTime: yesterday,
endTime: now,
recordingMethodsToFilter: [RecordingMethod.manual, RecordingMethod.unknown],
);
```

**Note that for this to work, the information needs to have been provided when writing the data to Health Connect or Apple Health**. For example, steps added manually through the Apple Health App will set `HKWasUserEntered` to true (corresponding to `RecordingMethod.manual`), however it seems that adding steps manually to Google Fit does not write the data with the `RecordingMethod.manual` in the metadata, instead it shows up as `RecordingMethod.unknown`. This is an open issue, and as such filtering manual entries when querying step count on Android with `getTotalStepsInInterval(includeManualEntries: false)` does not necessarily filter out manual steps.

**NOTE**: On iOS, you can only filter by `RecordingMethod.automatic` and `RecordingMethod`.manual` as it is stored `HKMetadataKeyWasUserEntered` is a boolean value in the metadata.


### Filtering out duplicates

If the same data is requested multiple times and saved in the same array duplicates will occur.
Expand Down
Loading
Loading