天天看點

計步器源代碼實作的倆種方式

網上比較流行的計步好多都是用第一中方法寫,是一套算法:

下邊是第一種的代碼,個人感覺準确度不是很好,誤差經常在好幾十往上,但是也還能用:下載下傳位址: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;