前言
當(dāng)前社會隨著社會水平的越來越高艰亮,人民飲食也更加的豐富多樣,隨之而來就成就了越來越多可愛的胖子娃圆。胖子多了蔫慧,一些“不良商販”發(fā)現(xiàn)商機(jī)研發(fā)出了運(yùn)動健身類的APP挠乳,如:Keep,咕咚,動動睡扬,趣走等等盟蚣,就連我們的移動社交老大哥騰訊也相繼推出了微信運(yùn)動,qq運(yùn)動等功能卖怜。那么今天我將通過此篇文章來給大家簡單介紹一下在我們的iOS中想要實(shí)現(xiàn)一個計(jì)步器的功能有哪幾種方案刁俭,以及實(shí)現(xiàn)它的一些原理。
實(shí)現(xiàn)方案
從目前技術(shù)角度來看韧涨,ios實(shí)現(xiàn)計(jì)步功能主要有三種方案:加速計(jì)牍戚,CMPedometer,HealthKit。下面我們分別來說說這三種實(shí)現(xiàn)方案虑粥。
一如孝、加速計(jì)
iOS4以后蘋果已經(jīng)提供了CoreMotion(核心運(yùn)動框架),但是并沒有提供給我們關(guān)于步數(shù)計(jì)算和行走公里數(shù)的計(jì)算方法娩贷。iOS7出現(xiàn)以后蘋果在CoreMotion中添加了CMStepCounter第晰,此時(shí)我們就可以通過CMStepCounter來計(jì)算行走的步數(shù)和公里數(shù)據(jù)了。iOS8的時(shí)候又出現(xiàn)了CMPedometer彬祖,它是CMStepCounter的替代者茁瘦,CMPedometer中的數(shù)據(jù)種類也變得更加多樣,比如我們不只可以獲取步數(shù)和公里數(shù)储笑,我們還可以計(jì)算我們的上下樓層數(shù)甜熔,以及我們活動的平均速度等等。但是由于硬件的緣故突倍,在iPhone5s以下的設(shè)備中沒有協(xié)處理器腔稀,就設(shè)備本身來講我們是無法通過手機(jī)去計(jì)算步數(shù)和公里數(shù)的。難道這樣我們就放棄了我們要做計(jì)步器的初衷了嗎羽历?當(dāng)然不是焊虏,下面我們就來介紹在iPhone5s以下設(shè)備中比較流行的一種計(jì)步器的實(shí)現(xiàn)方案——加速計(jì)
加速計(jì)是CoreMotion框架中用來計(jì)算設(shè)備在三維空間中的加速度的。那么我們?nèi)绾瓮ㄟ^加速計(jì)來計(jì)算步數(shù)呢秕磷?接下來我將詳細(xì)介紹加速計(jì)計(jì)算步數(shù)的原理诵闭。
原理
我們通過加速計(jì)來進(jìn)行特性分析,分別用以檢測人步行中三個方向的加速度變化澎嚣,如下圖
當(dāng)我們在水平步行運(yùn)動中疏尿,垂直和前進(jìn)兩個加速度會呈現(xiàn)周期性變化,如圖下圖所示币叹,在步行收腳的動作中润歉,由于重心向上單只腳觸地模狭,垂直方向加速度是呈正向增加的趨勢颈抚,之后繼續(xù)向前,重心下移兩腳觸底,加速度相反贩汉。水平加速度在收腳時(shí)減小驱富,在邁步時(shí)增加。
反映到圖表中匹舞,我們可以看到在步行運(yùn)動中褐鸥,垂直和前進(jìn)產(chǎn)生的加速度與時(shí)間大致為一個正弦曲線,而且在某點(diǎn)有一個峰值赐稽,其中垂直方向的加速度變化最大叫榕,通過對軌跡的峰值進(jìn)行檢測計(jì)算和加速度閾值決策,即可實(shí)時(shí)計(jì)算用戶運(yùn)動的步數(shù)姊舵。
?因?yàn)橛脩粼谶\(yùn)動中可能手平持設(shè)備或者將設(shè)備置于口袋中晰绎,所以設(shè)備的放置方向不定,為此我們通過計(jì)算三個加速度的矢量長度括丁,獲得一條步行運(yùn)動的正弦曲線軌跡荞下。
第二步是峰值檢測,我們記錄了上次矢量長度和運(yùn)動方向史飞,通過矢量長度的變化尖昏,可以判斷目前加速度的方向,并和上一次保存的加速度方向進(jìn)行比較构资,如果是相反的抽诉,即是剛過峰值狀態(tài),則進(jìn)入計(jì)步邏輯進(jìn)行計(jì)步吐绵,否則舍棄掸鹅。通過對峰值的次數(shù)累加可得到用戶步行步伐。
最后是去多余的干擾拦赠,手持設(shè)備會有一些低幅度和快速的移動狀態(tài)巍沙,或是我們說的手抖和快速甩動,或者某個惡作劇用戶想通過短時(shí)快速反復(fù)搖動設(shè)備來模擬人走路(當(dāng)然也包括哪些將手機(jī)捆綁在狗尾巴上的天才)荷鼠,這些干擾數(shù)據(jù)如果不剔除句携,會影響記步的準(zhǔn)確值,對于這種干擾允乐,我們可以通過給檢測加上閾值和步頻判斷來過濾矮嫉。比如我們可以設(shè)置一個一步所用的時(shí)間,如果短于這個時(shí)間我們就過濾掉牍疏。就像博爾特蠢笋,100米最快也需要9.69s。如果有生物跑100米所用時(shí)間小于8秒了鳞陨,按照現(xiàn)在的身體極限我們就可以斷定這個生物99.9%不是人類昨寞。
二、CMPedometer
iOS8以后,CoreMotion框架中為我們提供了一個獲取用戶活動信息的對象CMPedometer,通過CMPedometer我們可以獲取用戶的活動信息援岩,如:行走步數(shù)歼狼,行走的公里數(shù),上下樓層數(shù)以及平均速度等享怀。因此我們通過CMPedometer調(diào)用它的API接口就完全可以獲取到我們想要的步數(shù)羽峰。下邊我將介紹一下我們用到的API。
1.?當(dāng)我們在使用CMPedometer查詢我們需要的數(shù)據(jù)的時(shí)候添瓷,比如:步數(shù)梅屉,公里數(shù),上下樓層數(shù)等鳞贷,我們需要先通過判斷接口判斷設(shè)備中的這些功能是否可用履植,如下邊方法:
//判斷計(jì)步器是否可用
+ (BOOL)isStepCountingAvailable;
//是否支持距離估計(jì)
+ (BOOL)isDistanceAvailable;
//是否支持樓梯計(jì)數(shù)
+?(BOOL)isFloorCountingAvailable;
//等等,不一一進(jìn)行介紹了悄晃。
?2.?因?yàn)槲覀冃枰獜脑O(shè)備中獲取我們需要的活動數(shù)據(jù)玫霎,所以我們需要調(diào)用的是設(shè)備的數(shù)據(jù)查詢接口,如下邊方法:
//此方法是從某一時(shí)間段開始妈橄,連續(xù)的采集數(shù)據(jù)庶近,當(dāng)設(shè)備中的活動數(shù)據(jù)發(fā)生變更就會回調(diào)此方法,此方法是在串行隊(duì)列中執(zhí)行眷蚓。
-(void)startPedometerUpdatesFromDate:(NSDate*)start?withHandler:(CMPedometerHandler)handler;
//此方法是查詢某一時(shí)間段的數(shù)據(jù)鼻种,時(shí)間可長達(dá)7天,此方法是在串行隊(duì)列中執(zhí)行沙热。
-?(void)queryPedometerDataFromDate:(NSDate*)start?toDate:(NSDate*)endwithHandler:(CMPedometerHandler)handler;
3.?廢話不多說叉钥,直接上代碼?
連續(xù)獲取數(shù)據(jù)
?獲取某一時(shí)間段的數(shù)據(jù)
更新UI
三、HealthKit
?? ????iOS8以后蘋果推出了一個新的手機(jī)自帶的App——健康A(chǔ)pp篙贸,這個App就是用來顯示我們的活動信息的投队。并且蘋果還為我們提供了一個訪問健康A(chǔ)pp的框架HealthKit。我們可以理解HealthKit是一個活動數(shù)據(jù)的中央存儲庫爵川,而健康A(chǔ)pp是用來展示這個庫中的數(shù)據(jù)的敷鸦。那么HealthKit是如何獲取用戶的活動數(shù)據(jù)的呢?首先我們想一下寝贡,健康A(chǔ)pp中的運(yùn)動數(shù)據(jù)是從哪兒來的扒披?運(yùn)動信息嘛當(dāng)然是從核心運(yùn)動框架里邊來的了,那么訪問核心運(yùn)動框架中的信息都是通過CMPedometer來訪問的圃泡,所以我們就知道了HealthKit底層也是通過上邊我們提到CMPedometer來獲取用戶信息的碟案,只不過它的獲取方法在手機(jī)內(nèi)部,通過協(xié)處理器來進(jìn)行計(jì)算的颇蜡。而協(xié)處理器在5s以后的設(shè)備中才出現(xiàn)的价说,所以在5s以前的設(shè)備中是無法獲取用戶的運(yùn)動信息的辆亏。
??
我們在使用HealthKit的時(shí)候的注意事項(xiàng):
A:需要把HealthKit配置到AppID中
B:Xocede中需要打開HealthKit的開關(guān)選項(xiàng)
C:需要調(diào)用isHealthDataAvailable方法檢測HealthKit是否可用
D:在讀取和寫入數(shù)據(jù)之前需要先獲取權(quán)限,并且設(shè)置讀取和寫入的數(shù)據(jù)類型
申請權(quán)限
F:在info.plist文件中熔任,增加NSHealthShareUsageDescription用于讀取數(shù)據(jù)的描述和NSHealthUpdateUsageDescription用于寫入數(shù)據(jù)的描述。
設(shè)置好上面的配置信息后我們?nèi)绾卧L問和讀取數(shù)據(jù)呢唁情,下邊我們將以特征數(shù)據(jù)(性別)和樣本數(shù)據(jù)(步數(shù))為例疑苔,話不多說,直接上代碼甸鸟。
性別讀鹊敕选:
特征數(shù)據(jù)我們一般都是用HKHealthStore直接訪問,返回一個性別類型對象抢韭,然后通過對象值判斷性別薪贫。
?注意:特征數(shù)據(jù)只能讀取不能寫入,如何修改的話只能通過健康A(chǔ)pp來修改
步數(shù)讀瓤坦А:
a:事例查詢
此查詢方式為事例查詢瞧省,可以查詢到每一條寫入的數(shù)據(jù),并且能可以獲取數(shù)據(jù)的來源鳍贾,通過來源可以分析數(shù)據(jù)是設(shè)備背身記錄的數(shù)據(jù)還是三方app寫入的數(shù)據(jù)鞍匾。
b:統(tǒng)計(jì)查詢
此查詢方式為統(tǒng)計(jì)查詢,查詢結(jié)果為步數(shù)的總和骑科,不區(qū)分?jǐn)?shù)據(jù)來源橡淑。
步數(shù)寫入:
寫入數(shù)據(jù)一般我們采用saveObject的形式
以上為三種實(shí)現(xiàn)計(jì)步器的實(shí)現(xiàn)方案,下邊我將解答一下經(jīng)常有人問的問題:
1.如果我們用HealthKit寫入數(shù)據(jù)咆爽,那么我在其他App中讀取數(shù)據(jù)梁棠,那么這個數(shù)據(jù)是不是很大(比如微信的步數(shù)排行榜)?
????????首先我們介紹一下微信運(yùn)動斗埂,當(dāng)我們首次打開微信運(yùn)動的時(shí)候會出現(xiàn)一個提示框符糊,詢問是否允許訪問健康A(chǔ)pp,由此可以證明微信運(yùn)動就是通過HealthKit來訪問數(shù)據(jù)的呛凶。那么會不會出現(xiàn)我們上面提到的問題呢濒蒋?理論上是會的,前提是微信沒有進(jìn)行數(shù)據(jù)源判斷把兔。上邊我們提到了沪伙,每條數(shù)據(jù)我們都可以知道它的來源,通過來源我們就可以過濾數(shù)據(jù)县好,微信運(yùn)動有可能也是通過這種方式來處理了數(shù)據(jù)(個人猜測)围橡,通過此方式來保證數(shù)據(jù)的準(zhǔn)確。
2.如果我通過HealthKit寫入數(shù)據(jù)后缕贡,其他APP通過CMPedometer來訪問數(shù)據(jù)會不會很大翁授?
????????首先CMPedometer訪問的是核心運(yùn)動框架的數(shù)據(jù)拣播,而HealthKit寫入的數(shù)據(jù)只會保存在健康A(chǔ)pp中,健康A(chǔ)pp會整合數(shù)據(jù)收擦,將所有來源的數(shù)據(jù)進(jìn)行合并贮配,但是核心運(yùn)動框架中的數(shù)據(jù)還是與它分離的,只是HealthKit中也會包含核心運(yùn)動框架中的數(shù)據(jù)而已塞赂。所以結(jié)論就是CMPedometer訪問的還是核心運(yùn)動框架的數(shù)據(jù)泪勒,并不會讀取寫入的數(shù)據(jù)。