基于Android的计步器(Pedometer)的讲解(四)——后台记步
时间:2015-06-27 16:48:53
收藏:0
阅读:416
基于Android的计步器(Pedometer)的讲解(四)——后台记步
今天先不说Pedometer(计步器)项目UI方面的了,今天讲一个基于重力加速度的记步功能传感器(Sensor),然后
在后台开启记步。
计步器(Pedometer)整个项目的源代码,感兴趣的朋友可以下载来看看(记得帮小弟在github打个星~)
先上几张效果图:(效果和上一篇讲到的CircleBar非常的相似,因为记步功能在后台)


如图所示,能根据你的一些基本参数,来记步。有一个缺点,因为这个是根据感应加速度来计算是否走一步,所以你在原地晃手机,也会记步,不过正常的走路还是挺准确的。
首先给出StepDetector类的代码:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100packagecom.example.histogram.widet;importandroid.content.Context;importandroid.hardware.Sensor;importandroid.hardware.SensorEvent;importandroid.hardware.SensorEventListener;importandroid.hardware.SensorManager;/*** 这是一个实现了信号监听的记步的类* 这是从谷歌找来的一个记步的算法,看不太懂* @author Liyachao Date:2015-1-6**/publicclassStepDetectorimplementsSensorEventListener {publicstaticintCURRENT_SETP =0;publicstaticfloatSENSITIVITY =10;// SENSITIVITY灵敏度privatefloatmLastValues[] =newfloat[3*2];privatefloatmScale[] =newfloat[2];privatefloatmYOffset;privatestaticlongend =0;privatestaticlongstart =0;/*** 最后加速度方向*/privatefloatmLastDirections[] =newfloat[3*2];privatefloatmLastExtremes[][] = {newfloat[3*2],newfloat[3*2] };privatefloatmLastDiff[] =newfloat[3*2];privateintmLastMatch = -1;/*** 传入上下文的构造函数** @param context*/publicStepDetector(Context context) {super();inth =480;mYOffset = h *0.5f;mScale[0] = -(h *0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY *2)));mScale[1] = -(h *0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));}//当传感器检测到的数值发生变化时就会调用这个方法publicvoidonSensorChanged(SensorEvent event) {Sensor sensor = event.sensor;synchronized(this) {if(sensor.getType() == Sensor.TYPE_ACCELEROMETER) {floatvSum =0;for(inti =0; i <3; i++) {finalfloatv = mYOffset + event.values[i] * mScale[1];vSum += v;}intk =0;floatv = vSum /3;floatdirection = (v > mLastValues[k] ?1: (v < mLastValues[k] ? -1:0));if(direction == -mLastDirections[k]) {// Direction changedintextType = (direction >0?0:1);// minumum or// maximum?mLastExtremes[extType][k] = mLastValues[k];floatdiff = Math.abs(mLastExtremes[extType][k]- mLastExtremes[1- extType][k]);if(diff > SENSITIVITY) {booleanisAlmostAsLargeAsPrevious = diff > (mLastDiff[k] *2/3);booleanisPreviousLargeEnough = mLastDiff[k] > (diff /3);booleanisNotContra = (mLastMatch !=1- extType);if(isAlmostAsLargeAsPrevious && isPreviousLargeEnough&& isNotContra) {end = System.currentTimeMillis();if(end - start >500) {// 此时判断为走了一步CURRENT_SETP++;mLastMatch = extType;start = end;}}else{mLastMatch = -1;}}mLastDiff[k] = diff;}mLastDirections[k] = direction;mLastValues[k] = v;}}}//当传感器的经度发生变化时就会调用这个方法,在这里没有用publicvoidonAccuracyChanged(Sensor arg0,intarg1) {}}
下来是后台服务StepService的代码:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758packagecom.example.histogram.widet;importandroid.app.Service;importandroid.content.Context;importandroid.content.Intent;importandroid.hardware.Sensor;importandroid.hardware.SensorManager;importandroid.os.IBinder;publicclassStepServiceextendsService {publicstaticBoolean flag =false;privateSensorManager sensorManager;privateStepDetector stepDetector;@OverridepublicIBinder onBind(Intent arg0) {// TODO Auto-generated method stubreturnnull;}@OverridepublicvoidonCreate() {super.onCreate();//这里开启了一个线程,因为后台服务也是在主线程中进行,这样可以安全点,防止主线程阻塞newThread(newRunnable() {publicvoidrun() {startStepDetector();}}).start();}privatevoidstartStepDetector() {flag =true;stepDetector =newStepDetector(this);sensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);//获取传感器管理器的实例Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//获得传感器的类型,这里获得的类型是加速度传感器//此方法用来注册,只有注册过才会生效,参数:SensorEventListener的实例,Sensor的实例,更新速率sensorManager.registerListener(stepDetector, sensor,SensorManager.SENSOR_DELAY_FASTEST);}@OverridepublicintonStartCommand(Intent intent,intflags,intstartId) {returnsuper.onStartCommand(intent, flags, startId);}@OverridepublicvoidonDestroy() {super.onDestroy();flag =false;if(stepDetector !=null) {sensorManager.unregisterListener(stepDetector);}}}
最后把FragmentPedometer测试页面的代码也给大家,如果大家看过之前的博客,应该知道这是一个碎片。如果没看过,看兴趣的朋友可以看看之前的博文:123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144packagecom.example.histogram;importjava.text.SimpleDateFormat;importjava.util.Date;importcom.example.changepage1.R;importcom.example.histogram.widet.CircleBar;importcom.example.histogram.widet.StepDetector;importcom.example.histogram.widet.StepService;importcom.example.histogram.widet.Weather;importandroid.annotation.SuppressLint;importandroid.content.Intent;importandroid.os.Bundle;importandroid.os.Handler;importandroid.os.Message;importandroid.support.v4.app.Fragment;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.view.View.OnClickListener;/*** 这是记步的碎片* Author: 李垭超 email:296777513@qq.com* Date: 2015-1-6* Time: 下午8:39*/publicclassFragmentPedometerextendsFragmentimplementsOnClickListener{privateView view;privateCircleBar circleBar;privateinttotal_step =0;privateThread thread;privateintType =1;privateintcalories =0;privateintstep_length =50;privateintweight =70;privateWeather weather;privateString test;privatebooleanflag =true;// 来判断第三个页面是否开启动画@SuppressLint(HandlerLeak)Handler handler =newHandler() {publicvoidhandleMessage(Message msg) {super.handleMessage(msg);total_step = StepDetector.CURRENT_SETP;if(Type ==1) {circleBar.setProgress(total_step, Type);}elseif(Type ==2) {calories = (int) (weight * total_step * step_length *0.01*0.01);circleBar.setProgress(calories, Type);}elseif(Type ==3) {if(flag) {circleBar.startCustomAnimation();flag =false;}if(test !=null|| weather.getWeather() ==null) {weather.setWeather(正在更新中...);weather.setPtime();weather.setTemp1();weather.setTemp2();circleBar.startCustomAnimation();circleBar.setWeather(weather);}else{circleBar.setWeather(weather);}}}};@OverridepublicView onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {view = inflater.inflate(R.layout.pedometer, container,false);init();mThread();returnview;}privatevoidinit() {Intent intent =newIntent(getActivity(), StepService.class);getActivity().startService(intent);weather =newWeather();circleBar = (CircleBar) view.findViewById(R.id.progress_pedometer);circleBar.setMax(10000);circleBar.setProgress(StepDetector.CURRENT_SETP,1);circleBar.startCustomAnimation();circleBar.setOnClickListener(this);}privatevoidmThread() {if(thread ==null) {thread =newThread(newRunnable() {publicvoidrun() {while(true) {try{Thread.sleep(500);}catch(InterruptedException e) {e.printStackTrace();}if(StepService.flag) {Message msg =newMessage();handler.sendMessage(msg);}}}});thread.start();}}@OverridepublicvoidonClick(View v) {switch(v.getId()) {caseR.id.progress_pedometer:if(Type ==1) {Type =2;}elseif(Type ==2) {flag =true;Type =3;}elseif(Type ==3) {Type =1;}Message msg =newMessage();handler.sendMessage(msg);break;default:break;}}}
原文:http://my.oschina.net/u/1049180/blog/471473
评论(0)
我要投稿