您好,登錄后才能下訂單哦!
這篇文章介紹兩種可以獲取計(jì)步數(shù)據(jù)的方法,一種是采用CMPedometer獲取手機(jī)計(jì)步器數(shù)據(jù),另一種是采用HealthKit框架從手機(jī)健康A(chǔ)pp中獲取計(jì)步數(shù)據(jù)。另外玩了一下寫(xiě)入數(shù)據(jù)到健康A(chǔ)pp。有描述不當(dāng)之處,望指點(diǎn)。
花絮(用HealthKit框架構(gòu)建app,寫(xiě)入數(shù)據(jù)到蘋(píng)果健康app中,QQ和Keep等第三方app的運(yùn)動(dòng)數(shù)據(jù)都會(huì)隨之改變,猜測(cè)它們的運(yùn)動(dòng)數(shù)據(jù)是直接從蘋(píng)果健康app中獲取,而且沒(méi)有過(guò)濾掉其它數(shù)據(jù)來(lái)源。而微信運(yùn)動(dòng)的數(shù)據(jù)不會(huì)變,猜測(cè)其來(lái)源可能是使用CMPedometer類(lèi)獲取的,因?yàn)闇y(cè)試發(fā)現(xiàn)把微信運(yùn)動(dòng)的數(shù)據(jù)來(lái)源(蘋(píng)果健康)關(guān)閉后,依然會(huì)有運(yùn)動(dòng)數(shù)據(jù),而且該運(yùn)動(dòng)數(shù)據(jù)和CMPedometer類(lèi)獲取的一致。)
使用CMPedometer類(lèi)來(lái)獲取步數(shù)和距離
使用時(shí)需要導(dǎo)入<CoreMotion/CoreMotion.h>,此類(lèi)在iOS8之后才可用,在iOS8之前,使用CMStepCounter類(lèi)(在iOS8之后被CMPedometer替代)來(lái)獲取步數(shù),使用方法如CMPedometer類(lèi)相似。
CMPedometer
+ (BOOL)isStepCountingAvailable; 設(shè)備是否支持計(jì)步功能
+ (BOOL)isDistanceAvailable; 除了計(jì)步,設(shè)備是否支持距離估計(jì)
+ (BOOL)isFloorCountingAvailable; 除了計(jì)步,設(shè)備是否支持臺(tái)階計(jì)數(shù)
+ (BOOL)isPaceAvailable NS_AVAILABLE(NA,9_0);除了計(jì)步,設(shè)備是否支持速度估計(jì)
+(BOOL)isCadenceAvailable NS_AVAILABLE(NA,9_0);除了計(jì)步,設(shè)備是否支持節(jié)奏估計(jì)
+ (BOOL)isPedometerEventTrackingAvailable NS_AVAILABLE(NA,10_0) __WATCHOS_AVAILABLE(3_0);設(shè)備是否支持計(jì)步器事件
- (void)queryPedometerDataFromDate:(NSDate *)start toDate:(NSDate *)end withHandler:(CMPedometerHandler)handler;在給定時(shí)間范圍內(nèi)查詢用戶的行走活動(dòng),數(shù)據(jù)最多可以使用7天內(nèi)有效,返回的數(shù)據(jù)是從系統(tǒng)范圍的歷史記錄中計(jì)算出來(lái)的,該歷史記錄是在后臺(tái)連續(xù)收集的。結(jié)果返回在串行隊(duì)列中。
- (void)startPedometerUpdatesFromDate:(NSDate *)start withHandler:(CMPedometerHandler)handler;在串行隊(duì)列上啟動(dòng)一系列連續(xù)計(jì)步器更新到處理程序。 對(duì)于每次更新,應(yīng)用程序?qū)闹付ǖ拈_(kāi)始日期和與最新確定相關(guān)聯(lián)的時(shí)間戳開(kāi)始收到累積的行人活動(dòng)。 如果應(yīng)用程序在后臺(tái)進(jìn)行背景調(diào)整,則應(yīng)用程序?qū)⒃谙麓胃轮惺盏皆诤笈_(tái)期間累積的所有行人活動(dòng)。
-(void)stopPedometerUpdates;停止計(jì)步器更新
-(void)startPedometerEventUpdatesWithHandler:(CMPedometerEventHandler)handler NS_AVAILABLE(NA,10_0) __WATCHOS_AVAILABLE(3_0);在串行隊(duì)列上啟動(dòng)計(jì)步器事件更新。 事件僅在應(yīng)用程序在前臺(tái)/后臺(tái)運(yùn)行時(shí)可用。
-(void)stopPedometerEventUpdates NS_AVAILABLE(NA,10_0) __WATCHOS_AVAILABLE(3_0);停止計(jì)步器事件更新
CMPedometerData
@property(readonly, nonatomic) NSDate *startDate;計(jì)步器數(shù)據(jù)有效期間的開(kāi)始時(shí)間。這是會(huì)話或歷史查詢請(qǐng)求的開(kāi)始時(shí)間。
@property(readonly, nonatomic) NSDate *endDate;計(jì)步器數(shù)據(jù)有效期間的結(jié)束時(shí)間。對(duì)于更新,這是最新更新的時(shí)間。 對(duì)于歷史查詢,這是請(qǐng)求的結(jié)束時(shí)間。
@property(readonly, nonatomic) NSNumber *numberOfSteps;用戶的步數(shù)
@property(readonly, nonatomic, nullable) NSNumber *distance; 用戶行走和跑步時(shí)估計(jì)的一米為單位的距離。若設(shè)備不支持則值為nil
@property(readonly, nonatomic, nullable) NSNumber *floorsAscended;上樓的大概樓層數(shù),若設(shè)備不支持則值為nil
@property(readonly, nonatomic, nullable) NSNumber *floorsDescended;下樓的大概樓層數(shù), 若設(shè)備不支持則值為nil
@property(readonly, nonatomic, nullable) NSNumber *currentPace NS_AVAILABLE(NA,9_0);對(duì)于更新,這將以s / m(每米秒)返回當(dāng)前速度。 如果滿足以下條件,則值為零:1. 資料尚未公布 2. 歷史查詢 3.平臺(tái)不支持
@property(readonly, nonatomic, nullable) NSNumber *currentCadence NS_AVAILABLE(NA,9_0);對(duì)于更新,這將返回以秒為單位執(zhí)行行走的節(jié)奏。 如果滿足以下條件,則值為零:1. 資料尚未公布 2. 歷史查詢 3.平臺(tái)不支持
@property(readonly, nonatomic, nullable) NSNumber *averageActivePace NS_AVAILABLE(NA,10_0);對(duì)于更新,這將返回自startPedometerUpdatesFromDate:withHandler :,以s / m(每米秒))的平均活動(dòng)速度。 對(duì)于歷史查詢,這將返回startDate和endDate之間的平均活動(dòng)速度。 平均主動(dòng)速度省略了非活動(dòng)時(shí)間,平均步調(diào)從用戶移動(dòng)。 如果滿足以下條件,則值為零:1. 對(duì)于歷史信息查詢,信息無(wú)效。例如用戶在開(kāi)始時(shí)間和結(jié)束時(shí)間內(nèi)沒(méi)有移動(dòng) 2. 平臺(tái)不支持
CMPedometerEvent
@property(readonly, nonatomic) NSDate *date;事件發(fā)生的時(shí)間
@property(readonly, nonatomic) CMPedometerEventType type;描述行走活動(dòng)過(guò)渡的事件類(lèi)型
typedef void (^CMPedometerHandler)(CMPedometerData * __nullable pedometerData, NSError * __nullable error) __TVOS_PROHIBITED;當(dāng)計(jì)步器數(shù)據(jù)可用時(shí)要調(diào)用的block的類(lèi)型
typedef void (^CMPedometerEventHandler)(CMPedometerEvent * __nullable pedometerEvent, NSError * __nullable error) NS_AVAILABLE(NA, 10_0) __WATCHOS_AVAILABLE(3_0) __TVOS_PROHIBITED;//當(dāng)計(jì)步器事件可用時(shí)將被調(diào)用的block的類(lèi)型。
獲取步數(shù)和距離的方法
1、使用<CoreMotion/CoreMotion.h>庫(kù)需要在info.plist文件中增加NSMotionUsageDescription鍵。
2、可以使用isStepCountingAvailable或者isDistanceAvailable來(lái)檢查設(shè)備是否支持計(jì)步功能或距離功能。
3、創(chuàng)建CMPedometer實(shí)例對(duì)象
/// 創(chuàng)建計(jì)步器對(duì)象 if ([CMPedometer isStepCountingAvailable]) { // 8.0 之后可使用 self.pedometer = [[CMPedometer alloc] init]; }
4、調(diào)用- (void)startPedometerUpdatesFromDate:(NSDate *)start withHandler:(CMPedometerHandler)handler方法獲取從某個(gè)時(shí)間點(diǎn)到現(xiàn)在的步數(shù),距離,樓層等信息。此方法會(huì)實(shí)時(shí)更新數(shù)據(jù)。
[self.pedometer startPedometerUpdatesFromDate:fromDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) { // 如果沒(méi)有錯(cuò)誤,具體信息從pedometerData參數(shù)中獲取 }];
5、不需要使用的時(shí)候,調(diào)用stopPedometerUpdates方法停止更新
[self.pedometer stopPedometerUpdates];
6、如果不需要實(shí)時(shí)更新數(shù)據(jù),可直接調(diào)用- (void)queryPedometerDataFromDate:(NSDate *)start toDate:(NSDate *)end withHandler:(CMPedometerHandler)handler;查詢某個(gè)時(shí)間段內(nèi)的數(shù)據(jù),不過(guò)只能查詢七天內(nèi)的數(shù)據(jù)。
[self.pedometer queryPedometerDataFromDate:start toDate:end withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) { // 如果沒(méi)有錯(cuò)誤,具體信息從pedometerData參數(shù)中獲取 }];
使用HealthKit框架獲取蘋(píng)果健康數(shù)據(jù)
在HealthKit中,使用HKHealthStore類(lèi)來(lái)訪問(wèn)健康數(shù)據(jù),健康數(shù)據(jù)的類(lèi)型有很多類(lèi),蘋(píng)果健康app中的健身記錄、營(yíng)養(yǎng)攝入、睡眠狀況等等都可以進(jìn)行數(shù)據(jù)讀取和共享(即第三方app寫(xiě)入數(shù)據(jù)到蘋(píng)果健康app)。
大概步驟:
1、在Xcode中, 打開(kāi)HealthKit 功能
開(kāi)啟HealthKit功能
1、調(diào)用isHealthDataAvailable方法檢查設(shè)備HealthKit是否可用。
if ([HKHealthStore isHealthDataAvailable]) { // add code to use HealthKit here... }
2、如果可用,創(chuàng)建HKHealthStore對(duì)象
self.healthStore = [[HKHealthStore alloc] init];
3、向用戶請(qǐng)求授權(quán)共享或讀取健康數(shù)據(jù), 調(diào)用- (void)requestAuthorizationToShareTypes:(nullable NSSet<HKSampleType *> *)typesToShare readTypes:(nullable NSSet<HKObjectType *> *)typesToRead completion:(void (^)(BOOL success, NSError * _Nullable error))completion;方法,例如下面請(qǐng)求讀取步數(shù)和距離數(shù)據(jù)
NSSet<HKSampleType *> *shareTypes = nil; HKQuantityType *stepType = [HKQuantityType quantityTypeForIdentifier:(HKQuantityTypeIdentifierStepCount)]; HKQuantityType *distanceType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; NSSet<HKObjectType *> *readTypes = [NSSet setWithObjects:stepType, distanceType, nil]; [self.healthStore requestAuthorizationToShareTypes:shareTypes readTypes:readTypes completion:^(BOOL success, NSError * _Nullable error) { }];
4、在info.plist文件中,增加NSHealthShareUsageDescription用于讀取數(shù)據(jù)的描述和NSHealthUpdateUsageDescription用于寫(xiě)入數(shù)據(jù)的描述
5、用戶授權(quán)之后,就可以對(duì)健康數(shù)據(jù)中授權(quán)的項(xiàng)目進(jìn)行讀取或?qū)懭氩僮?。下面的代碼是查詢一段歷史的計(jì)步記錄的示例,如CMPedemoter不同的是查詢到的數(shù)據(jù)不是實(shí)時(shí)更新的。
// 查詢數(shù)據(jù)的類(lèi)型,比如計(jì)步,行走+跑步距離等等 HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:(HKQuantityTypeIdentifierStepCount)]; // 謂詞,用于限制查詢返回結(jié)果 NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:start endDate:end options:(HKQueryOptionNone)]; NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *anchorComponents = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:[NSDate date]]; // 用于錨集合的時(shí)間間隔 NSDate *anchorDate = [calendar dateFromComponents:anchorComponents]; // 采樣時(shí)間間隔 NSDateComponents *intervalComponents = [[NSDateComponents alloc] init]; intervalComponents.day = 1; // 創(chuàng)建統(tǒng)計(jì)查詢對(duì)象 HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType quantitySamplePredicate:predicate options:(HKStatisticsOptionCumulativeSum|HKStatisticsOptionSeparateBySource) anchorDate:anchorDate intervalComponents:intervalComponents]; query.initialResultsHandler = ^(HKStatisticsCollectionQuery * _Nonnull query, HKStatisticsCollection * _Nullable result, NSError * _Nullable error) { NSMutableArray *resultArr = [NSMutableArray array]; if (error) { NSLog(@"error: %@", error); } else { for (HKStatistics *statistics in [result statistics]) { NSLog(@"statics: %@,\n sources: %@", statistics, statistics.sources); for (HKSource *source in statistics.sources) { // 過(guò)濾掉其它應(yīng)用寫(xiě)入的健康數(shù)據(jù) if ([source.name isEqualToString:[UIDevice currentDevice].name]) { // 獲取到步數(shù) double step = round([[statistics sumQuantityForSource:source] doubleValueForUnit:[HKUnit countUnit]]); } } } } // 執(zhí)行查詢請(qǐng)求 [self.healthStore executeQuery:query];
如果要寫(xiě)入數(shù)據(jù)到蘋(píng)果HealtkKit中,過(guò)程類(lèi)似,下面的示例是寫(xiě)入步數(shù)到健康數(shù)據(jù)。(QQ中運(yùn)動(dòng)的步數(shù)和Keep中的步數(shù)都是從健康數(shù)據(jù)中獲取的步數(shù),而且沒(méi)有過(guò)濾其它應(yīng)用寫(xiě)入的數(shù)據(jù),所以想要修改QQ或Keep中的步數(shù),可以用自己的app寫(xiě)入步數(shù)數(shù)據(jù),親測(cè)有效)
①請(qǐng)求用戶授權(quán)
HKQuantityType *stepType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; NSSet *shareTypes = [NSSet setWithObjects:stepType, nil]; [self.healthStore requestAuthorizationToShareTypes:shareTypes readTypes:nil completion:^(BOOL success, NSError * _Nullable error) { }];
②寫(xiě)入數(shù)據(jù)
double step = [self.textField.text doubleValue]; HKQuantityType *stepType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; HKQuantity *stepQuantity = [HKQuantity quantityWithUnit:[HKUnit countUnit] doubleValue:step]; HKQuantitySample *stepSample = [HKQuantitySample quantitySampleWithType:stepType quantity:stepQuantity startDate:[self getTodayStartDate] endDate:[NSDate date]]; [self.healthStore saveObject:stepSample withCompletion:^(BOOL success, NSError * _Nullable error) { if (error) { NSLog(@"error: %@", error.localizedDescription); } dispatch_async(dispatch_get_main_queue(), ^{ self.stateLabel.text = success ? @"成功" : @"失敗"; }); }];
項(xiàng)目中使用了HealthKit時(shí),上架需要注意點(diǎn):
You must also provide a privacy policy for any app that uses the HealthKit framework. You can find guidance on creating a privacy policy at the following sites://你必須為每個(gè)使用HealthKit框架的應(yīng)用提供一份隱私策略。你可以在以下網(wǎng)站找到創(chuàng)建隱私策略的指導(dǎo):
1、Personal Health Record model (for non-HIPAA apps): http://www.healthit.gov/policy-researchers-implementers/personal-health-record-phr-model-privacy-notice
2、HIPAA model (for HIPAA covered apps): http://www.hhs.gov/ocr/privacy/hipaa/modelnotices.html
參考文章
https://developer.apple.com/documentation/healthkit#classes
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。