Android计步功能的实现代码
本文对原文计步项目进行了精简,移除了进程服务和计时、守护进程、数据库保存等等,方便扩展功能。
Android4.4以上版本,有些手机有计步传感器可以直接使用,而有些手机没有,但有加速度传感器,也可以实现计步功能(需要计算加速度波峰波谷来判断人走一步)!
一.使用
publicclassMainActivityextendsAppCompatActivityimplementsStepCallBack{ ......... @Override publicvoidStep(intstepNum){ //计步回调 stepText.setText("步数:"+stepNum); } @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); stepText=(TextView)findViewById(R.id.step_text); //开启计步监听,分为加速度传感器、或计步传感器 stepSensor=newStepSensorPedometer(this,this); if(!stepSensor.registerStep()){ Toast.makeText(this,"计步传传感器不可用!",Toast.LENGTH_SHORT).show(); stepSensor=newStepSensorAcceleration(this,this); if(!stepSensor.registerStep()){ Toast.makeText(this,"加速度传感器不可用!",Toast.LENGTH_SHORT).show(); } } } ....... }
二.计步传感器抽象类
/** *计步传感器抽象类,子类分为加速度传感器、或计步传感器 */ publicabstractclassStepSensorBaseimplementsSensorEventListener{ privateContextcontext; publicStepCallBackstepCallBack; publicSensorManagersensorManager; publicstaticintCURRENT_SETP=0; publicbooleanisAvailable=false; publicStepSensorBase(Contextcontext,StepCallBackstepCallBack){ this.context=context; this.stepCallBack=stepCallBack; } /** *开启计步 */ publicbooleanregisterStep(){ if(sensorManager!=null){ sensorManager.unregisterListener(this); sensorManager=null; } sensorManager=(SensorManager)context.getSystemService(Context.SENSOR_SERVICE); registerStepListener(); returnisAvailable; } /** *注册计步监听器 */ protectedabstractvoidregisterStepListener(); /** *注销计步监听器 */ publicabstractvoidunregisterStep(); }
三.直接使用计步传感器
/** *计步传感器 */ publicclassStepSensorPedometerextendsStepSensorBase{ privatefinalStringTAG="StepSensorPedometer"; privateintlastStep=-1; privateintliveStep=0; privateintincrement=0; privateintsensorMode=0;//计步传感器类型 publicStepSensorPedometer(Contextcontext,StepCallBackstepCallBack){ super(context,stepCallBack); } @Override protectedvoidregisterStepListener(){ SensordetectorSensor=sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR); SensorcountSensor=sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); if(sensorManager.registerListener(this,detectorSensor,SensorManager.SENSOR_DELAY_UI)){ isAvailable=true; sensorMode=0; Log.i(TAG,"计步传感器Detector可用!"); }elseif(sensorManager.registerListener(this,countSensor,SensorManager.SENSOR_DELAY_UI)){ isAvailable=true; sensorMode=1; Log.i(TAG,"计步传感器Counter可用!"); }else{ isAvailable=false; Log.i(TAG,"计步传感器不可用!"); } } @Override publicvoidunregisterStep(){ sensorManager.unregisterListener(this); } @Override publicvoidonSensorChanged(SensorEventevent){ liveStep=(int)event.values[0]; if(sensorMode==0){ StepSensorBase.CURRENT_SETP+=liveStep; }elseif(sensorMode==1){ StepSensorBase.CURRENT_SETP=liveStep; } stepCallBack.Step(StepSensorBase.CURRENT_SETP); } @Override publicvoidonAccuracyChanged(Sensorsensor,intaccuracy){ } }
三.使用加速度传感器实现计步功能
publicclassStepSensorAccelerationextendsStepSensorBase{ privatefinalStringTAG="StepSensorAcceleration"; //存放三轴数据 finalintvalueNum=5; //用于存放计算阈值的波峰波谷差值 float[]tempValue=newfloat[valueNum]; inttempCount=0; //是否上升的标志位 booleanisDirectionUp=false; //持续上升次数 intcontinueUpCount=0; //上一点的持续上升的次数,为了记录波峰的上升次数 intcontinueUpFormerCount=0; //上一点的状态,上升还是下降 booleanlastStatus=false; //波峰值 floatpeakOfWave=0; //波谷值 floatvalleyOfWave=0; //此次波峰的时间 longtimeOfThisPeak=0; //上次波峰的时间 longtimeOfLastPeak=0; //当前的时间 longtimeOfNow=0; //当前传感器的值 floatgravityNew=0; //上次传感器的值 floatgravityOld=0; //动态阈值需要动态的数据,这个值用于这些动态数据的阈值 finalfloatinitialValue=(float)1.7; //初始阈值 floatThreadValue=(float)2.0; //初始范围 floatminValue=11f; floatmaxValue=19.6f; /** *0-准备计时1-计时中2-正常计步中 */ privateintCountTimeState=0; publicstaticintTEMP_STEP=0; privateintlastStep=-1; //用x、y、z轴三个维度算出的平均值 publicstaticfloataverage=0; privateTimertimer; //倒计时3.5秒,3.5秒内不会显示计步,用于屏蔽细微波动 privatelongduration=3500; privateTimeCounttime; publicStepSensorAcceleration(Contextcontext,StepCallBackstepCallBack){ super(context,stepCallBack); } @Override protectedvoidregisterStepListener(){ //注册加速度传感器 isAvailable=sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI); if(isAvailable){ Log.i(TAG,"加速度传感器可用!"); }else{ Log.i(TAG,"加速度传感器不可用!"); } } @Override publicvoidunregisterStep(){ sensorManager.unregisterListener(this); } publicvoidonAccuracyChanged(Sensorarg0,intarg1){ } publicvoidonSensorChanged(SensorEventevent){ Sensorsensor=event.sensor; synchronized(this){ if(sensor.getType()==Sensor.TYPE_ACCELEROMETER){ calc_step(event); } } } synchronizedprivatevoidcalc_step(SensorEventevent){ average=(float)Math.sqrt(Math.pow(event.values[0],2) +Math.pow(event.values[1],2)+Math.pow(event.values[2],2)); detectorNewStep(average); } /* *检测步子,并开始计步 *1.传入sersor中的数据 *2.如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步 *3.符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中 **/ publicvoiddetectorNewStep(floatvalues){ if(gravityOld==0){ gravityOld=values; }else{ if(DetectorPeak(values,gravityOld)){ timeOfLastPeak=timeOfThisPeak; timeOfNow=System.currentTimeMillis(); if(timeOfNow-timeOfLastPeak>=200 &&(peakOfWave-valleyOfWave>=ThreadValue)&&(timeOfNow-timeOfLastPeak)<=2000){ timeOfThisPeak=timeOfNow; //更新界面的处理,不涉及到算法 preStep(); } if(timeOfNow-timeOfLastPeak>=200 &&(peakOfWave-valleyOfWave>=initialValue)){ timeOfThisPeak=timeOfNow; ThreadValue=Peak_Valley_Thread(peakOfWave-valleyOfWave); } } } gravityOld=values; } privatevoidpreStep(){ //if(CountTimeState==0){ ////开启计时器 //time=newTimeCount(duration,700); //time.start(); //CountTimeState=1; //Log.v(TAG,"开启计时器"); //}elseif(CountTimeState==1){ //TEMP_STEP++; //Log.v(TAG,"计步中TEMP_STEP:"+TEMP_STEP); //}elseif(CountTimeState==2){ CURRENT_SETP++; //if(stepCallBack!=null){ stepCallBack.Step(CURRENT_SETP); //} //} } /* *检测波峰 *以下四个条件判断为波峰: *1.目前点为下降的趋势:isDirectionUp为false *2.之前的点为上升的趋势:lastStatus为true *3.到波峰为止,持续上升大于等于2次 *4.波峰值大于1.2g,小于2g *记录波谷值 *1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值 *2.所以要记录每次的波谷值,为了和下次的波峰做对比 **/ publicbooleanDetectorPeak(floatnewValue,floatoldValue){ lastStatus=isDirectionUp; if(newValue>=oldValue){ isDirectionUp=true; continueUpCount++; }else{ continueUpFormerCount=continueUpCount; continueUpCount=0; isDirectionUp=false; } //Log.v(TAG,"oldValue:"+oldValue); if(!isDirectionUp&&lastStatus &&(continueUpFormerCount>=2&&(oldValue>=minValue&&oldValue=8){ //Log.v(TAG,"超过8"); ave=(float)4.3; }elseif(ave>=7&&ave<8){ //Log.v(TAG,"7-8"); ave=(float)3.3; }elseif(ave>=4&&ave<7){ //Log.v(TAG,"4-7"); ave=(float)2.3; }elseif(ave>=3&&ave<4){ //Log.v(TAG,"3-4"); ave=(float)2.0; }else{ //Log.v(TAG,"else"); ave=(float)1.7; } returnave; } classTimeCountextendsCountDownTimer{ publicTimeCount(longmillisInFuture,longcountDownInterval){ super(millisInFuture,countDownInterval); } @Override publicvoidonFinish(){ //如果计时器正常结束,则开始计步 time.cancel(); CURRENT_SETP+=TEMP_STEP; lastStep=-1; Log.v(TAG,"计时正常结束"); timer=newTimer(true); TimerTasktask=newTimerTask(){ publicvoidrun(){ if(lastStep==CURRENT_SETP){ timer.cancel(); CountTimeState=0; lastStep=-1; TEMP_STEP=0; Log.v(TAG,"停止计步:"+CURRENT_SETP); }else{ lastStep=CURRENT_SETP; } } }; timer.schedule(task,0,2000); CountTimeState=2; } @Override publicvoidonTick(longmillisUntilFinished){ if(lastStep==TEMP_STEP){ Log.v(TAG,"onTick计时停止:"+TEMP_STEP); time.cancel(); CountTimeState=0; lastStep=-1; TEMP_STEP=0; }else{ lastStep=TEMP_STEP; } } } }
本文源码:StepOrient_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。