Regular step count fetch and upload to API

Hello all,

I am quite new to iOS and Swift, and before venturing further, I feel it's better to ask for advice.

I have build a Type I diabetes simulator running as a NodeJS application on a server. The clients authenticate via a browser using Fitbit/Google oauth2, set up a virtual patient, then take care of the patient 24/7. The app imports the users steps and heartrate, as these influence the blood sugar variations. (https://cgmsim.com)

I designed a companion app with Expo, adding high/log blood glucose alerts with push notifications. If the user doesn't have a Fitbit tracker or doesn't use Google Fit, I'd like to send their HealthKit step counts to the backend. (Using sensor data directly in Android).

It works using Expo's Background Fetch and TaskManager, but the uploads from the iOS device are very irregular. I set up silent push notifications from the backend to wake up the app in the background and trigger the step count upload. It works, but it is not reliable enough.

I now wrote my first local native module for iOS, where a HKObserverQuery listening for new step events, making the upload and sending the count to the JS for rendering. I used enableBackgroundDelivery and BackgroundTask for uploading the results. All the entitlements and Info.plist entries should be ok. Still my app works well only in the foreground, and not upload at all happens when in the background.

As we all do, I asked Claude, and it assured me th app should work. I have doubts though, as I noticed how strict iOS is about executing background tasks. So... should I even expect this to work ?

Answered by DTS Engineer in 803861022

Yeah, handling background tasks is indeed a bit tricky because, to optimize the overall user experience, iOS implements a mechanism to coordinate the running of background tasks. The iOS Background Execution Limits post covers this topic quite a bit. You can take a look if haven't yet.

HeathKit adds a bit more complexity:

  • HKObserverQuery + enableBackgroundDelivery allows you to get notified when your app is running in the background and the observed Health data changes. However, when your iPhone is locked, the system can’t write any data to the HealthKit store, and so no change will happen.

  • HealthKit background updates are budgeted. On watchOS, we document here that your app can receive up to four updates (or background app refresh tasks) an hour. We don't have a similar documentation for iOS, but if the observed Health data type changes very frequently, I won't expect that every change triggers a background update.

In your case, you can probably start with logging your app's activities to figure out the following:

  1. Is the update handler of your HKObserverQuery triggered when your app runs in the background and the observed Health data changes?

  2. Is the background upload task successfully scheduled?

  3. Is your scheduled background task triggered?

A clear answer to these questions will narrow down your issue to a certain area, HealthKit or background uploading, and going from there, folks may be able to better comment.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Yeah, handling background tasks is indeed a bit tricky because, to optimize the overall user experience, iOS implements a mechanism to coordinate the running of background tasks. The iOS Background Execution Limits post covers this topic quite a bit. You can take a look if haven't yet.

HeathKit adds a bit more complexity:

  • HKObserverQuery + enableBackgroundDelivery allows you to get notified when your app is running in the background and the observed Health data changes. However, when your iPhone is locked, the system can’t write any data to the HealthKit store, and so no change will happen.

  • HealthKit background updates are budgeted. On watchOS, we document here that your app can receive up to four updates (or background app refresh tasks) an hour. We don't have a similar documentation for iOS, but if the observed Health data type changes very frequently, I won't expect that every change triggers a background update.

In your case, you can probably start with logging your app's activities to figure out the following:

  1. Is the update handler of your HKObserverQuery triggered when your app runs in the background and the observed Health data changes?

  2. Is the background upload task successfully scheduled?

  3. Is your scheduled background task triggered?

A clear answer to these questions will narrow down your issue to a certain area, HealthKit or background uploading, and going from there, folks may be able to better comment.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Regular step count fetch and upload to API
 
 
Q