14

我们目前正在尝试让 HealthKit 在后台工作,以便在应用程序关闭时将步数数据传送到我们的服务器。

出于实验目的,我们在 XCode 中创建了一个全新的 iOS 项目,启用了 HealhtKit 和 Compabilities 中的所有背景模式。之后,我们几乎运行代码(见下文)。

所以首先发生的是应用程序当然会要求我们授予的权限。我们期望的是应用程序应该每小时将步数数据传送到服务器。但它没有这样做,似乎应用程序在不活动时无法做任何事情。

该应用程序仅在恢复或启动时提供数据,但根本不从后台传递数据(软关闭/硬关闭)

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];
}
4

2 回答 2

5

不久前,我在与 Apple 的某个人交谈时发现了这一点。显然,如果设备被锁定,您将无法在后台访问 HK 数据:

笔记

因为 HealthKit 存储是加密的,所以当手机被锁定时,您的应用程序无法从存储中读取数据。这意味着您的应用在后台启动时可能无法访问商店。但是,即使手机被锁定,应用程序仍然可以将数据写入商店。商店会暂时缓存数据,并在手机解锁后立即将其保存到加密存储中。

来自: https ://developer.apple.com/library/ios/documentation/HealthKit/Reference/HealthKit_Framework/

于 2015-06-28T22:18:42.170 回答
0

我看到一些可能导致您的问题的东西AppDelegate,尤其是这一行:

[[NSURLConnection alloc] initWithRequest:request delegate:self];

这是创建一个 NSURLConnection,但没有启动它。尝试将其更改为:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];

编辑:在再次查看文档后

application didFinishLaunchingWithOptions:他们建议在您的方法中设置您的观察者查询。在上面的代码中,您HKObserverQuery在授权处理程序中进行了设置,该处理程序在随机后台队列中调用。尝试进行此更改以在主线程上进行设置:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self setTypes];
    [self observeQuantityType];
    return YES;
}

HKObserver查询参考

于 2015-05-15T21:43:31.360 回答