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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。