日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

healthkit 之前的计步方案

發布時間:2024/1/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 healthkit 之前的计步方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文:http://blog.csdn.net/gf771115/article/details/52121489


計步模塊接觸了一年多,最近又改需求了,所以又換了全新的統計步數的方法,整理一下吧。

在iPhone5s以前機型因為沒有陀螺儀的存在,所以需要用加速度傳感器來采集加速度值信息,然后根據震動幅度讓其加入踩點數組并過濾,獲取自己需要的步數數據。

直接上代碼吧:

首先需要一個步數的model如下:

#import <Foundation/Foundation.h>@interface VHSSteps : NSObject //步數模型 @property(nonatomic,strong) NSDate *date;@property(nonatomic,assign) int record_no;@property(nonatomic, strong) NSString *record_time;@property(nonatomic,assign) int step;//g是一個震動幅度的系數,通過一定的判斷條件來判斷是否計做一步 @property(nonatomic,assign) double g;@end

然后是如何獲取步數,首先判斷傳感器是否可用

//加速度傳感器self.motionManager = [[CMMotionManager alloc] init];// 檢查傳感器到底在設備上是否可用if (!self.motionManager.accelerometerAvailable) {return;} else {// 更新頻率是100Hz//以pull方式獲取數據self.motionManager.accelerometerUpdateInterval = 1.0/40;}

可用的話開始實現統計步數的算法

@try{//如果不支持陀螺儀,需要用加速傳感器來采集數據if (!self.motionManager.isAccelerometerActive) {// isAccelerometerAvailable方法用來查看加速度器的狀態:是否Active(啟動)。// 加速度傳感器采集的原始數組if (arrAll == nil) {arrAll = [[NSMutableArray alloc] init];}else {[arrAll removeAllObjects];}/*1.push方式這種方式,是實時獲取到Accelerometer的數據,并且用相應的隊列來顯示。即主動獲取加速計的數據。*/NSOperationQueue *queue = [[NSOperationQueue alloc] init];[self.motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error){if (!self.motionManager.isAccelerometerActive) {return;}//三個方向加速度值double x = accelerometerData.acceleration.x;double y = accelerometerData.acceleration.y;double z = accelerometerData.acceleration.z;//g是一個double值 ,根據它的大小來判斷是否計為1步.double g = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2)) - 1;//將信息保存在步數模型中VHSSteps *stepsAll = [[VHSSteps alloc] init];stepsAll.date = [NSDate date];//日期NSDateFormatter *df = [[NSDateFormatter alloc] init] ;df.dateFormat = @"yyyy-MM-dd HH:mm:ss";NSString *strYmd = [df stringFromDate:stepsAll.date];df = nil;stepsAll.record_time =strYmd;stepsAll.g = g;// 加速度傳感器采集的原始數組 [arrAll addObject:stepsAll];// 每采集10條,大約1.2秒的數據時,進行分析if (arrAll.count == 10) {// 步數緩存數組NSMutableArray *arrBuffer = [[NSMutableArray alloc] init];arrBuffer = [arrAll copy];[arrAll removeAllObjects];// 踩點數組NSMutableArray *arrCaiDian = [[NSMutableArray alloc] init];//遍歷步數緩存數組for (int i = 1; i < arrBuffer.count - 2; i++) {//如果數組個數大于3,繼續,否則跳出循環,用連續的三個點,要判斷其振幅是否一樣,如果一樣,然并卵if (![arrBuffer objectAtIndex:i-1] || ![arrBuffer objectAtIndex:i] || ![arrBuffer objectAtIndex:i+1]){continue;}VHSSteps *bufferPrevious = (VHSSteps *)[arrBuffer objectAtIndex:i-1];VHSSteps *bufferCurrent = (VHSSteps *)[arrBuffer objectAtIndex:i];VHSSteps *bufferNext = (VHSSteps *)[arrBuffer objectAtIndex:i+1];//控制震動幅度,,,,,,根據震動幅度讓其加入踩點數組,if (bufferCurrent.g < -0.12 && bufferCurrent.g < bufferPrevious.g && bufferCurrent.g < bufferNext.g) {[arrCaiDian addObject:bufferCurrent];}}//如果沒有步數數組,初始化if (nil == self.arrSteps) {self.arrSteps = [[NSMutableArray alloc] init];self.arrStepsSave = [[NSMutableArray alloc] init];}// 踩點過濾for (int j = 0; j < arrCaiDian.count; j++) {VHSSteps *caidianCurrent = (VHSSteps *)[arrCaiDian objectAtIndex:j];//如果之前的步數為0,則重新開始記錄if (self.arrSteps.count == 0) {//上次記錄的時間lastDate = caidianCurrent.date;// 重新開始時,紀錄No初始化record_no = 1;record_no_save = 1;// 運動識別號NSTimeInterval interval = [caidianCurrent.date timeIntervalSince1970];NSNumber *numInter = [[NSNumber alloc] initWithDouble:interval*1000];long long llInter = numInter.longLongValue;//運動識別idself.actionId = [NSString stringWithFormat:@"%lld",llInter];self.distance = 0.00f;self.second = 0;self.calorie = 0;self.step = 0;self.gpsDistance = 0.00f;self.agoGpsDistance = 0.00f;self.agoActionDistance = 0.00f;caidianCurrent.record_no = record_no;caidianCurrent.step = self.step;[self.arrSteps addObject:caidianCurrent];[self.arrStepsSave addObject:caidianCurrent];}else {int intervalCaidian = [caidianCurrent.date timeIntervalSinceDate:lastDate] * 1000;// 步行最大每秒2.5步,跑步最大每秒3.5步,超過此范圍,數據有可能丟失int min = 259;if (intervalCaidian >= min) {if (self.motionManager.isAccelerometerActive) {//存一下時間lastDate = caidianCurrent.date;if (intervalCaidian >= ACCELERO_START_TIME * 1000) {// 計步器開始計步時間(秒)self.startStep = 0;}if (self.startStep < ACCELERO_START_STEP) {//計步器開始計步步數 (步) self.startStep ++;break;}else if (self.startStep == ACCELERO_START_STEP) {self.startStep ++;// 計步器開始步數// 運動步數(總計)self.step = self.step + self.startStep;}else {self.step ++;}//步數在這里NSLog(@"步數%d",self.step);int intervalMillSecond = [caidianCurrent.date timeIntervalSinceDate:[[self.arrSteps lastObject] date]] * 1000;if (intervalMillSecond >= 1000) {record_no++;caidianCurrent.record_no = record_no;caidianCurrent.step = self.step;[self.arrSteps addObject:caidianCurrent];}// 每隔100步保存一條數據(將來插入DB用)VHSSteps *arrStepsSaveVHSSteps = (VHSSteps *)[self.arrStepsSave lastObject];int intervalStep = caidianCurrent.step - arrStepsSaveVHSSteps.step;// DB_STEP_INTERVAL 數據庫存儲步數采集間隔(步) 100步if (self.arrStepsSave.count == 1 || intervalStep >= DB_STEP_INTERVAL) {//保存次數record_no_save++;caidianCurrent.record_no = record_no_save;[self.arrStepsSave addObject:caidianCurrent];// 備份當前運動數據至文件中,以備APP異常退出時數據也不會丟失// [self bkRunningData]; }}}// 運動提醒檢查// [self checkActionAlarm]; }}}}];}}@catch (NSException * e) {NSLog(@"Exception: %@", e);return;}

然后iPhone 5s出現了, 增加了 M7 運動協處理器,也帶來了CMStepCounter類,從此我們就不用自己計算步數了,只要直接讀取就好。

  首先還是要檢測協處理器是否可用

if (!([CMStepCounter isStepCountingAvailable] || [CMMotionActivityManager isActivityAvailable])) {NSString *msg = @"demo只支持iPhone5s以上機型.";UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Opps!"message:msgdelegate:nilcancelButtonTitle:@"OK"otherButtonTitles:nil];[alert show];}

然后才是獲取步數的方法,主要有兩種:

計步 第一種方法
??? ?
???? startStepCountingUpdatesToQueue:updateOn:withHandler:
??? ?
???? 開始分發當前步數計數數據到第三方應用
??? ?
???? - (void)startStepCountingUpdatesToQueue:(NSOperationQueue *)queue updateOn:(NSInteger)stepCounts withHandler:(CMStepUpdateHandler)handler
???? Parameters
??? ?
???? queue
??? ?
???? 被指定執行特定的handler塊的操作隊列。第三方可以指定一個定制隊列或者使用操作隊列協助app的主線程。該參數不能為nil
??? ?
???? stepCounts
??? ?
???? 記錄的步伐數據,達到該數值去執行handler塊。該數值必須大于0
??? ?
???? handler
??? ?
???? 該塊在步伐計數達到或超出數值時會被執行,該參數不能為nil。更多塊方法信息參考CMStepQueryHandler。
??? ?
???? Discussion
??? ?
???? 該方法實現對用戶步伐數據的追蹤,并周期性地喚起塊方法去分發結果。當第三方調用了該方法,步伐計數器會重置當前步伐數為0,并開始計數。每次計數到達指定的步伐數時,會執行指定的handler塊方法。比如,當設定stepCounts為100時,會在100,200,300等數目時發送更新,激活該塊方法。每次發送到該塊方法的步伐數目都是從你調用該方法開始的步伐數目總和。
??? ?
???? 每次超過設定步數值時,指定的處理程序塊handler會被執行。如果當超過設定值時第三方應用處在被掛起的狀態,那程序塊也不會被執行。當第三方應用被喚醒,程序塊也不會執行,直到再次超過設定步數值。
??? ?
???? 可以調用stopStepCountingUpdates方法去停止分發步數計數,當然當步數計數對像被銷毀的時候,分發過程也會被停止。
????
  代碼如下:

if ([CMStepCounter isStepCountingAvailable]) {self.stepCounter = [[CMStepCounter alloc] init];[self.stepCounter startStepCountingUpdatesToQueue:self.operationQueueupdateOn:1withHandler:^(NSInteger numberOfSteps, NSDate *timestamp, NSError *error) {dispatch_async(dispatch_get_main_queue(), ^{if (error) {UIAlertView *error = [[UIAlertView alloc] initWithTitle:@"Opps!" message:@"error" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];[error show];}else {NSString *text = [NSString stringWithFormat:@"當前步數: %ld", (long)numberOfSteps];//這里是步數weakSelf.stepsLabel.text = text;}});}]; }

?

計步 第二種方法

????
???? queryStepCountStartingFrom:to:toQueue:withHandler:
??? ?
???? 收集并返回某一時間段內的歷史步數數據
??? ?
???? - (void)queryStepCountStartingFrom:(NSDate *)start to:(NSDate *)end toQueue:(NSOperationQueue *)queuewithHandler:(CMStepQueryHandler)handler
???? Parameters
??? ?
???? start
??? ?
???? 收集步數數據的開始時間,該參數不能為 nil.
??? ?
???? end
??? ?
???? 收集步數數據的停止時間,該參數不能為nil.
??? ?
???? queue
??? ?
???? 執行指定handler塊的操作隊列,第三方可以指定一個定制隊列或者使用操作隊列協助app的主線程。該參數不能為nil
??? ?
???? handler
??? ?
???? 執行處理結果的塊方法,該參數不能為nil。更多塊方法信息參考CMStepQueryHandler。
??? ?
???? Discussion
??? ?
???? 該方法為異步方法,會立即返回并且把結果分發到指定的handler塊中處理。系統最多僅存儲最近7天內的有效步數數據。如果在指定時間范圍內沒有數據,則會傳遞一個0值到handler塊中。
  
代碼如下

// 獲取今日步數 __weak ViewController *weakSelf = self; self.operationQueue = [[NSOperationQueue alloc] init];NSCalendar *calendar = [NSCalendar currentCalendar]; NSDate *now = [NSDate date]; NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:now]; // 開始日期 NSDate *startDate = [calendar dateFromComponents:components]; // 結束日期 NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];if ([CMStepCounter isStepCountingAvailable]) {[self.stepCounter queryStepCountStartingFrom:startDate to:endDate toQueue:self.operationQueue withHandler:^(NSInteger numberOfSteps, NSError * _Nullable error) {NSLog(@"%ld",numberOfSteps);dispatch_async(dispatch_get_main_queue(), ^{if (error) {UIAlertView *error = [[UIAlertView alloc] initWithTitle:@"Opps!" message:@"error" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];[error show];}else {weakSelf.totalLabel.text = [NSString stringWithFormat:@"今日總步數%ld",numberOfSteps];}});}]; }

另外,iOS7還增加了CMMotionActivity類,用來獲取運動狀態

if ([CMMotionActivityManager isActivityAvailable]) {self.activityManager = [[CMMotionActivityManager alloc] init];[self.activityManager startActivityUpdatesToQueue:self.operationQueuewithHandler:^(CMMotionActivity *activity) {dispatch_async(dispatch_get_main_queue(), ^{NSString *status = [weakSelf statusForActivity:activity];NSString *confidence = [weakSelf stringFromConfidence:activity.confidence];weakSelf.statusLabel.text = [NSString stringWithFormat:@"狀態: %@", status];weakSelf.confidenceLabel.text = [NSString stringWithFormat:@"速度: %@", confidence];});}]; } - (NSString *)statusForActivity:(CMMotionActivity *)activity {NSMutableString *status = @"".mutableCopy;if (activity.stationary) {[status appendString:@"not moving"];}if (activity.walking) {if (status.length) [status appendString:@", "];[status appendString:@"on a walking person"];}if (activity.running) {if (status.length) [status appendString:@", "];[status appendString:@"on a running person"];}if (activity.automotive) {if (status.length) [status appendString:@", "];[status appendString:@"in a vehicle"];}if (activity.unknown || !status.length) {[status appendString:@"unknown"];}return status; }- (NSString *)stringFromConfidence:(CMMotionActivityConfidence)confidence {switch (confidence) {case CMMotionActivityConfidenceLow:return @"Low";case CMMotionActivityConfidenceMedium:return @"Medium";case CMMotionActivityConfidenceHigh:return @"High";default:return nil;} }

好吧,隨著時間的推移,iOS8來了,也帶來了healthkit,不過之前的方法滿足需求也就還是用的CMStepCounter方法。

不過最近客戶改需求了,手環,iWatch的數據也需要統計進來,就不得不用healthkit的方法了。

?還是老套路,先檢查能不能用

//查看healthKit在設備上是否可用,ipad不支持HealthKitif(![HKHealthStore isHealthDataAvailable]){NSLog(@"設備不支持healthKit");}

然后獲取步數

//創建healthStore實例對象self.healthStore = [[HKHealthStore alloc] init];//設置需要獲取的權限這里僅設置了步數HKObjectType *stepCount = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];NSSet *healthSet = [NSSet setWithObjects:stepCount, nil];//從健康應用中獲取權限[self.healthStore requestAuthorizationToShareTypes:nil readTypes:healthSet completion:^(BOOL success, NSError * _Nullable error) {if (success){NSDateFormatter *formatter = [[NSDateFormatter alloc ]init];[formatter setDateFormat:@"yyyy-MM-dd"];NSDate *now = [NSDate date];NSString *todaystr = [formatter stringFromDate:now];NSDate *today = [formatter dateFromString:todaystr];NSDate *next = [today dateByAddingTimeInterval:24*60*60];        //定義需要獲取的數據為步數HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];        //設置獲取的步數時間間隔NSDateComponents *dateComponents = [[NSDateComponents alloc] init];dateComponents.day = 1;NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:today endDate:next options:HKQueryOptionStrictStartDate];//創建查詢統計對象collectionQueryHKStatisticsCollectionQuery *collectionQuery = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType quantitySamplePredicate:predicate options: HKStatisticsOptionCumulativeSum | HKStatisticsOptionSeparateBySource anchorDate:[NSDate dateWithTimeIntervalSince1970:0] intervalComponents:dateComponents];collectionQuery.initialResultsHandler = ^(HKStatisticsCollectionQuery *query, HKStatisticsCollection * __nullable result, NSError * __nullable error) {float numberOfSteps = 0;for (HKStatistics *statistic in result.statistics) {for (HKSource *source in statistic.sources) { //HKSource對象中的name可用于區分健康數據來源if ([source.name isEqualToString:deviceName]) {float steps = [[statistic sumQuantityForSource:source] doubleValueForUnit:[HKUnit countUnit]];numberOfSteps += steps;} //deviceName是根據接入的設備做的標記,if ([deviceName isEqualToString:@"iPhone"]) {if ([source.name isEqualToString:[UIDevice currentDevice].name]) {float steps = [[statistic sumQuantityForSource:source] doubleValueForUnit:[HKUnit countUnit]];numberOfSteps += steps;}}else if ([deviceName isEqualToString:@"iWatch"] && ![source.name isEqualToString:[UIDevice currentDevice].name]){if ([source.bundleIdentifier hasPrefix:@"com.apple.health"]) {float steps = [[statistic sumQuantityForSource:source] doubleValueForUnit:[HKUnit countUnit]];numberOfSteps += steps;}}else if ([deviceName isEqualToString:@"xiaomi"]){if ([source.name isEqualToString:@"小米運動"] || [source.bundleIdentifier isEqualToString:@"HM.wristband"]) {float steps = [[statistic sumQuantityForSource:source] doubleValueForUnit:[HKUnit countUnit]];numberOfSteps += steps;}}}}NSLog(@"ff = %f",numberOfSteps);//步數看這里就好stepString = [NSString stringWithFormat:@"%.0f",numberOfSteps];//CGFloat distance = [VHSCommon getDistance:numberOfSteps];//int calorie = [VHSCommon getActionCalorie:distance speed:distance * 3600 / 24*60*60];//distanceString = [NSString stringWithFormat:@"%.2f",distance];//calorString = [NSString stringWithFormat:@"%d",calorie]; };[self.healthStore executeQuery:collectionQuery];}else{NSLog(@"獲取步數權限失敗");}}];

demo完整代碼在這里:

加速度傳感器進行計步

CMStepCounter獲取健康步數

關于healthkit的還沒有整理好,過段時間再補充吧。


總結

以上是生活随笔為你收集整理的healthkit 之前的计步方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本欧美在线播放 | 中文字幕免费视频观看 | 亚洲永久精品在线观看 | 日韩精品高清视频 | 亚洲国产黄 | av青草| 妖精视频在线观看免费 | 亚洲xxx视频 | 色综合天天综合网国产成人网 | 中国国产黄色片 | 久久在线中文字幕 | 黄瓜视频在线观看 | 毛片一级免费 | 国产福利久久 | 国产做爰免费观看视频 | 欧美99| 国产无套在线观看 | 欧美人妻精品一区二区 | 亚洲成人免费视频 | www亚洲成人 | 日韩精品在线观看中文字幕 | 亚洲一级影院 | 一区二区免费播放 | gogo人体做爰aaaa | 红桃视频黄色 | 在线播放亚洲 | 成人作爱视频 | 成人国产 | 成人尹人 | 中文字幕无线码一区 | 蜜臀在线一区二区三区 | 日韩精品一区二区三区av | 在线观看涩涩视频 | 成人av动漫在线观看 | 色欲无码人妻久久精品 | 黑帮大佬和我的365日第二部 | 欧美精品免费一区二区 | 成人综合一区二区 | 国产999精品视频 | 精品少妇白浆小泬60P | wwwxxxx欧美| 国产伦精品一区二区三区妓女下载 | 国产wwwxxx| 很黄很色的视频 | 又黄又爽又刺激的视频 | 成人深夜网站 | av美女网站 | 日韩av导航 | 一区二区三区四区在线观看视频 | 超碰在线香蕉 | 妺妺窝人体色www聚色窝仙踪 | 中文字幕永久在线视频 | 国产精品久久婷婷 | 国产亚洲欧美日韩精品 | 亚洲精品一区二区三区蜜桃久 | 久久调教视频 | 91综合色 | 懂色av蜜臂av粉嫩av | 岳奶大又白下面又肥又黑水多 | 精品视频一区二区在线 | 中出白浆 | 色一区二区三区四区 | 国产一级在线观看视频 | 毛片xxx| 蜜桃成人无码区免费视频网站 | 91免费网站入口 | 五月情婷婷 | 亚洲青色在线 | 婷婷久久精品 | 欧美深性狂猛ⅹxxx深喉 | 九九免费在线视频 | 亚洲视频免费在线 | 黄色一级片a | 风流僵尸艳片a级 | 欧美黑人一区二区三区 | 中文字幕在线观看高清 | 波多野结衣在线视频播放 | 毛片av网站| 天天干夜夜添 | 日韩大片在线免费观看 | 一色桃子juy758在线播放 | 精品人妻一区二区乱码 | 91av网址 | 无码国产精品96久久久久 | 午夜性剧场 | 一级aaaa毛片 | 91精品日韩 | 成熟人妻av无码专区 | 亚洲最大综合网 | 欧美激情影音先锋 | 国产女人18毛片水18精 | 天天插天天狠 | 日本大胆欧美人术艺术 | 国产18在线 | 97caoporn| 国产清纯白嫩初高中在线观看性色 | 外国av网站 | 国产做爰免费观看 | 九九九网站 |