基于Android的计步器(Pedometer)的讲解(四)——后台记步

今天先不说Pedometer(计步器)项目UI方面的了,今天讲一个基于重力加速度的记步功能传感器(Sensor),然后

在后台开启记步。

计步器(Pedometer)整个项目的源代码,感兴趣的朋友可以下载来看看(记得帮小弟在github打个星~)

https://github.com/296777513/pedometer

先上几张效果图:(效果和上一篇讲到的CircleBar非常的相似,因为记步功能在后台)

如图所示,能根据你的一些基本参数,来记步。有一个缺点,因为这个是根据感应加速度来计算是否走一步,所以你在原地晃手机,也会记步,不过正常的走路还是挺准确的。

首先给出StepDetector类的代码:

package com.example.histogram.widet;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

/**
 * 这是一个实现了信号监听的记步的类
 * 这是从谷歌找来的一个记步的算法,看不太懂
 * @author Liyachao Date:2015-1-6
 *
 */
public class StepDetector implements SensorEventListener {

	public static int CURRENT_SETP = 0;
	public static float SENSITIVITY = 10; // SENSITIVITY灵敏度
	private float mLastValues[] = new float[3 * 2];
	private float mScale[] = new float[2];
	private float mYOffset;
	private static long end = 0;
	private static long start = 0;
	/**
	 * 最后加速度方向
	 */
	private float mLastDirections[] = new float[3 * 2];
	private float mLastExtremes[][] = { new float[3 * 2], new float[3 * 2] };
	private float mLastDiff[] = new float[3 * 2];
	private int mLastMatch = -1;

	/**
	 * 传入上下文的构造函数
	 *
	 * @param context
	 */
	public StepDetector(Context context) {
		super();
		int h = 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)));
	}

	//当传感器检测到的数值发生变化时就会调用这个方法
	public void onSensorChanged(SensorEvent event) {
		Sensor sensor = event.sensor;
		synchronized (this) {
			if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

				float vSum = 0;
				for (int i = 0; i < 3; i++) {
					final float v = mYOffset + event.values[i] * mScale[1];
					vSum += v;
				}
				int k = 0;
				float v = vSum / 3;

				float direction = (v > mLastValues[k] ? 1
						: (v < mLastValues[k] ? -1 : 0));
				if (direction == -mLastDirections[k]) {
					// Direction changed
					int extType = (direction > 0 ? 0 : 1); // minumum or
															// maximum?
					mLastExtremes[extType][k] = mLastValues[k];
					float diff = Math.abs(mLastExtremes[extType][k]
							- mLastExtremes[1 - extType][k]);

					if (diff > SENSITIVITY) {
						boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k] * 2 / 3);
						boolean isPreviousLargeEnough = mLastDiff[k] > (diff / 3);
						boolean isNotContra = (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;
			}

		}
	}
	//当传感器的经度发生变化时就会调用这个方法,在这里没有用
	public void onAccuracyChanged(Sensor arg0, int arg1) {

	}

}

下来是后台服务StepService的代码:

package com.example.histogram.widet;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.IBinder;

public class StepService extends Service {
	public static Boolean flag = false;
	private SensorManager sensorManager;
	private StepDetector stepDetector;

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		//这里开启了一个线程,因为后台服务也是在主线程中进行,这样可以安全点,防止主线程阻塞
		new Thread(new Runnable() {
			public void run() {
				startStepDetector();
			}
		}).start();

	}

	private void startStepDetector() {
		flag = true;
		stepDetector = new StepDetector(this);
		sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);//获取传感器管理器的实例
		Sensor sensor = sensorManager
				.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//获得传感器的类型,这里获得的类型是加速度传感器
		//此方法用来注册,只有注册过才会生效,参数:SensorEventListener的实例,Sensor的实例,更新速率
		sensorManager.registerListener(stepDetector, sensor,
				SensorManager.SENSOR_DELAY_FASTEST);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		flag = false;
		if (stepDetector != null) {
			sensorManager.unregisterListener(stepDetector);
		}

	}
}

最后把FragmentPedometer测试页面的代码也给大家,如果大家看过之前的博客,应该知道这是一个碎片。如果没看过,看兴趣的朋友可以看看之前的博文:

package com.example.histogram;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.example.changepage1.R;
import com.example.histogram.widet.CircleBar;
import com.example.histogram.widet.StepDetector;
import com.example.histogram.widet.StepService;
import com.example.histogram.widet.Weather;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;

/**
 * 这是记步的碎片
 * Author: 李垭超   email:[email protected]
 * Date: 2015-1-6
 * Time: 下午8:39
 */
public class FragmentPedometer extends Fragment implements OnClickListener{
	private View view;
	private CircleBar circleBar;
	private int total_step = 0;
	private Thread thread;
	private int Type = 1;
	private int calories = 0;
	private int step_length = 50;
	private int weight = 70;
	private Weather weather;
	private String test;
	private boolean flag = true;// 来判断第三个页面是否开启动画

	@SuppressLint("HandlerLeak")
	Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			total_step = StepDetector.CURRENT_SETP;
			if (Type == 1) {
				circleBar.setProgress(total_step, Type);
			} else if (Type == 2) {
				calories = (int) (weight * total_step * step_length * 0.01 * 0.01);
				circleBar.setProgress(calories, Type);
			} else if (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);
				}

			}

		}

	};

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		view = inflater.inflate(R.layout.pedometer, container, false);
		init();
		mThread();
		return view;
	}
	private void init() {
		Intent intent = new Intent(getActivity(), StepService.class);
		getActivity().startService(intent);
		weather = new Weather();
		circleBar = (CircleBar) view.findViewById(R.id.progress_pedometer);
		circleBar.setMax(10000);
		circleBar.setProgress(StepDetector.CURRENT_SETP, 1);
		circleBar.startCustomAnimation();
		circleBar.setOnClickListener(this);

	}

	private void mThread() {
		if (thread == null) {

			thread = new Thread(new Runnable() {
				public void run() {
					while (true) {
						try {
							Thread.sleep(500);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						if (StepService.flag) {
							Message msg = new Message();
							handler.sendMessage(msg);
						}
					}
				}
			});
			thread.start();
		}
	}
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.progress_pedometer:
			if (Type == 1) {
				Type = 2;
			} else if (Type == 2) {
				flag = true;
				Type = 3;
			} else if (Type == 3) {
				Type = 1;
			}
			Message msg = new Message();
			handler.sendMessage(msg);
			break;
		default:
			break;
		}

	}

}

这些是主要的代码,其他次要的我就不贴出来了,如果想要demo的朋友可以在下面留言,我给你们。

如果大家有什么建议,可以提出来哦。

时间: 2024-10-26 13:07:25

基于Android的计步器(Pedometer)的讲解(四)——后台记步的相关文章

基于Android的计步器(Pedometer)的讲解(五)——跟随界面滑动的指示器

计步器(Pedometer)整个项目的源代码,感兴趣的朋友可以下载来看看(记得帮小弟在github打个星~) https://github.com/296777513/pedometer 今天,说下指示器随着界面滑动,可能这样说不太直观,我先附上几张效果图: 如图所示,中间部分为一个ViewPager(可以滑动的页面),大家可以看到屏幕的顶部,字体下面有一个指示器, 当页面向右滑动时,指示器也会随着界面动态的向右滑动,当页面停在第二个页面时,字体也会变为蓝色. 下来给大家贴出主要的代码: pac

基于Android的计步器(Pedometer)的讲解(三)——CircleBar(圆形进度条)

计步器(Pedometer)整个项目的源代码,感兴趣的朋友可以下载来看看(记得帮小弟在github打个星~) https://github.com/296777513/pedometer 本篇文章讲的demo在这里下载(0分下载): http://download.csdn.net/detail/a296777513/8328461 先给几张效果图: 如上图所示,点击中间的圆圈会依次显示3个不同的页面(信息),而且圆形的进度条是动态增加的,效果还是可以的.然后给出源代码,供大家参考 Circle

基于Android的计步器(Pedometer)的讲解(一)——Fragment页面跳转

首先需要做的是实现几个页面的跳转,既类似微信的点击按钮,切换页面. 话不多说,这是一个简单的页面切换的Demo,先贴几张实现的效果: 图片的底部是5个RadioButton,用来进行页面之间的切换.剩下的部分是一个LinearLayout的布局,用来镶嵌5个Fragment(碎片)的页面. 一共用到5个类:MainActivity.MyAdapter.FragmentHistory.FragmentAnalysis.FragmentPedometer.FragmentPK.FragmentSet

基于Android的计步器(Pedometer)的讲解(二)——柱状图分析

写正文之前,小小的吐槽一下,还有一个月就放假了,作业.考试.还有实习(研一,下半学期课不多,也不想在实验室)的考虑,最近基于hadoop的数据分析马上也要验收了,真的忙的"外焦里嫩"啊!目前定的方向是Android开发,所以想过年来了找一个Android的实习工作,提高一点在真正的项目中的经验. 好了,说了这么多废话,开始进入正题吧. 整个计步器的项目已经上传到github上了,感兴趣的朋友可以去看看(最好能给小弟我打颗星星哦~) https://github.com/29677751

基于Android的计步器(Pedometer)的讲解-序(修改)

今天本来想说listview中的下拉刷新数据的,但是突然想到一些比较好的想法. 用了一天的时间将Pedometer这个项目其中的网络功能.照片和一些逻辑功能做了修改,所以在这里有必要和大家讲一下,以前下载的Pedometer程序可能不能运行了. 计步器(Pedometer)整个项目的源代码,感兴趣的朋友可以下载来看看(记得帮小弟在github打个星~) https://github.com/296777513/pedometer 头像由以前的路径存储变为二进制存储,这样大家可以看到传到网上的头像

基于Android的计步器(Pedometer)的讲解(六)——ListView下拉刷新页面

计步器(Pedometer)整个项目的源代码,最近做了比较大的修改,可能以前下载的不能运行,感兴趣的朋友可以下载来看看(记得帮小弟在github打个星~) https://github.com/296777513/pedometer 今天实现实现的下拉刷新的功能,先上几张效果图: 如图所示,今天就是要实现的这个效果 首先,分析ListView下拉刷新实现方式 1.需要添加顶部下拉加载页面 2.需要监听onScrollListener来判断当前是否显示在listview的最顶部 3.因为顶部下拉加

分享基于Android系统的XMPP即时通讯技术项目实战(仿微信开发架构,自定义控件)

即时通讯技术是 网络技术中的明珠.即时通讯产品改变了人们的生活习惯.经过十几年的发展,即时通讯功能的应用也逐渐从专门软件才能实现的功能逐渐成为标准配置.即时通讯技术的应用不仅仅只是用于社交领域,在大多的协同工作领域,以及需要分布结构的网络通讯领域都是非常重要的.讲师本人在android领域有多年的开发经验,在即时通讯系统方面也有深入的研究.在本课程中,详细讲解了android开发中要解决的一些主要的问题,即时通讯在客户端实现的过程,并手把手的进行操作,方便学习和理解.因为课时的原因,对于一些初级

【转】Android Paint之 setXfermode PorterDuffXfermode 讲解

[置顶] Android Paint之 setXfermode PorterDuffXfermode 讲解 分类: android动效篇2015-04-07 17:23 978人阅读 评论(8) 收藏 举报 setXfermodePorterDuffXfermode图层混合模式android图像混合模式AvoidXfermode 尊重原创,欢迎转载,转载请注明: FROM  GA_studio   http://blog.csdn.net/tianjian4592 前面关于paint的方法讲解里

基于Android平台的i-jetty网站智能农业监控系统

基于android平台i-jetty网站的智能农业监控系统 摘要:传统的监控系统,一般是基于PC的有线通信传输,其有很多不足之处,如功耗较高.布线成本高.难度大,适应性差,可扩展性不强,增加新的通信线路需要再次布线施工,而且维护起来也比较麻烦,一旦线路出问题,需要繁琐的检查.而嵌入式Web监控系统是基于物联网技术,其无线通信技术具有成本低廉.适应性强.扩展性强.信息安全.使用维护简单等优点. 智能农业中,种植大棚是通过大棚内安装温湿度以及光照传感器,来对农作物的环境参数进行实时采集,由Web监控