全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

详解iOS 计步器的几种实现方式

这篇文章介绍两种可以获取计步数据的方法,一种是采用CMPedometer获取手机计步器数据,另一种是采用HealthKit框架从手机健康App中获取计步数据。另外玩了一下写入数据到健康App。有描述不当之处,望指点。

花絮(用HealthKit框架构建app,写入数据到苹果健康app中,QQ和Keep等第三方app的运动数据都会随之改变,猜测它们的运动数据是直接从苹果健康app中获取,而且没有过滤掉其它数据来源。而微信运动的数据不会变,猜测其来源可能是使用CMPedometer类获取的,因为测试发现把微信运动的数据来源(苹果健康)关闭后,依然会有运动数据,而且该运动数据和CMPedometer类获取的一致。)

使用CMPedometer类来获取步数和距离

使用时需要导入<CoreMotion/CoreMotion.h>,此类在iOS8之后才可用,在iOS8之前,使用CMStepCounter类(在iOS8之后被CMPedometer替代)来获取步数,使用方法如CMPedometer类相似。

CMPedometer

+ (BOOL)isStepCountingAvailable; 设备是否支持计步功能

+ (BOOL)isDistanceAvailable; 除了计步,设备是否支持距离估计

+ (BOOL)isFloorCountingAvailable; 除了计步,设备是否支持台阶计数

+ (BOOL)isPaceAvailable NS_AVAILABLE(NA,9_0);除了计步,设备是否支持速度估计

+(BOOL)isCadenceAvailable NS_AVAILABLE(NA,9_0);除了计步,设备是否支持节奏估计

+ (BOOL)isPedometerEventTrackingAvailable NS_AVAILABLE(NA,10_0) __WATCHOS_AVAILABLE(3_0);设备是否支持计步器事件

- (void)queryPedometerDataFromDate:(NSDate *)start toDate:(NSDate *)end withHandler:(CMPedometerHandler)handler;在给定时间范围内查询用户的行走活动,数据最多可以使用7天内有效,返回的数据是从系统范围的历史记录中计算出来的,该历史记录是在后台连续收集的。结果返回在串行队列中。

- (void)startPedometerUpdatesFromDate:(NSDate *)start withHandler:(CMPedometerHandler)handler;在串行队列上启动一系列连续计步器更新到处理程序。 对于每次更新,应用程序将从指定的开始日期和与最新确定相关联的时间戳开始收到累积的行人活动。 如果应用程序在后台进行背景调整,则应用程序将在下次更新中收到在后台期间累积的所有行人活动。

-(void)stopPedometerUpdates;停止计步器更新

-(void)startPedometerEventUpdatesWithHandler:(CMPedometerEventHandler)handler NS_AVAILABLE(NA,10_0) __WATCHOS_AVAILABLE(3_0);在串行队列上启动计步器事件更新。 事件仅在应用程序在前台/后台运行时可用。

-(void)stopPedometerEventUpdates NS_AVAILABLE(NA,10_0) __WATCHOS_AVAILABLE(3_0);停止计步器事件更新

CMPedometerData

@property(readonly, nonatomic) NSDate *startDate;计步器数据有效期间的开始时间。这是会话或历史查询请求的开始时间。

@property(readonly, nonatomic) NSDate *endDate;计步器数据有效期间的结束时间。对于更新,这是最新更新的时间。 对于历史查询,这是请求的结束时间。

@property(readonly, nonatomic) NSNumber *numberOfSteps;用户的步数

@property(readonly, nonatomic, nullable) NSNumber *distance; 用户行走和跑步时估计的一米为单位的距离。若设备不支持则值为nil

@property(readonly, nonatomic, nullable) NSNumber *floorsAscended;上楼的大概楼层数,若设备不支持则值为nil

@property(readonly, nonatomic, nullable) NSNumber *floorsDescended;下楼的大概楼层数, 若设备不支持则值为nil

@property(readonly, nonatomic, nullable) NSNumber *currentPace NS_AVAILABLE(NA,9_0);对于更新,这将以s / m(每米秒)返回当前速度。 如果满足以下条件,则值为零:1. 资料尚未公布 2. 历史查询 3.平台不支持

@property(readonly, nonatomic, nullable) NSNumber *currentCadence NS_AVAILABLE(NA,9_0);对于更新,这将返回以秒为单位执行行走的节奏。 如果满足以下条件,则值为零:1. 资料尚未公布 2. 历史查询 3.平台不支持

@property(readonly, nonatomic, nullable) NSNumber *averageActivePace NS_AVAILABLE(NA,10_0);对于更新,这将返回自startPedometerUpdatesFromDate:withHandler :,以s / m(每米秒))的平均活动速度。 对于历史查询,这将返回startDate和endDate之间的平均活动速度。 平均主动速度省略了非活动时间,平均步调从用户移动。 如果满足以下条件,则值为零:1. 对于历史信息查询,信息无效。例如用户在开始时间和结束时间内没有移动 2. 平台不支持

CMPedometerEvent

@property(readonly, nonatomic) NSDate *date;事件发生的时间

@property(readonly, nonatomic) CMPedometerEventType type;描述行走活动过渡的事件类型

typedef void (^CMPedometerHandler)(CMPedometerData * __nullable pedometerData, NSError * __nullable error) __TVOS_PROHIBITED;当计步器数据可用时要调用的block的类型

typedef void (^CMPedometerEventHandler)(CMPedometerEvent * __nullable pedometerEvent, NSError * __nullable error) NS_AVAILABLE(NA, 10_0) __WATCHOS_AVAILABLE(3_0) __TVOS_PROHIBITED;//当计步器事件可用时将被调用的block的类型。

获取步数和距离的方法

1、使用<CoreMotion/CoreMotion.h>库需要在info.plist文件中增加NSMotionUsageDescription键。

2、可以使用isStepCountingAvailable或者isDistanceAvailable来检查设备是否支持计步功能或距离功能。

3、创建CMPedometer实例对象

 /// 创建计步器对象
 if ([CMPedometer isStepCountingAvailable]) { // 8.0 之后可使用
   self.pedometer = [[CMPedometer alloc] init];
 }

4、调用- (void)startPedometerUpdatesFromDate:(NSDate *)start withHandler:(CMPedometerHandler)handler方法获取从某个时间点到现在的步数,距离,楼层等信息。此方法会实时更新数据。

 [self.pedometer startPedometerUpdatesFromDate:fromDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) {
  // 如果没有错误,具体信息从pedometerData参数中获取
 }];

5、不需要使用的时候,调用stopPedometerUpdates方法停止更新

 [self.pedometer stopPedometerUpdates];

6、如果不需要实时更新数据,可直接调用- (void)queryPedometerDataFromDate:(NSDate *)start toDate:(NSDate *)end withHandler:(CMPedometerHandler)handler;查询某个时间段内的数据,不过只能查询七天内的数据。

 [self.pedometer queryPedometerDataFromDate:start toDate:end withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) {
  // 如果没有错误,具体信息从pedometerData参数中获取
 }];

使用HealthKit框架获取苹果健康数据

在HealthKit中,使用HKHealthStore类来访问健康数据,健康数据的类型有很多类,苹果健康app中的健身记录、营养摄入、睡眠状况等等都可以进行数据读取和共享(即第三方app写入数据到苹果健康app)。

大概步骤:

1、在Xcode中, 打开HealthKit 功能

开启HealthKit功能

1、调用isHealthDataAvailable方法检查设备HealthKit是否可用。

 if ([HKHealthStore isHealthDataAvailable]) {
 // add code to use HealthKit here...
 }

2、如果可用,创建HKHealthStore对象

 self.healthStore = [[HKHealthStore alloc] init];

3、向用户请求授权共享或读取健康数据, 调用- (void)requestAuthorizationToShareTypes:(nullable NSSet<HKSampleType *> *)typesToShare readTypes:(nullable NSSet<HKObjectType *> *)typesToRead completion:(void (^)(BOOL success, NSError * _Nullable error))completion;方法,例如下面请求读取步数和距离数据

 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用于读取数据的描述和NSHealthUpdateUsageDescription用于写入数据的描述

5、用户授权之后,就可以对健康数据中授权的项目进行读取或写入操作。下面的代码是查询一段历史的计步记录的示例,如CMPedemoter不同的是查询到的数据不是实时更新的。

   // 查询数据的类型,比如计步,行走+跑步距离等等 
   HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:(HKQuantityTypeIdentifierStepCount)];
   // 谓词,用于限制查询返回结果
   NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:start endDate:end options:(HKQueryOptionNone)];

   NSCalendar *calendar = [NSCalendar currentCalendar];
   NSDateComponents *anchorComponents = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:[NSDate date]];
   // 用于锚集合的时间间隔
   NSDate *anchorDate = [calendar dateFromComponents:anchorComponents];

   // 采样时间间隔
   NSDateComponents *intervalComponents = [[NSDateComponents alloc] init];
   intervalComponents.day = 1;
   
   // 创建统计查询对象
   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) {
         // 过滤掉其它应用写入的健康数据
         if ([source.name isEqualToString:[UIDevice currentDevice].name]) {
           // 获取到步数
           double step = round([[statistics sumQuantityForSource:source] doubleValueForUnit:[HKUnit countUnit]]); 
         }
       }
     }
   }
   // 执行查询请求
   [self.healthStore executeQuery:query];

如果要写入数据到苹果HealtkKit中,过程类似,下面的示例是写入步数到健康数据。(QQ中运动的步数和Keep中的步数都是从健康数据中获取的步数,而且没有过滤其它应用写入的数据,所以想要修改QQ或Keep中的步数,可以用自己的app写入步数数据,亲测有效)

①请求用户授权

  HKQuantityType *stepType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
  NSSet *shareTypes = [NSSet setWithObjects:stepType, nil];
 [self.healthStore requestAuthorizationToShareTypes:shareTypes readTypes:nil completion:^(BOOL success, NSError * _Nullable error) {

 }];

②写入数据

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 ? @"成功" : @"失败";
  });
}];

项目中使用了HealthKit时,上架需要注意点:

  • 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.//你的应用不应该将HealthKit收集的数据用于广告或类似的服务。注意,可能在使用HealthKit框架应用中还是要服务广告,但是你不能使用HealthKit中的数据来服务广告。
  • 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.// 在没有用户的明确允许下,你不能向第三方展示任何HealthKit收集的数据。即使用户允许,你也只能向提供健康或健身服务的第三方展示这些数据
  • You cannot sell information gained through HealthKit to advertising platforms, data brokers, or information resellers.// 你不能将HealthKit收集的数据出售给广告平台、数据代理人或者信息经销商
  • If the user consents, you may share his or her HealthKit data with a third party for medical research.// 如果用户允许,你可以将HealthKit数据共享给第三方用于医学研究。
  • You must clearly disclose to the user how you and your app will use their HealthKit data.//你必须明确说明,你和你的应用会怎样使用用户的HealthKit数据。

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://你必须为每个使用HealthKit框架的应用提供一份隐私策略。你可以在以下网站找到创建隐私策略的指导:

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# iOS  # 计步器  # 计步器实现  # ios计步器代码实现  # vue 里面使用axios 和封装的示例代码  # iOS中利用CoreAnimation实现一个时间的进度条效果  # IOS NSUserDefault 记住用户名及密码功能的实例代码  # iOS 获取设备唯一标示符的方法详解  # iOS在Block中修改外部变量值的实现代码  # ios原生和react-native各种交互的示例代码  # IOS 开发之实现取消tableView返回时cell选中的问题  # 不支持  # 值为  # 第三方  # 这是  # 这将  # 你可以  # 应用程序  # 不需要  # 是从  # 如果没有  # 可以使用  # 历史记录  # 你必须  # 自己的  # 的是  # 过滤掉  # 是在  # 会有  # 结束时间 


相关文章: 台州网站建设制作公司,浙江手机无犯罪记录证明怎么开?  ,南京靠谱的征婚网站?  装修招标网站设计制作流程,装修招标流程?  如何在阿里云虚拟主机上快速搭建个人网站?  如何用搬瓦工VPS快速搭建个人网站?  如何通过多用户协作模板快速搭建高效企业网站?  山东云建站价格为何差异显著?  实现虚拟支付需哪些建站技术支撑?  网站制作说明怎么写,简述网页设计的流程并说明原因?  如何快速生成ASP一键建站模板并优化安全性?    宝塔建站无法访问?如何排查配置与端口问题?  建站之星如何实现网站加密操作?  如何在阿里云ECS服务器部署织梦CMS网站?  打鱼网站制作软件,波克捕鱼官方号怎么注册?  企业宣传片制作网站有哪些,传媒公司怎么找企业宣传片项目?  如何彻底卸载建站之星软件?  如何通过可视化优化提升建站效果?  电商网站制作价格怎么算,网上拍卖流程以及规则?  如何使用Golang table-driven基准测试_多组数据测量函数效率  太原网站制作公司有哪些,网约车营运证查询官网?  Python文件管理规范_工程实践说明【指导】  建站之星安装后如何配置SEO及设计样式?  小型网站制作HTML,*游戏网站怎么搭建?  网站制作知乎推荐,想做自己的网站用什么工具比较好?  如何挑选高效建站主机与优质域名?  已有域名如何免费搭建网站?  宁波自助建站系统如何快速打造专业企业网站?  如何在IIS中新建站点并解决端口绑定冲突?  c++怎么实现高并发下的无锁队列_c++ std::atomic原子变量与CAS操作【详解】  C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)  历史网站制作软件,华为如何找回被删除的网站?  名字制作网站免费,所有小说网站的名字?  广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?  SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?  在线制作视频网站免费,都有哪些好的动漫网站?  较简单的网站制作软件有哪些,手机版网页制作用什么软件?  官网网站制作腾讯审核要多久,联想路由器newifi官网  logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?  ,购物网站怎么盈利呢?  Swift中swift中的switch 语句  网站制作专业公司有哪些,如何制作一个企业网站,建设网站的基本步骤有哪些?  外贸公司网站制作,外贸网站建设一般有哪些步骤?  如何正确下载安装西数主机建站助手?  教学论文网站制作软件有哪些,写论文用什么软件 ?  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  长春网站建设制作公司,长春的网络公司怎么样主要是能做网站的?  教程网站设计制作软件,怎么创建自己的一个网站?  css网站制作参考文献有哪些,易聊怎么注册?  网站好制作吗知乎,网站开发好学吗?有什么技巧? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。