屏幕锁定时的 HealthStore enableBackgroundDelivery

Posted

技术标签:

【中文标题】屏幕锁定时的 HealthStore enableBackgroundDelivery【英文标题】:HealthStore enableBackgroundDelivery when screen is locked 【发布时间】:2015-02-11 15:34:14 【问题描述】:

您好,我正在尝试设置启用了后台交付的健康商店观察者。我的问题是屏幕锁定时它不会提供任何东西。我已经简化了我的代码来解决这个问题:) 我的 plist 中有 HealthKit,并且我接受了 healthStore 类型的步数。 当应用程序打开并且屏幕未锁定时,一切都很好。但是当屏幕被锁定时,我没有得到任何观察。 出于测试目的,频率设置为立即。

我的代码如下

- (void)setupHealthStore
if ([HKHealthStore isHealthDataAvailable])

    NSSet *readDataTypes = [self dataTypesToRead];
    self.healthStore = [[HKHealthStore alloc]init];
    [self.healthStore requestAuthorizationToShareTypes:nil readTypes:readDataTypes completion:^(BOOL success, NSError *error)
     
         if (success)
         
             HKQuantityType *quantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
             [self.healthStore enableBackgroundDeliveryForType:quantityType frequency:HKUpdateFrequencyImmediate withCompletion:^(BOOL success, NSError *error)
             
                 if (success)
                 
                     [self setupObserver];
                 
             ];
         
     ];

上述方法在AppDelegate didfinishLaunchWithOptions中调用

下一个方法是

- (void)setupObserver
HKQuantityType *quantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
HKObserverQuery *query = [[HKObserverQuery alloc]initWithSampleType:quantityType predicate:nil updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError *error)

    if (!error)
    
        [self alarm];
        if (completionHandler)
        
            NSLog(@"Completed");
            completionHandler();
        
    
    else
    
        if (completionHandler)
        
            completionHandler();
        
    
];
[self.healthStore executeQuery:query];

当我打开应用程序时,它会立即返回观察结果。

【问题讨论】:

看看我的回答:***.com/a/35073904/1677480 【参考方案1】:

当 iPhone 被锁定时,您无法以任何方式访问 healthKit 数据。

当 iPhone 解锁但应用处于后台时,只能使用 HKObserverQuery,用于了解是否添加了一些新样本。

当 iPhone 解锁并且应用程序处于前台时,您可以使用与 HealthKit 框架相关的所有内容。

【讨论】:

这应该是正确的答案。当设备屏幕关闭并且设置了密码(这称为锁定)时,HealthKit 不可查询。 当手机解锁并且我的应用在 ios 12 的后台时,我可以查询 HealthKit 商店。 @JoshuaC.Lerner 你需要知道这个答案是在 2014 年写的。HealthKit 可能会有一些变化。【参考方案2】:

我能够通过观察 HealthKit 的体重和血糖变化来使用它。

ApplicationDelegate中:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
    // Override point for customization after application launch.        

    GlobalHealthManager.startObservingWeightChanges()

    return true

HealthManager.swift

    let past = NSDate.distantPast() as NSDate
    let now   = NSDate()
    return HKQuery.predicateForSamplesWithStartDate(past, endDate:now, options: .None)

    ()

    //here is my query:
    lazy var query: HKObserverQuery = [weak self] in
    let strongSelf = self!
    return HKObserverQuery(sampleType: strongSelf.weightQuantityType,
        //predicate: strongSelf.longRunningPredicate,
        predicate : nil, //all samples delivered
        updateHandler: strongSelf.weightChangedHandler)
    ()




func startObservingWeightChanges()
        healthKitStore?.executeQuery(query)
        healthKitStore?.enableBackgroundDeliveryForType(weightQuantityType,
            frequency: .Immediate,
            withCompletion: (succeeded: Bool, error: NSError!) in

            if succeeded
                println("Enabled background delivery of weight changes")
             else 
                if let theError = error
                    print("Failed to enable background delivery of weight changes. ")
                    println("Error = \(theError)")
                
            

    )




/** this should get called in the background */
func weightChangedHandler(query: HKObserverQuery!,
    completionHandler: HKObserverQueryCompletionHandler!,
    error: NSError!)

        NSLog(" Got an update Here ")

     /** this function will get called each time a new weight sample is added to healthKit.  

    //Here, I need to actually query for the changed values.. 
   //using the standard query functions in HealthKit.. 

         //Tell IOS we're done... updated my server, etc. 
         completionHandler()         




【讨论】:

我应该注意,即使应用程序未运行,只要您拥有正确的权限,它也可以工作。 感谢您的回答。您是否能够实际查询 HealthStore 的数据?因为根据文档,当屏幕锁定时,HealthStore 受到保护。锁定我的意思是用密码锁定。无论如何,如果它正在工作,那就太好了,但我需要它作为步骤数据类型.. 是的,我可以使用 HK 查询 API 查询数据。我对密码问题感到困惑..如果屏幕被锁定并且您的应用程序(或正在写入此数据的任何应用程序)能够将步骤写入 HK 数据库,那么我认为后台观察者会起作用。 问题是我不是在写数据,我是在读数据。但是我在 Apple 使用了一张支持票,得到的答案是,当屏幕锁定(使用密码)时,所有 HealthStore 数据都受到保护,如果应用程序在后台被位置服务等其他服务唤醒,则可以从 healthStore 观察者获取更新或在后台获取。但是观察者只报告观察变化而不是任何实际数据,我仍然无法读取任何数据,因为它受到保护。 @Thomas,您可以添加您的 Apple 支持票以供参考吗?【参考方案3】:

步骤的最低更新频率为 1 小时,这意味着您的应用每小时只会被唤醒一次。打开应用程序后,您的观察者查询会立即触发。请参阅 enableBackgroundDeliveryForType 讨论中的注释。

https://developer.apple.com/library/prerelease/ios/documentation/HealthKit/Reference/HKHealthStore_Class/index.html#//apple_ref/occ/instm/HKHealthStore/enableBackgroundDeliveryForType:frequency:withCompletion:

【讨论】:

我读起来有点不同,我理解最低更新频率,因为我应该至少每小时获得一次,如果我愿意,我可以立即获得,但我无法设置最低超过每小时一次的任何事情,例如每天一次是不允许的。我已经对此进行了测试,当将频率设置为该频率时,我会立即获得步骤。 嗯,你的实验证明了这一点吗?您的应用是立即唤醒还是每小时唤醒一次? 观察者会立即收到通知,但前提是应用程序被其他服务唤醒,例如位置服务或后台获取。 尝试禁用会唤醒您的应用的所有其他功能,添加步数读数,然后等待一个小时以查看该小时后这些步数是否会唤醒您的应用。应该工作!【参考方案4】:

对于 HKObserverQuery,您必须启用应用程序的任何后台模式才能在后台收到 ObserverQuery 的通知(应用程序未终止)。

【讨论】:

以上是关于屏幕锁定时的 HealthStore enableBackgroundDelivery的主要内容,如果未能解决你的问题,请参考以下文章

屏幕锁定时的 navigator.geolocation.getCurrentPosition()

在 Redmi 设备上启用“在锁定屏幕上显示”权限

在主故事板顶部呈现锁定屏幕

屏幕关闭时的 iBeacon 事件

屏幕关闭时的 Android TYPE_STEP_DETECTOR

healthStore.requestAuthorization() 使 Apple Watch 应用程序崩溃