代码之家  ›  专栏  ›  技术社区  ›  Renish Dadhaniya

如何从iOS中的健康工具包近实时获取心率数据?

  •  5
  • Renish Dadhaniya  · 技术社区  · 7 年前

    我在Watch中创建了一个会话,并在Health Kit中更新心率数据。现在,我想在iPhone屏幕上显示当前的心率。手表传感器更新健康套件中的心率数据,但iPhone应用程序无法从健康套件中获取实时数据。我已经测试了以下两种情况。我还回忆了这个使用定时器的方法/功能,但它不能获取实时数据。

    注意:当我打开健康应用程序并重新打开应用程序时,它会自动刷新数据。如果我的应用程序一直在前台,那么下面的代码不会刷新健康工具包中的最新数据

    1.尝试使用HKSampleQuery获取实时心率数据

            let calendar = NSCalendar.current
            let components = calendar.dateComponents([.year, .month, .day], from: Date())
            let startDate : NSDate = calendar.date(from: components)! as NSDate
            let endDate : Date = calendar.date(byAdding: Calendar.Component.day, value: 1, to: startDate as Date)!
    
            let predicate = HKQuery.predicateForSamples(withStart: startDate as Date, end: endDate, options:[])
    
            //descriptor
            let sortDescriptors = [NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)]
    
            self.heartRateQuery = HKSampleQuery(sampleType: self.heartRateType, predicate: predicate, limit: 1, sortDescriptors: sortDescriptors, resultsHandler: { (query:HKSampleQuery,  results:[HKSample]?, error:Error?) in
    
                guard error == nil else { print("error in getting data"); return }
    
                self.collectCurrentHeartRateSample(currentSampleTyple: results)
    
            })
    
            self.healthStore.execute(self.heartRateQuery!)
    

    2.尝试使用HKAnchoredObjectQuery获取实时心率数据

        let sampleType : HKSampleType =  HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
        let predicate : NSPredicate =  HKQuery.predicateForSamples(withStart: startDate as Date, end: endDate, options: [])
        let anchor: HKQueryAnchor = HKQueryAnchor(fromValue: 0)
    
        let anchoredQuery = HKAnchoredObjectQuery(type: sampleType, predicate: predicate, anchor: anchor, limit: HKObjectQueryNoLimit) { (query, samples, deletedObjects, anchor, error ) in
    
            self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)
    
        }
    
        anchoredQuery.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in
            self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)
        }
    
        self.healthStore.execute(anchoredQuery)
    

    =============================================

    解析数据

    func collectCurrentHeartRateSample(currentSampleTyple : [HKSample]?, deleted : 
    
        [HKDeletedObject]?){
    
        //    func collectCurrentHeartRateSample(currentSampleTyple : [HKSample]?){
    
                DispatchQueue.main.async {
    
                    self.currentHeartRateSample = currentSampleTyple
    
                    //Get Last Sample of Heart Rate
                    self.currentHeartLastSample = self.currentHeartRateSample?.last
                    print("lastSample : \(String(describing: self.currentHeartLastSample))")
    
                    if self.currentHeartLastSample != nil {
    
                        let result = self.currentHeartLastSample as! HKQuantitySample
    
                        let heartRateBPM = result.quantity.doubleValue(for: HKUnit(from: "count/min"))
                        let heartRateBPMUnit = "count/min"
    
                        let deviceUUID = self.currentHeartLastSample?.uuid
                        let deviceIdentity = result.sourceRevision.source.name
                        let deviceProductName = self.currentHeartLastSample?.device?.name
                        let deviceProductType = result.sourceRevision.productType
                        let deviceOSVersion = result.sourceRevision.version
    
                        let startDate = self.currentHeartLastSample?.startDate
                        let endDate = self.currentHeartLastSample?.endDate
    
                        self.aCollectionView.reloadData()
                    }
    
    
                }
    
            }
    
    1 回复  |  直到 7 年前
        1
  •  3
  •   Myk    7 年前

    我认为最好的方法是使用Watch通讯将心率数据发送到手机应用程序。

    在监视代码中:

    func send(heartRate: Int) {
        guard WCSession.default.isReachable else {
            print("Phone is not reachable")
            return
        }
    
        WCSession.default.sendMessage(["Heart Rate" : heartRate], replyHandler: nil) { error in
            print("Error sending message to phone: \(error.localizedDescription)")
        }
     }
    

    在手机上,您通过以下方式接收数据:

    func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
        if let heartRate = message["Heart Rate"] {
            print("Received heart rate: \(heartRate)")
        } else {
            print("Did not receive heart rate =[")
        }
    }
    

    这应该是实时的。或者还有另一个不太可靠的解决方案(imo),那就是每5秒左右执行一次心率查询,但如果我理解正确的话,你已经尝试过了,但它不起作用。

        2
  •  0
  •   Renish Dadhaniya    7 年前

    下面是我自己关于获取实时心率的分析。

    1. 如果您使用iPhone app访问健康工具包数据,在这种情况下,健康工具包数据库不会频繁更新/刷新。因此,你的应用程序无法通过iPhone应用程序实时获取最新更新的数据。

    2. 使用手表应用程序,你可以通过Health Kit DB访问近实时数据。Watch应用程序能够实时获取最新的健康套件数据。

    3. 你需要将数据从手表传输到iPhone应用程序。这里有一个代码供你参考。您可以根据需要编写代码。你只需要通过 香港查询

    let defaultSession = WCSession.default
    
    let healthStore = HKHealthStore()
    
    var currentHeartRateSample : [HKSample]?
    
    var currentHeartLastSample : HKSample?
    
    var currentHeartRateBPM = Double()
    
    
    //Get Heart Rate from Health Kit
    
    func getCurrentHeartRateData(){
    
        let calendar = Calendar.current
        let components = calendar.dateComponents([.year, .month, .day], from: Date())
        let startDate : Date = calendar.date(from: components)!
        let endDate : Date = calendar.date(byAdding: Calendar.Component.day, value: 1, to: startDate as Date)!
    
        let sampleType : HKSampleType =  HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
        let predicate : NSPredicate =  HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: [])
        let anchor: HKQueryAnchor = HKQueryAnchor(fromValue: 0)
    
        let anchoredQuery = HKAnchoredObjectQuery(type: sampleType, predicate: predicate, anchor: anchor, limit: HKObjectQueryNoLimit) { (query, samples, deletedObjects, anchor, error ) in
    
            if samples != nil {
    
                self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)
    
            }
    
        }
    
        anchoredQuery.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in
            self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)
        }
    
        self.healthStore.execute(anchoredQuery)
    
    }
    
    
    //Retrived necessary parameter from HK Sample
    func collectCurrentHeartRateSample(currentSampleTyple : [HKSample]?, deleted : [HKDeletedObject]?){
    
            self.currentHeartRateSample = currentSampleTyple
    
            //Get Last Sample of Heart Rate
            self.currentHeartLastSample = self.currentHeartRateSample?.last
    
            if self.currentHeartLastSample != nil {
    
                let lastHeartRateSample = self.currentHeartLastSample as! HKQuantitySample
    
                self.currentHeartRateBPM = lastHeartRateSample.quantity.doubleValue(for: HKUnit(from: "count/min"))
                let heartRateStartDate = lastHeartRateSample.startDate
                let heartRateEndDate = lastHeartRateSample.endDate
    
                //Send Heart Rate Data Using Send Messge
    
                DispatchQueue.main.async {
    
                    let message = [
                        "HeartRateBPM" : "\(self.currentHeartRateBPM)",
                        "HeartRateStartDate" : "\(heartRateStartDate)",
                        "HeartRateEndDate" : "\(heartRateEndDate)"
                    ]
    
    //Transfer data from watch to iPhone
                    self.defaultSession.sendMessage(message, replyHandler:nil, errorHandler: { (error) in
                        print("Error in send message : \(error)")
                    })
    
                }
    
            }
    
    
    }
    
    推荐文章