HealthKit & # 8594; Heart Rate Monitoring HKAnchoredObjectQuery called only after the DidBecomeActive application (BUG or FEATURE?)

I am writing a simple heart rate monitoring application (HKQuantityTypeIdentifierHeartRate) from HealthKit whenever a new health speed value is written to HealthKit.

As seen at WWDC2015 (Session 203), I am using HKAnchoredObjectQuery , which should work to add and remove objects. Whenever I run the application, I call HKQuery for the latest objects and executeQuery , which works fine !!! But I do not have new samples, even if there are samples, but if I bring the application to the background and again to the fore, I get all new heart rates. This is mistake? Or what should I do to control my heart rate without bringing the app to the background?

Here is the code I use (everything is stored in AppDelegate), I call [self requestAccessDataTypes]; from didFinishLaunchingWithOptions :

 [healthStore enableBackgroundDeliveryForType:sampleType frequency:HKUpdateFrequencyImmediate withCompletion:^(BOOL success, NSError *error) {}]; HKQuery *query = [self createHeartRateStreamingQuery:datum]; if (query) { [healthStore executeQuery:query]; } else { NSLog(@"workout can not start"); } 

 -(HKQuery*)createHeartRateStreamingQuery:(NSDate*)workoutStartDate { NSLog(@"%@ - createHeartRateStreamingQuery", [self class]); if ([HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]) { HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; HKAnchoredObjectQuery * heartRateQuery = [[HKAnchoredObjectQuery alloc] initWithType:quantityType predicate:nil anchor:anchor limit:HKObjectQueryNoLimit resultsHandler:^(HKAnchoredObjectQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable sampleObjects, NSArray<HKDeletedObject *> * _Nullable deletedObjects, HKQueryAnchor * _Nullable newAnchor, NSError * _Nullable error) { if (!error) { anchor = newAnchor; [self updateHeartRate:sampleObjects]; } }]; heartRateQuery.updateHandler = ^void(HKAnchoredObjectQuery *query, NSArray<__kindof HKSample *> * __nullable addedObjects, NSArray<HKDeletedObject *> * __nullable deletedObjects, HKQueryAnchor * __nullable newAnchor, NSError * __nullable error) { if (!error) { anchor = newAnchor; [self updateHeartRate:addedObjects]; } }; return heartRateQuery; } return nil; } ] initWithType: quantityType predicate: nil anchor: anchor limit: HKObjectQueryNoLimit resultsHandler: ^ (HKAnchoredObjectQuery * _Nonnull query, NSArray <__ kindof HKSample *> * _Nullable sampleObjects, NSArray <HKDeletedObject *> * _Nullable deletedObjects, HKQueryAnchor -(HKQuery*)createHeartRateStreamingQuery:(NSDate*)workoutStartDate { NSLog(@"%@ - createHeartRateStreamingQuery", [self class]); if ([HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]) { HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; HKAnchoredObjectQuery * heartRateQuery = [[HKAnchoredObjectQuery alloc] initWithType:quantityType predicate:nil anchor:anchor limit:HKObjectQueryNoLimit resultsHandler:^(HKAnchoredObjectQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable sampleObjects, NSArray<HKDeletedObject *> * _Nullable deletedObjects, HKQueryAnchor * _Nullable newAnchor, NSError * _Nullable error) { if (!error) { anchor = newAnchor; [self updateHeartRate:sampleObjects]; } }]; heartRateQuery.updateHandler = ^void(HKAnchoredObjectQuery *query, NSArray<__kindof HKSample *> * __nullable addedObjects, NSArray<HKDeletedObject *> * __nullable deletedObjects, HKQueryAnchor * __nullable newAnchor, NSError * __nullable error) { if (!error) { anchor = newAnchor; [self updateHeartRate:addedObjects]; } }; return heartRateQuery; } return nil; } 
+5
source share
2 answers

Now (iOS 9.1, WatchOS 2.0.1) it is not possible to get the latest data from HealthKit through the iOS app. This is possible in the WWDC demo, because the code was executed in the WatchOS ExtensionDelegate application, and not in the iOS application. There is an rdar error report presented here .

To get the latest data on iOS, this is not possible without creating the WatchOS application. With the WatchOS app, you can use a training session and Watch Connectivity send heart rate data to the iOS app every time it changes.

Of course, this will not help if the heart rate data does not come from the Apple Watch. I hope it will be fixed in the upcoming release.

+1
source

You are missing an important part for monitoring changes in HealthKit. It is called HKObserverQuery .

Documentation

Inquiries from observers set a long-term task in the background. This task monitors the HealthKit store and alerts you every time comparable data is saved or deleted from the store. Observer requests let your application respond to changes made by other applications and devices.

Summary

You need to wrap your HKAnchoredObjectQuery in HKObserverQuery if background delivery is enabled to receive notification of updates. Then you can fulfill your request when this happens.

Note 1: The HKObserverQuery update handler will NOT give you any sample Apple Health data. You still need to execute your HKAnchoredObjectQuery with the proper anchor to get the samples.

Note 2: every time you start the application, you need to configure HKObserverQuery .

See my answer here for more information.

0
source

Source: https://habr.com/ru/post/1234748/


All Articles