cph-cachet / flutter-plugins

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

[health 3.4.4] No new data on subsequent queries #546

Open Parfyonator opened 2 years ago

Parfyonator commented 2 years ago

Remember to specify the plugin name in the title!

Device / Emulator and OS

Please complete the following information for each phone and/or emulator you're experiencing this bug on:

Describe the bug

The fresh and up-to-date data is returned only on the very first query. The subsequent queries return the subset of the very first query: as the time window moves forward the less and less data is left in the returned list.

To Reproduce

// make multiple calls with some time intervals to reproduce
final now = DateTime.now();
final healthData = await HealthFactory().getHealthDataFromTypes(
  now.subtract(Duration(seconds: 120)),
  now,
  [HealthDataType.HEART_RATE]
);
healthData.sort(((HealthDataPoint a, HealthDataPoint b) =>  b.dateTo.compareTo(a.dateTo)));
print(healthData.map((e) => e.value));

Eventually the list becomes empty.

Expected behavior

Get up-to-date data on every query (as it happens on the very first query).

Actual behavior

Subsequent queries eventually result in empty returned list.

Screenshots

If applicable, add screenshots to help explain your problem.

Flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.10.5, on macOS 12.3.1 21E258 darwin-arm, locale
    en-UA)
[✓] Android toolchain - develop for Android devices (Android SDK version
    32.1.0-rc1)
[✓] Xcode - develop for iOS and macOS (Xcode 13.3)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.1)
[✓] VS Code (version 1.67.1)
[✓] Connected device (2 available)
    ! Error: Oleksandr’s iPhone is busy: Preparing the watch for development via
      Oleksandr’s iPhone. Xcode will continue when Oleksandr’s iPhone is
      finished. (code -10)
[✓] HTTP Host Availability

• No issues found!

Additional information

Add any other info about the problem here.

Parfyonator commented 2 years ago

Here is an example app that shows the problem: https://github.com/Parfyonator/FlutterHealthTest

The only way to get new portion of data is to collapse the running application and bring it back again.

Additional note: I'm using Apple Watch 7 as a heart beat sensor.

MadsVSChristensen commented 2 years ago

Hey @Parfyonator

I've tested this but I'm unable recreate the issue. Using your example app i seem to get the sliding window correctly with new values I add concurrently. As I didn't have an Apple Watch available, I can't conclude if there is an issue with that, but for now I suggest you test with Health 4.0.0 and check if the issue persists.

Regards, Mads

Parfyonator commented 2 years ago

Hello @MadsVSChristensen . I've updated Health package to version 4.0.0. Nothing have changed. I'll try to make a video to show what is happening.

Also I want to share an update: sometimes it gives a new potion of data but the time interval is not consistent (sometimes it is under a minute, sometimes it 2-5 minutes). Maybe that's because Health app on iPhone doesn't get updates from Apple Watch very often. On the other hand, it gives new data after collapsing the app and bringing it back again.

I also tried another package, but faced the same issue. I'm not sure if this task with real-time heart rate reading may be accomplished without a companion app on Apple Watch, so I ended up writing one in Swift that streams heartbeat data from apple watch to my flutter app.

MadsVSChristensen commented 2 years ago

Hey @Parfyonator

Thanks for the update. It does seem like the issue might be related to the time interval between updates from the Apple Watch to the Health app. When I tested it, I added data manually (on a button press) which worked as intended. This suggests the issues lies in the update interval.

I was unable to locate any information in the HealthKit documentation about the update interval, but did find an old post about it here. It seems to require starting a "Workout", which you might want to look into.

Hope this helps.

Regards, Mads

Parfyonator commented 2 years ago

Hi @MadsVSChristensen

I've already seen that link on apple developer forum. I also found it while was researching the problem. Yes, I was unable to get any HBPM untill starting a workout session. But after starting it manually on my Apple Watch I had the exact behaviour I've described earlier. In the companion app I wrote for my Apple Watch I also had to start workout session in the background in order to get HBPM in real-time, though it works differently than a regular workout session that you start manually: you have to start/pause/stop from your companion app and manage all this controls yourself (this background workout is not available in the standard Apple application).

In the dart package I've mentioned earlier (health_kit_reporter) there is a functionality to start workout session but I didn't manage to start it using it. It doesn't seem to work properly at the moment. But I still will try to make it work. I'm hoping to be able to start background workout session from my flutter app without corresponding companion app on the Apple Watch. If it works out I can share the progress (if you'd like, of course).

Best regards, Oleksandr

imskm commented 1 year ago

Hello @Parfyonator, I am dealing with the same issue. I have created an app using health package, the app fetches the heart rate for the first time when the app is opened but after fetching the heart rate from inside an interval function, I don't get the latest heart rate.

When I try to open the Apple Health app (in real physical phone and watch) then my app gets updated heart rate.

Have you found any solution to that?

Parfyonator commented 1 year ago

Hi @imskm. My solution was to implement an Apple Watch companion app and stream heartbeat data to iphone via method channel. The downside is that it requires additional actions from user: he/she has to open this companion app and press "play" (to start a workout). But it gives realtime data (every few seconds).

If you are interested in how it can be done. Here is a repo with sample Apple Watch companion app which you can extend: https://github.com/theamorn/flutter-apple-watch

It will require some Swift coding but not that much. I've uploaded a repo to GitHub a while ago with a very messy implementation based on the mentioned repository. I'm using the health_kit_reported plugin there which actually is not needed. But you can use it as a reference https://github.com/Parfyonator/FlutterAppleWatchPulsemeter

Hope it helps