Android——学习计步器心得(一)

<span style="white-space: pre;">
</span><span style="color:#ff0000;">自己研究加上网上查资料基本上能实现加速器记步功能,下来把代码贴上。
</span>
<span style="color:#ff0000;">第一个包是后台服务Service</span>
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;


 //service负责后台的需要长期运行的任务
 // 计步器服务
 // 运行在后台的服务程序,完成了界面部分的开发后
 // 就可以开发后台的服务类StepService
 // 注册或注销传感器监听器,在手机屏幕状态栏显示通知,与StepActivity进行通信,走过的步数记到哪里了
public class StepService extends Service {

	public static Boolean FLAG = false;// 服务运行标志

	private SensorManager mSensorManager;// 传感器服务
	private StepDetector detector;// 传感器监听对象

	private PowerManager mPowerManager;// 电源管理服务
	private WakeLock mWakeLock;// 屏幕灯

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

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();

		FLAG = true;// 标记为服务正在运行

		// 创建监听器类,实例化监听对象
		detector = new StepDetector(this);

		// 获取传感器的服务,初始化传感器
		mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
		// 注册传感器,注册监听器
		mSensorManager.registerListener(detector,
				mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_FASTEST);

		// 电源管理服务
		mPowerManager = (PowerManager) this
				.getSystemService(Context.POWER_SERVICE);
		mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
				| PowerManager.ACQUIRE_CAUSES_WAKEUP, "Jackie");
		mWakeLock.acquire();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		FLAG = false;// 服务停止
		if (detector != null) {
			mSensorManager.unregisterListener(detector);
		}

		if (mWakeLock != null) {
			mWakeLock.release();
		}
	}

}
<span style="color:#ff0000;">然后是计算步数的算法,这段代码是从github上截取下来的。</span>
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;

//走步检测器,用于检测走步并计数
/**
 * 具体算法不太清楚。
 * 
 */
public class StepDetector implements SensorEventListener {

	public static int CURRENT_SETP = 0;

	public static float SENSITIVITY = 0; // 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) {
		// TODO Auto-generated constructor stub
		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)));
	
		SENSITIVITY = 10;
	}


	@Override
	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) {// 此时判断为走了一步
									Log.i("StepDetector", "CURRENT_SETP:"
											+ CURRENT_SETP);
									CURRENT_SETP++;
									mLastMatch = extType;
									start = end;
								}
							} else {
								mLastMatch = -1;
							}
						}
						mLastDiff[k] = diff;
					}
					mLastDirections[k] = direction;
					mLastValues[k] = v;
				}
			
		}
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		// TODO Auto-generated method stub
	}

}
<span style="color:#ff0000;">最后一个是实现记步和卡路里计算的Activity</span>
import java.text.DecimalFormat;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
	private TextView tv_show_step;// 步数
	private TextView tv_calories;// 卡路里
	private Button btn_start;// 开始按钮
	private Button btn_stop;// 停止按钮
	private Double distance = 0.0;// 路程:米
	private Double calories = 0.0;// 热量:卡路里
	private int step_length = 0; // 步长
	private int weight = 0; // 体重
	private int total_step = 0; // 走的总步数
	private Thread thread; // 定义线程对象

	Handler handler = new Handler() {
		public void handleMessage(Message msg) {

			super.handleMessage(msg); // 此处可以更新UI

			countDistance(); // 调用距离方法,看一下走了多远

			if (distance != 0.0) {

				// 体重、距离
				// 跑步热量(kcal)=体重(kg)×距离(公里)×1.036
				calories = weight * distance * 0.01;
			} else {
				calories = 0.0;
			}

			countStep(); // 调用步数方法

			tv_show_step.setText(total_step + "");// 显示当前步数
			tv_calories.setText(formatDouble(calories));// 显示卡路里
		}

	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		if (thread == null) {

			thread = new Thread() {// 子线程用于监听当前步数的变化

				@Override
				public void run() {
					// TODO Auto-generated method stub
					super.run();
					int temp = 0;
					while (true) {
						try {
							Thread.sleep(300);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						if (StepService.flag) {
							Message msg = new Message();
							if (temp != StepDetector.CURRENT_SETP) {
								temp = StepDetector.CURRENT_SETP;
							}
							handler.sendMessage(msg);
						}
					}
				}
			};
			thread.start();
		}
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		tv_calories = (TextView) findViewById(R.id.calories);
		tv_show_step = (TextView) findViewById(R.id.step);
		btn_start = (Button) findViewById(R.id.button1);
		btn_stop = (Button) findViewById(R.id.button2);

		step_length = 50;
		weight = 65;

		countDistance();
		countStep();
		if (distance != 0.0) {
			calories = weight * distance * 0.001;
		} else {
			calories = 0.0;
		}

		tv_calories.setText(formatDouble(calories));

		tv_show_step.setText(total_step + "");

		btn_start.setEnabled(!StepService.flag);
		btn_stop.setEnabled(StepService.flag);

		if (StepService.flag) {
			btn_stop.setText("停止");
		} else if (StepDetector.CURRENT_SETP > 0) {
			btn_stop.setEnabled(true);
			btn_stop.setText("暂停");
		}

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	private CharSequence formatDouble(Double doubles) {
		DecimalFormat format = new DecimalFormat("####.##");
		String distanceStr = format.format(doubles);
		return distanceStr.equals("0") ? "0.0" : distanceStr;

	}

	public void onClick(View view) {
		Intent service = new Intent(this, StepService.class);
		switch (view.getId()) {
		case R.id.button1:
			startService(service);
			btn_start.setEnabled(false);
			btn_stop.setEnabled(true);
			btn_stop.setText("暂停");
			break;

		case R.id.button2:
			stopService(service);
			if (StepService.flag && StepDetector.CURRENT_SETP > 0) {
				btn_stop.setText("清零");
			} else {
				StepDetector.CURRENT_SETP = 0;
				btn_stop.setText("暂停");
				btn_stop.setEnabled(false);
				tv_show_step.setText("0");
				tv_calories.setText(formatDouble(0.0));
				// tv_velocity.setText(formatDouble(0.0));

				handler.removeCallbacks(thread);
			}
			btn_start.setEnabled(true);
			break;

		}
	}

	private void countStep() {
		if (StepDetector.CURRENT_SETP % 2 == 0) {
			total_step = StepDetector.CURRENT_SETP / 2 * 3;
		} else {
			total_step = StepDetector.CURRENT_SETP / 2 * 3 + 1;
		}

	}

	private void countDistance() {
		if (StepDetector.CURRENT_SETP % 2 == 0) {
			distance = (StepDetector.CURRENT_SETP / 2) * 3 * step_length * 0.01;
		} else {
			distance = ((StepDetector.CURRENT_SETP / 2) * 3 + 1) * step_length
					* 0.01;
		}

	}

}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值