溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

詳解iOS 計(jì)步器的幾種實(shí)現(xiàn)方式

發(fā)布時(shí)間:2020-09-14 09:22:47 來(lái)源:腳本之家 閱讀:503 作者:丨n水瓶座菜蟲(chóng)灬 欄目:移動(dòng)開(kāi)發(fā)

這篇文章介紹兩種可以獲取計(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)獲取的一致。)

詳解iOS 計(jì)步器的幾種實(shí)現(xiàn)方式

使用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 功能

詳解iOS 計(jì)步器的幾種實(shí)現(xiàn)方式

開(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):

  • Your app may not use information gained through the use of the HealthKit framework for advertising or similar services. Note that you may still serve advertising in an app that uses the HealthKit framework, but you cannot use data from the HealthKit store to serve ads.//你的應(yīng)用不應(yīng)該將HealthKit收集的數(shù)據(jù)用于廣告或類(lèi)似的服務(wù)。注意,可能在使用HealthKit框架應(yīng)用中還是要服務(wù)廣告,但是你不能使用HealthKit中的數(shù)據(jù)來(lái)服務(wù)廣告。
  • You must not disclose any information gained through HealthKit to a third party without express permission from the user. Even with permission, you can only share information to a third party if they are also providing a health or fitness service to the user.// 在沒(méi)有用戶的明確允許下,你不能向第三方展示任何HealthKit收集的數(shù)據(jù)。即使用戶允許,你也只能向提供健康或健身服務(wù)的第三方展示這些數(shù)據(jù)
  • You cannot sell information gained through HealthKit to advertising platforms, data brokers, or information resellers.// 你不能將HealthKit收集的數(shù)據(jù)出售給廣告平臺(tái)、數(shù)據(jù)代理人或者信息經(jīng)銷(xiāo)商
  • If the user consents, you may share his or her HealthKit data with a third party for medical research.// 如果用戶允許,你可以將HealthKit數(shù)據(jù)共享給第三方用于醫(yī)學(xué)研究。
  • You must clearly disclose to the user how you and your app will use their HealthKit data.//你必須明確說(shuō)明,你和你的應(yīng)用會(huì)怎樣使用用戶的HealthKit數(shù)據(jù)。

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í)有所幫助,也希望大家多多支持億速云。

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI