cph-cachet / flutter-plugins

A collection of Flutter plugins developed by CACHET
550 stars 678 forks source link

[HEALTH 11.1.0] getTotalStepsInInterval returns wrong value when compared with App Health. #1072

Open tntkhang opened 2 weeks ago

tntkhang commented 2 weeks ago

Hello guys, I am using the Health plugin in version 11.1.0, and it is a wonderful library. But when using it on iOS, I found a problem and did not know how to solve it.

Device/Emulator and OS

Device: iPhone 13 Promax + Apple Watch, iPhone 12 Promax + AppleWatch. OS: iOS 18.0.1

NB: Bugs pertaining to old devices/OS versions will likely not be fixed.

Describe the bug

As the requirement, I need to get a step count of the previous 30 days. But the output of the function getTotalStepsInInterval() return does not match with the Health App display just in a few days. Please see the log, and if you are in the same situation, please help.

The log when using the function getTotalStepsInInterval()

To Reproduce

Run the function log the previous 30 days on any phone that has connected with Apple Watch. `  extension DateUtil on DateTime { DateTime startOfTheDay() => DateTime(year, month, day); DateTime endOfTheDay() => DateTime(year, month, day, 23, 59, 59); } void logStepsRecordPrevious30Days() async { for (int i = 0; i <= 30; i++) { DateTime start Date = DateTime.now(). subtract(Duration(days: i)).  startOfTheDay(); DateTime endDate = DateTime.now(). subtract(Duration(days: i)).  endOfTheDay(); int? totalStepCount = await health. getTotalStepsInInterval(startDate, endDate);

Logger.i('Health STEP: $totalStepCount | from: $startDate - to: $endDate'); } }`

Expected behavior

All the steps must be exactly like the health display.

Actual behavior

Some days are not matched with health displ

Screenshotsay

The screenshot from the log, use function getTotalStepsInInterval():

image

And the screenshot from app Health -> Steps -> Show All Data image

On 2 days: Oct 30 and Oct 31, we have a difference step count between the log and the health app.

Thanks.

benmartin88 commented 2 weeks ago

We are seeing the same issue and behaviour.

For example, if a user has both an iPhone and Apple Watch, and has both them on their body at the time steps are recorded, Apple Health will not aggregate values recorded at the same time, based on the priority order of data sources.

However this integration appears to aggregate all records which results in a mismatch between the integration and Apple Health.

In my opinion it would be preferable to be able to query Apple Health for its total value rather than just the records directly.

We believe this is not unique to iOS though and is also happening in Health Connect.

tntkhang commented 2 weeks ago

I have fixed it on my end, download the library to local, by modifying the native code using HKStatisticsCollectionQuery instead of HKStatisticsQuery. The result return exactly value displayed in Health App.

benmartin88 commented 2 weeks ago

I have fixed it on my end, download the library to local, by modifying the native code using HKStatisticsCollectionQuery instead of HKStatisticsQuery. The result return exactly value displayed in Health App.

Can you please provide a code snippet and the file you have modified so we can try to replicate this potential fix?

tntkhang commented 2 weeks ago

My native code is not good so I dupplicated code a lot, but at least hope it help.

https://github.com/tntkhang/flutter_health_plugin/tree/main

tntkhang commented 1 week ago

For using HKStatisticsCollectionQuery the time interval for day must be from: 00:00:00 to 23:59:59, then value will be true; otherwise,  the value will be wrong in some days.

HassanAlyousef commented 1 week ago

I believe it has something to do with the start and end time, sometimes an entry will start and end on different days (i.e. Starts at 11:55PM and ends at 12:02AM) and this entry is sometimes counted for both days and sometimes it isn't, not sure how Apple chooses which is which

tntkhang commented 1 week ago

The main reason is just because the plugin uses the wrong query collection then returns the wrong value. You shouldn't calculate manually because each entry can have timestamps that overlap another. That's why you must use the same query function like Health does, and then it will return the same value. As I mentioned above, I found the solution. I can get exactly the correct value as displayed in Health; just use the HKStatisticsCollectionQuery instead of the HKStatisticsQuery. With the same phone as above, I have tested and it's return exactly value for every day in a year.

HassanAlyousef commented 1 week ago

The main reason is just because the plugin uses the wrong query collection then returns the wrong value. You shouldn't calculate manually because each entry can have timestamps that overlap another. That's why you must use the same query function like Health does, and then it will return the same value. As I mentioned above, I found the solution. I can get exactly the correct value as displayed in Health; just use the HKStatisticsCollectionQuery instead of the HKStatisticsQuery. With the same phone as above, I have tested and it's return exactly value for every day in a year.

Thank you for your response, I opened an Issue last week for the same exact problem, I'm trying to display Health Data for the current day and last week summary and when a user has multiple sources for the entries it gets messed up.

May I have the snippet code you use to return the last year values? Also, does it work on the other health data types or is it only for the steps? Thank you.

tntkhang commented 1 week ago

Yes It also works for other values: distance, calories... (which can come from multiple source: phone, apple watch) I have posted my code on an github which just modify Health plugin only, the link in the above comment. My native iOS code is not good so it's duplicated a lot. But at least the value totally match with Health.