网上比较流行的计步好多都是用第一中方法写,是一套算法:
下边是第一种的代码,个人感觉准确度不是很好,误差经常在好几十往上,但是也还能用:下载地址:http://download.csdn.net/detail/u012808234/8539079
package com.example.pedometerdemo;
import java.util.List;
import java.util.Timer;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import android.util.Log;
public class pedometerService extends Service implements SensorEventListener {
public static final String STEP_CHANGE = "step_change";
public static final String ADD_STEPS = "add_Step";
private static final int notifiId = 11;
private Intent intent;
private ActivityManager activityManager;
private SensorManager sensorManager;
private Timer timer = new Timer();
private long lastTime;// 上次记步的时间
private float mLimit = 6.44f;
private int interval_time;
private float mLastValues[] = new float[3 * 2];
private float mScale[] = new float[2];
private float mYOffset;
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;
private int startStep;
private Service instance;
private float[] xyz=new float[3];
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
instance = this;
initData();
initStepDetector();
interval_time = 200;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
System.out.println("启动");
return START_REDELIVER_INTENT;
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
sensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
Sensor sensor = event.sensor;
synchronized (this) {
if (System.currentTimeMillis() - lastTime < interval_time) {
return;
}
if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
} else {
int j = (sensor.getType() == Sensor.TYPE_ACCELEROMETER) ? 1 : 0;
if (j == 1) {
float vSum = 0;
for (int i = 0; i < 3; i++) {
final float v = mYOffset + event.values[i] * mScale[j];
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 > mLimit) {
boolean isAlmostAsLargeAsPrevious = diff > (mLastDiff[k] * 2 / 3);
boolean isPreviousLargeEnough = mLastDiff[k] > (diff / 3);
boolean isNotContra = (mLastMatch != 1 - extType);
if (isAlmostAsLargeAsPrevious && isPreviousLargeEnough && isNotContra) {
long currentTime = System.currentTimeMillis();
if (currentTime - lastTime > 2000) {
startStep = 0;
} else {
Log.e("STEP", startStep+++"");
}
mLastMatch = extType;
lastTime = currentTime;
} else {
mLastMatch = -1;
}
}
mLastDiff[k] = diff;
}
mLastDirections[k] = direction;
mLastValues[k] = v;
}
}
}
}
private boolean appIsTop() {
if (activityManager == null) {
activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
}
List<RunningTaskInfo> rti = activityManager.getRunningTasks(1);
String packagename = rti.get(0).topActivity.getPackageName();
if (packagename.equals(getPackageName())) {
return true;
}
return false;
}
public void initStepDetector() {
int h = 480; // TODO: remove this constant
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)));
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
private void initData() {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
if (sensorManager != null) {// 注册监听器
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST);
// 第一个参数是Listener,第二个参数是所得传感器类型,第三个参数值获取传感器信息的频率
}
}
}
还有第二种,我觉得是误差小点的,自己测试了下,不管别的情况的,就是正常走路的误差在10步左右:看看代码,他是封成了好几个方法,上最主要的逻辑代码:
下载地址:http://download.csdn.net/detail/u012808234/8539095
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.simplepedometer;
/**
* Receives sensor updates and alerts a StepListener when a step has been detected.
*/
public class SimpleStepDetector {
private static final int ACCEL_RING_SIZE = 50;
private static final int VEL_RING_SIZE = 10;
private static final float STEP_THRESHOLD = 4f;
private static final int STEP_DELAY_NS = 250000000;
private int accelRingCounter = 0;
private float[] accelRingX = new float[ACCEL_RING_SIZE];
private float[] accelRingY = new float[ACCEL_RING_SIZE];
private float[] accelRingZ = new float[ACCEL_RING_SIZE];
private int velRingCounter = 0;
private float[] velRing = new float[VEL_RING_SIZE];
private long lastStepTimeNs = 0;
private float oldVelocityEstimate = 0;
private StepListener listener;
public void registerListener(StepListener listener) {
this.listener = listener;
}
/**
* Accepts updates from the accelerometer.
*/
public void updateAccel(long timeNs, float x, float y, float z) {
float[] currentAccel = new float[3];
currentAccel[0] = x;
currentAccel[1] = y;
currentAccel[2] = z;
// First step is to update our guess of where the global z vector is.
accelRingCounter++;
accelRingX[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[0];
accelRingY[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[1];
accelRingZ[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[2];
float[] worldZ = new float[3];
worldZ[0] = SensorFusionMath.sum(accelRingX) / Math.min(accelRingCounter, ACCEL_RING_SIZE);
worldZ[1] = SensorFusionMath.sum(accelRingY) / Math.min(accelRingCounter, ACCEL_RING_SIZE);
worldZ[2] = SensorFusionMath.sum(accelRingZ) / Math.min(accelRingCounter, ACCEL_RING_SIZE);
float normalization_factor = SensorFusionMath.norm(worldZ);
worldZ[0] = worldZ[0] / normalization_factor;
worldZ[1] = worldZ[1] / normalization_factor;
worldZ[2] = worldZ[2] / normalization_factor;
// Next step is to figure out the component of the current acceleration
// in the direction of world_z and subtract gravity's contribution
float currentZ = SensorFusionMath.dot(worldZ, currentAccel) - normalization_factor;
velRingCounter++;
velRing[velRingCounter % VEL_RING_SIZE] = currentZ;
float velocityEstimate = SensorFusionMath.sum(velRing);
if (velocityEstimate > STEP_THRESHOLD && oldVelocityEstimate <= STEP_THRESHOLD
&& (timeNs - lastStepTimeNs > STEP_DELAY_NS)) {
listener.step(timeNs);
lastStepTimeNs = timeNs;
}
oldVelocityEstimate = velocityEstimate;
}
}