We're currently trying to get HealthKit to work in the background, in order to deliver steps data to our server when the App is closed.
For experimental purposes we've created a brand new iOS project in XCode, enabled HealhtKit and all background modes in Compabilities. After that, we pretty much run the code (see further down).
So what happens first is that the app ofcourse asks for the permissions, which we grant. What we're expecting is that the app should keep deliver the steps data every hour, to the server. But it doesnt do that, it seems like the app cant do anything when it's not active.
The app only deliver data when it gets resumed or started, but not at all from the background (Soft-closed / Hard-closed)
appdelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self setTypes];
return YES;
}
-(void) setTypes
{
self.healthStore = [[HKHealthStore alloc] init];
NSMutableSet* types = [[NSMutableSet alloc]init];
[types addObject:[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]];
[self.healthStore requestAuthorizationToShareTypes: types
readTypes: types
completion:^(BOOL success, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[self observeQuantityType];
[self enableBackgroundDeliveryForQuantityType];
});
}];
}
-(void)enableBackgroundDeliveryForQuantityType{
[self.healthStore enableBackgroundDeliveryForType: [HKQuantityType quantityTypeForIdentifier: HKQuantityTypeIdentifierStepCount] frequency:HKUpdateFrequencyImmediate withCompletion:^(BOOL success, NSError *error) {
}];
}
-(void) observeQuantityType{
HKSampleType *quantityType = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
HKObserverQuery *query =
[[HKObserverQuery alloc]
initWithSampleType:quantityType
predicate:nil
updateHandler:^(HKObserverQuery *query,
HKObserverQueryCompletionHandler completionHandler,
NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (completionHandler) completionHandler();
[self getQuantityResult];
});
}];
[self.healthStore executeQuery:query];
}
-(void) getQuantityResult{
NSInteger limit = 0;
NSPredicate* predicate = nil;
NSString *endKey = HKSampleSortIdentifierEndDate;
NSSortDescriptor *endDate = [NSSortDescriptor sortDescriptorWithKey: endKey ascending: NO];
HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType: [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]
predicate: predicate
limit: limit
sortDescriptors: @[endDate]
resultsHandler:^(HKSampleQuery *query, NSArray* results, NSError *error){
dispatch_async(dispatch_get_main_queue(), ^{
// sends the data using HTTP
[self sendData: [self resultAsNumber:results]];
});
}];
[self.healthStore executeQuery:query];
}
I see something that might be causing an issue in your
AppDelegate
, particularly this line:This is creating an NSURLConnection, but not starting it. Try changing it to this:
Edit: After taking a second look at the docs
They recommend setting up your observer queries in your
application didFinishLaunchingWithOptions:
method. In your code above, you set theHKObserverQuery
up in the authorization handler, which is called on a random background queue. Try making this change to set it up on the main thread:HKObserverQuery Reference