網上比較流行的計步好多都是用第一中方法寫,是一套算法:
下邊是第一種的代碼,個人感覺準确度不是很好,誤差經常在好幾十往上,但是也還能用:下載下傳位址: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;
}
public void oncreate() {
super.oncreate();
instance = this;
initdata();
initstepdetector();
interval_time = 200;
public int onstartcommand(intent intent, int flags, int startid) {
system.out.println("啟動");
return start_redeliver_intent;
public void ondestroy() {
super.ondestroy();
sensormanager.unregisterlistener(this);
public void onsensorchanged(sensorevent event) {
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)));
public void onaccuracychanged(sensor arg0, int arg1) {
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;