Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force a HKQuery to load the most recent steps counts?

Currently I'm trying to use HKStatisticsQuery to get the steps count between a certain time interval. I'm doing test by shaking the phone myself. However, it seems that the result I get is not the most recent one, unless:

  1. I open the Health.app, keep it running in background, and do the test again in my app;
  2. I open the UP app, keep it running in background, and do the test again in my app.

And if I force-quit the Health.app orUP app, my app will not be able to get the most recent data again. So UP must be doing something I'm missing, but I can't find there's any "reload" like method in HKHealthStore, or any related options in HKQuery/HKStatisticsQuery.

The code I'm using is quite straight forward as below. I wonder if there's any permissions or anything I'm missing.

    let predicate = HKQuery.predicateForSamplesWithStartDate(date_start, endDate: NSDate(), options: HKQueryOptions.StrictStartDate)
    var type = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)
    var query = HKStatisticsQuery(quantityType: type,
        quantitySamplePredicate: predicate,
        options: .CumulativeSum | .SeparateBySource,
        completionHandler: { query, stats, error in ( /*logs here*/ ) })
    let healthStore = HKHealthStore()
    healthStore.executeQuery(query)

Edit: I also tried to write some data to HealthKit but the query doesn't get updated.

Edit2: when I said "most recent steps counts" I meant something like: 1. execute HKQuery; 2. shake phone; 3. execute HKQuery again. Running the code above for 2 times and I always get the same results, but if I left Health.app or the UP app in the background, the latest query got the updated results.

I also tried to call some other APIs like:

    healthStore.enableBackgroundDeliveryForType(type, frequency:.Immediate, withCompletion:{
        (success:Bool, error:NSError!) -> Void in
        let authorized = healthStore.authorizationStatusForType(type)
        LF.log("HEALTH callback success", success)
        LF.log("HEALTH callback authorized", type)
    })

    if HKHealthStore.isHealthDataAvailable() == false {
        LF.log("HEALTH data not available")
        return
    } else {
        LF.log("HEALTH OK")
    }

For almost no reason but try to secretly "trigger" some sort of background refresh. But none of these attempts worked.

like image 278
superarts.org Avatar asked Dec 14 '22 18:12

superarts.org


1 Answers

HealthKit does not always have an up-to-date count of the user's steps and distance travelled. It imports these values, which actually come from CoreMotion.framework, periodically and in response to certain events. If a running application has an open HKObserverQuery or HKStatisticsCollectionQuery then HealthKit will stream the values to the client but otherwise the samples are just a snapshot from the last import.

So if you'd like to observe changes for a sample type, you should subscribe to updates using an HKObserverQuery and then query HealthKit again for the latest values. A more efficient approach would be to use HKStatisticsCollectionQuery, though, which has an update handler that will be invoked as the statistics for the samples matching the predicates change.

Finally, if you're only interested up-to-date step counts or distance travelled for at most the past 7 days then I recommend that you consider using CoreMotion.framework directly instead.

like image 134
Allan Avatar answered Mar 08 '23 04:03

Allan