美文网首页
iOS接入HealthKit,获取健康应用步数

iOS接入HealthKit,获取健康应用步数

作者: 欲码还修 | 来源:发表于2018-09-05 11:31 被阅读390次

    Overview

    话不多说,先看看官网对HealthKit的解释:

    屏幕快照 2018-09-04 15.45.11.png
    稍稍翻译一下,创建完成,HealthKit可以完成一下任务:
    收集和存储健康和健身数据
    分析和可视化数据
    实现社交互动

    HealthKit中有很多数据,但是没必要全部获取,只需要拿到当前需要的就行。🤦‍♀️

    1.启用HealthKit

    79f2fd7e-6a9c-4c18-8c70-73ff9b9f992a.png
    开启HealthKit之后,在info.plist中增加 Privacy - Health Share Usage DescriptionPrivacy - Health Update Usage Description,内容可以随便填写。

    2.确保HealthKit可用

    import HealthKit
    //检测当前HealthKit是否可以使用
    if HKHealthStore.isHealthDataAvailable() {
        print("HealthKit可以使用")
    }
    

    3.创建HKHealthStore

    let healthStore = HKHealthStore()
    

    4.请求读取和共享数据的权限

    //读取权限
    let typestoRead = Set([HKObjectType.workoutType(), //步行+跑步距离
                     HKObjectType.quantityType(forIdentifier: .stepCount)!, //步数
                     HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,  //活动能量
                     HKObjectType.quantityType(forIdentifier: .distanceCycling)!,  //  骑车距离
                     HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!,  // 体能训练
                     HKObjectType.quantityType(forIdentifier: .heartRate)!])  //心率
    //写入权限
    let typestoShare = Set([
                    HKObjectType.quantityType(forIdentifier: .stepCount)!,
                    HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
                    HKObjectType.quantityType(forIdentifier: .distanceCycling)!,  //活动能量
                    HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!,
                    HKObjectType.quantityType(forIdentifier: .heartRate)!])
    healthStore.requestAuthorization(toShare: typestoShare, read: typestoRead, completion: { [weak self] (success, error) in
            if !success {
                 NSLog("Display not allowed")
            }else {
                 self?.readStep()
            }
    })
    

    5.读取数据

    func readStep() {
            HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)
            //NSSortDescriptors用来告诉healthStore怎么样将结果排序
            let start = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
            let stop  = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
            let now = Date()
            guard let sampleType = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount) else {
                fatalError("*** This method should never fail ***")
            }
            
            let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
            var dataCom = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: now)
            let endDate = calendar.date(from: dataCom)    //设置查询的截止时间(当前)
            dataCom.hour = 0
            dataCom.minute = 0
            dataCom.second = 0
            let startDate = calendar.date(from: dataCom)    //设置查询的起始时间(当天0点)
            let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: HKQueryOptions.strictStartDate)
            
            var localSum: Double = 0  //手机写入步数
            var currentDeviceSum: Double = 0  //软件写入步数
            let query = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: Int(HKObjectQueryNoLimit), sortDescriptors: [start, stop]) { (query, results, error) in
                
                guard (results as? [HKQuantitySample]) != nil else {
    //                fatalError("An error occured fetching the user's tracked food. In your app, try to handle this error gracefully. The error was: \(String(describing: error?.localizedDescription))");
                    print("获取步数error ---> \(String(describing: error?.localizedDescription))")
                    return
                }
                for res in results! {
                    // res.sourceRevision.source.bundleIdentifier  当前数据来源的BundleId
                    // Bundle.main.bundleIdentifier  当前软件的BundleId
                    if res.sourceRevision.source.bundleIdentifier == Bundle.main.bundleIdentifier {
                        print("app写入数据")
                        let _res = res as? HKQuantitySample
                        currentDeviceSum = currentDeviceSum + (_res?.quantity.doubleValue(for: HKUnit.count()))!
                    }else {     //手机录入数据
                        let _res = res as? HKQuantitySample
                        localSum = localSum + (_res?.quantity.doubleValue(for: HKUnit.count()))!
                    }
                }
                print("当前步数  -- \(currentDeviceSum)")
                print("当前步数  -- \(localSum)")
    //            DispatchQueue.main.async { [weak self] in
    //
    //            }
            }
            healthStore.execute(query)   //开始查询
        }
    

    6.存入数据

    healthStore.requestAuthorization(toShare: typestoShare, read: typestoRead, completion: { [weak self] (success, error) in
                    if !success {
                        NSLog("Display not allowed")
                    }else {
                        
                        //写入的时间点
                        let now = Date()
                        let startDate = Date(timeInterval: -10, since: now)
                        let countUnit = HKUnit.count()
                        // 写入的步数
                        let countUnitQuantity = HKQuantity.init(unit: countUnit, doubleValue: 1000)
                        let countUnitType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)
                        let stepCountSample = HKQuantitySample.init(type: countUnitType!, quantity: countUnitQuantity, start: startDate, end: now)
    
                        self?.healthStore.save(stepCountSample) { (isSuccess, error) in
                            if isSuccess {
                                print("保存成功 ----> \(isSuccess)")
                            }else {
                                print("error -----> \(String(describing: error))")
                            }
                        }
                        
                        self?.readStep()
                    }
                })
    

    *所有健康数据类型(HKObjectType)

    HealthKit使用子类来识别HealthKit中存储的不同类型的数据:HKObjectType
    
    * HKCharacteristicType  表示通常不随时间变化的数据(例如,血型)。
    * HKQuantityType 表示包含数值的样本(例如消耗的卡路里)。
    * HKCategoryType 表示包含可能值的短列表中的选项的样本(例如睡眠分析)。
    * HKCorrelationType 表示包含许多数量或类别样本的复杂样本(例如,包含许多营养样本的食物样本)。
    * HKWorkoutType表示锻炼及其相关数据(有关更多信息,请参阅锻炼)。
    
    let bloodType = HKObjectType.characteristicType(forIdentifier: .bloodType)
    let caloriesConsumed = HKObjectType.quantityType(forIdentifier: .dietaryEnergyConsumed)
    let sleepAnalysis = HKObjectType.categoryType(forIdentifier: .sleepAnalysis)
    let food = HKObjectType.correlationType(forIdentifier: .food)
    

    以上是类型,具体可以获取到哪些数据请参考https://developer.apple.com/documentation/healthkit/hkobjecttype

    End

    当使用了HealthKit的项目提交时,需要注意在 iTunes Connection项目描述中加入项目使用了健康应用数据的提示

    demo https://github.com/duke3312/healthKitDemo

    相关文章

      网友评论

          本文标题:iOS接入HealthKit,获取健康应用步数

          本文链接:https://www.haomeiwen.com/subject/daigwftx.html