HealthStore enableBackgroundDelivery, когда экран заблокирован

Здравствуйте, я пытаюсь настроить обозреватель хранилища здоровья с включенной фоновой доставкой. Моя проблема в том, что он ничего не доставляет, когда экран заблокирован. Я упростил свой код для этого вопроса, чтобы добраться до сути :) У меня есть HealthKit в моем plist, и я принял количество шагов типа 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];

}

Когда я открываю приложение, оно сразу возвращает наблюдение.


person Thomas    schedule 11.02.2015    source источник
comment
Посмотрите на мой ответ здесь: stackoverflow.com/a/35073904/1677480   -  person damirstuhec    schedule 29.01.2016


Ответы (4)


Когда iPhone заблокирован, вы не можете получить доступ к данным HealthKit каким-либо образом.

Когда iPhone разблокирован, но приложение находится в фоновом режиме, вы можете использовать только HKObserverQuery, который используется, чтобы узнать, добавлены ли новые образцы или нет.

Когда iPhone разблокирован и приложение находится на переднем плане, вы можете использовать все, что связано с HealthKit Framework.

person jeongmin.cha    schedule 14.10.2015
comment
Это должен быть правильный ответ. HealthKit не поддерживает запросы, когда экран устройства выключен и установлен пароль (это называется заблокированным). - person lehn0058; 06.01.2016
comment
Когда телефон разблокирован и мое приложение работает в фоновом режиме на iOS 12, я могу запросить магазин HealthKit. - person Joshua C. Lerner; 27.01.2019
comment
@JoshuaC.Lerner Вы должны знать, что этот ответ был написан в 2014 году. В HealthKit могут быть некоторые изменения. - person jeongmin.cha; 17.03.2019

Я смог заставить это работать, наблюдая за изменениями веса и уровня глюкозы в крови в 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()         
}


}
person cmollis    schedule 02.03.2015
comment
Я должен отметить, что это работает, даже когда приложение не запущено, если у вас есть правильные разрешения. - person cmollis; 02.03.2015
comment
Спасибо за ответ. Можете ли вы запросить данные в HealthStore? Потому что, согласно документам, HealthStore защищен, когда экран заблокирован. Под заблокированным я имею в виду заблокированный паролем. В любом случае хорошо, если он работает, но мне это нужно для типа данных шага. - person Thomas; 03.03.2015
comment
Да, я могу запрашивать данные с помощью API запросов HK. Я запутался в проблеме с паролем ... если экран заблокирован, и ваше приложение (или любое другое приложение, записывающее эти данные) может записать шаги в базу данных HK, тогда я думаю, что фоновые наблюдатели будут работать. - person cmollis; 04.03.2015
comment
Проблема в том, что я не пишу данные, я читаю данные. Но я воспользовался билетом поддержки в Apple и получил ответ, что все данные HealthStore защищены, когда экран заблокирован (с кодом доступа), можно получать обновления от наблюдателя HealthStore, если приложение пробуждается в фоновом режиме другими службами, такими как служба определения местоположения или получить в фоновом режиме. Но наблюдатель сообщает только об изменении наблюдения, а не о каких-либо фактических данных, я все еще не могу прочитать какие-либо данные, потому что они защищены. - person Thomas; 09.03.2015
comment
@Thomas, вы можете добавить свой билет в службу поддержки Apple для справки? - person Bhanu Prakash; 19.03.2015
comment
@cmollis в вашем ответе отсутствует объявление функции в HealthManager.swift - person Hugo Alonso; 28.05.2015
comment
Будет ли ваше приложение вызываться, даже если пользователь явно убил приложение? - person Pratik Stephen; 22.11.2015
comment
@Victor Sigler Не могли бы вы поделиться образцом Objective C для этого? - person yaali; 10.07.2018
comment
@cmollis, можете ли вы обновить весь файл HealthManager.swift. В какой-то момент я не могу интегрировать - person Apple; 30.10.2018

Шаги имеют минимальную частоту обновления 1 час, что означает, что ваше приложение будет пробуждаться только один раз в час. Как только вы открываете приложение, ваши запросы наблюдателя сразу же запускаются. См. примечание в обсуждении для enableBackgroundDeliveryForType.

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

person drdaanger    schedule 06.03.2015
comment
Я прочитал это немного по-другому, я понимаю минимальную частоту обновления, так как я должен получать его как минимум один раз в час, я могу получить его немедленно, если захочу, но я не могу установить минимум на что-либо более одного раза в час, например раз в сутки нельзя. Я проверил это, и я сразу получаю шаги, когда устанавливаю частоту на это. - person Thomas; 09.03.2015
comment
Что ж, ваши эксперименты подтверждают это? Ваше приложение просыпается сразу или раз в час? - person drdaanger; 10.03.2015
comment
Наблюдатель получает уведомление немедленно, но только в том случае, если приложение пробуждается другими службами, такими как служба определения местоположения или фоновая выборка. - person Thomas; 11.03.2015
comment
Попробуйте отключить все остальное, что может разбудить ваше приложение, добавить чтение шагов, а затем подождать час, чтобы увидеть, разбудят ли шаги ваше приложение после этого часа. Должно сработать! - person drdaanger; 12.03.2015

В случае HKObserverQuery вы должны включить любой из фоновых режимов приложения, чтобы получать уведомления о ObserverQuery в фоновом режиме (приложение не убито).

введите здесь описание изображения

person Bhanu Prakash    schedule 19.03.2015