国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android實現計步傳感器功能

2019-10-22 18:16:01
字體:
來源:轉載
供稿:網友

本文對原文:android實現計步功能初探,計步項目進行了精簡,移除了進程服務和計時、守護進程、數據庫保存等等,方便擴展功能。

本文源碼:https://github.com/lifegh/StepOrient

Android4.4以上版本,有些手機有計步傳感器可以直接使用,
而有些手機沒有,但有加速度傳感器,也可以實現計步功能(需要計算加速度波峰波谷來判斷人走一步)!

Android,計步,傳感器

一.調用

public class MainActivity extends AppCompatActivity implements StepSensorBase.StepCallBack{  .........  @Override  public void Step(int stepNum) {    // 計步回調    stepText.setText("步數:" + stepNum);  }  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);       setContentView(R.layout.activity_main);    stepText = (TextView) findViewById(R.id.step_text);    // 開啟計步監聽, 分為加速度傳感器、或計步傳感器    stepSensor = new StepSensorPedometer(this, this);    if (!stepSensor.registerStep()) {      Toast.makeText(this, "計步傳傳感器不可用!", Toast.LENGTH_SHORT).show();      stepSensor = new StepSensorAcceleration(this, this);      if (!stepSensor.registerStep()) {        Toast.makeText(this, "加速度傳感器不可用!", Toast.LENGTH_SHORT).show();      }    }  }  ....... } /** * 計步傳感器抽象類,子類分為加速度傳感器、或計步傳感器 */public abstract class StepSensorBase implements SensorEventListener {  private Context context;  protected StepCallBack stepCallBack;  protected SensorManager sensorManager;  protected static int CURRENT_SETP = 0;  protected boolean isAvailable = false;  public StepSensorBase(Context context, StepCallBack stepCallBack) {    this.context = context;    this.stepCallBack = stepCallBack;  }  public interface StepCallBack {    /**     * 計步回調     */    void Step(int stepNum);  }  /**   * 開啟計步   */  public boolean registerStep() {    if (sensorManager != null) {      sensorManager.unregisterListener(this);      sensorManager = null;    }    sensorManager = SensorUtil.getInstance().getSensorManager(context);    registerStepListener();    return isAvailable;  }  /**   * 注冊計步監聽器   */  protected abstract void registerStepListener();  /**   * 注銷計步監聽器   */  public abstract void unregisterStep();}

二.直接使用計步傳感器實現計步

/** * 計步傳感器 */public class StepSensorPedometer extends StepSensorBase {  private final String TAG = "StepSensorPedometer";  private int lastStep = -1;  private int liveStep = 0;  private int increment = 0;  private int sensorMode = 0; // 計步傳感器類型  public StepSensorPedometer(Context context, StepCallBack stepCallBack) {    super(context, stepCallBack);  }  @Override  protected void registerStepListener() {    Sensor detectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);    Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);    if (sensorManager.registerListener(this, detectorSensor, SensorManager.SENSOR_DELAY_GAME)) {      isAvailable = true;      sensorMode = 0;      Log.i(TAG, "計步傳感器Detector可用!");    } else if (sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_GAME)) {      isAvailable = true;      sensorMode = 1;      Log.i(TAG, "計步傳感器Counter可用!");    } else {      isAvailable = false;      Log.i(TAG, "計步傳感器不可用!");    }  }  @Override  public void unregisterStep() {    sensorManager.unregisterListener(this);  }  @Override  public void onSensorChanged(SensorEvent event) {    liveStep = (int) event.values[0];    if (sensorMode == 0) {      Log.i(TAG, "Detector步數:"+liveStep);      StepSensorBase.CURRENT_SETP += liveStep;    } else if (sensorMode == 1) {      Log.i(TAG, "Counter步數:"+liveStep);      StepSensorBase.CURRENT_SETP = liveStep;    }    stepCallBack.Step(StepSensorBase.CURRENT_SETP);  }  @Override  public void onAccuracyChanged(Sensor sensor, int accuracy) {  }}

三.使用加速度傳感器實現計步

/** * 加速度傳感器 */public class StepSensorAcceleration extends StepSensorBase {  private final String TAG = "StepSensorAcceleration";  //存放三軸數據  final int valueNum = 5;  //用于存放計算閾值的波峰波谷差值  float[] tempValue = new float[valueNum];  int tempCount = 0;  //是否上升的標志位  boolean isDirectionUp = false;  //持續上升次數  int continueUpCount = 0;  //上一點的持續上升的次數,為了記錄波峰的上升次數  int continueUpFormerCount = 0;  //上一點的狀態,上升還是下降  boolean lastStatus = false;  //波峰值  float peakOfWave = 0;  //波谷值  float valleyOfWave = 0;  //此次波峰的時間  long timeOfThisPeak = 0;  //上次波峰的時間  long timeOfLastPeak = 0;  //當前的時間  long timeOfNow = 0;  //當前傳感器的值  float gravityNew = 0;  //上次傳感器的值  float gravityOld = 0;  //動態閾值需要動態的數據,這個值用于這些動態數據的閾值  final float initialValue = (float) 1.7;  //初始閾值  float ThreadValue = (float) 2.0;  //初始范圍  float minValue = 11f;  float maxValue = 19.6f;  /**   * 0-準備計時  1-計時中 2-正常計步中   */  private int CountTimeState = 0;  public static int TEMP_STEP = 0;  private int lastStep = -1;  //用x、y、z軸三個維度算出的平均值  public static float average = 0;  private Timer timer;  // 倒計時3.5秒,3.5秒內不會顯示計步,用于屏蔽細微波動  private long duration = 3500;  private TimeCount time;  public StepSensorAcceleration(Context context, StepCallBack stepCallBack) {    super(context, stepCallBack);  }  @Override  protected void registerStepListener() {    // 注冊加速度傳感器    isAvailable = sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),        SensorManager.SENSOR_DELAY_GAME);    if (isAvailable) {      Log.i(TAG, "加速度傳感器可用!");    } else {      Log.i(TAG, "加速度傳感器不可用!");    }  }  @Override  public void unregisterStep() {    sensorManager.unregisterListener(this);  }  public void onAccuracyChanged(Sensor arg0, int arg1) {  }  public void onSensorChanged(SensorEvent event) {    Sensor sensor = event.sensor;    synchronized (this) {      if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {        calc_step(event);      }    }  }  synchronized private void calc_step(SensorEvent event) {    average = (float) Math.sqrt(Math.pow(event.values[0], 2)        + Math.pow(event.values[1], 2) + Math.pow(event.values[2], 2));    detectorNewStep(average);  }  /*   * 檢測步子,并開始計步   * 1.傳入sersor中的數據   * 2.如果檢測到了波峰,并且符合時間差以及閾值的條件,則判定為1步   * 3.符合時間差條件,波峰波谷差值大于initialValue,則將該差值納入閾值的計算中   * */  public void detectorNewStep(float values) {    if (gravityOld == 0) {      gravityOld = values;    } else {      if (DetectorPeak(values, gravityOld)) {        timeOfLastPeak = timeOfThisPeak;        timeOfNow = System.currentTimeMillis();        if (timeOfNow - timeOfLastPeak >= 200            && (peakOfWave - valleyOfWave >= ThreadValue) && (timeOfNow - timeOfLastPeak) <= 2000) {          timeOfThisPeak = timeOfNow;          //更新界面的處理,不涉及到算法          preStep();        }        if (timeOfNow - timeOfLastPeak >= 200            && (peakOfWave - valleyOfWave >= initialValue)) {          timeOfThisPeak = timeOfNow;          ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);        }      }    }    gravityOld = values;  }  private void preStep() {//    if (CountTimeState == 0) {//      // 開啟計時器//      time = new TimeCount(duration, 700);//      time.start();//      CountTimeState = 1;//      Log.v(TAG, "開啟計時器");//    } else if (CountTimeState == 1) {//      TEMP_STEP++;//      Log.v(TAG, "計步中 TEMP_STEP:" + TEMP_STEP);//    } else if (CountTimeState == 2) {    StepSensorBase.CURRENT_SETP++;//      if (stepCallBack != null) {    stepCallBack.Step(StepSensorBase.CURRENT_SETP);//      }//    }  }  /*   * 檢測波峰   * 以下四個條件判斷為波峰:   * 1.目前點為下降的趨勢:isDirectionUp為false   * 2.之前的點為上升的趨勢:lastStatus為true   * 3.到波峰為止,持續上升大于等于2次   * 4.波峰值大于1.2g,小于2g   * 記錄波谷值   * 1.觀察波形圖,可以發現在出現步子的地方,波谷的下一個就是波峰,有比較明顯的特征以及差值   * 2.所以要記錄每次的波谷值,為了和下次的波峰做對比   * */  public boolean DetectorPeak(float newValue, float oldValue) {    lastStatus = isDirectionUp;    if (newValue >= oldValue) {      isDirectionUp = true;      continueUpCount++;    } else {      continueUpFormerCount = continueUpCount;      continueUpCount = 0;      isDirectionUp = false;    }//    Log.v(TAG, "oldValue:" + oldValue);    if (!isDirectionUp && lastStatus        && (continueUpFormerCount >= 2 && (oldValue >= minValue && oldValue < maxValue))) {      peakOfWave = oldValue;      return true;    } else if (!lastStatus && isDirectionUp) {      valleyOfWave = oldValue;      return false;    } else {      return false;    }  }  /*   * 閾值的計算   * 1.通過波峰波谷的差值計算閾值   * 2.記錄4個值,存入tempValue[]數組中   * 3.在將數組傳入函數averageValue中計算閾值   * */  public float Peak_Valley_Thread(float value) {    float tempThread = ThreadValue;    if (tempCount < valueNum) {      tempValue[tempCount] = value;      tempCount++;    } else {      tempThread = averageValue(tempValue, valueNum);      for (int i = 1; i < valueNum; i++) {        tempValue[i - 1] = tempValue[i];      }      tempValue[valueNum - 1] = value;    }    return tempThread;  }  /*   * 梯度化閾值   * 1.計算數組的均值   * 2.通過均值將閾值梯度化在一個范圍里   * */  public float averageValue(float value[], int n) {    float ave = 0;    for (int i = 0; i < n; i++) {      ave += value[i];    }    ave = ave / valueNum;    if (ave >= 8) {//      Log.v(TAG, "超過8");      ave = (float) 4.3;    } else if (ave >= 7 && ave < 8) {//      Log.v(TAG, "7-8");      ave = (float) 3.3;    } else if (ave >= 4 && ave < 7) {//      Log.v(TAG, "4-7");      ave = (float) 2.3;    } else if (ave >= 3 && ave < 4) {//      Log.v(TAG, "3-4");      ave = (float) 2.0;    } else {//      Log.v(TAG, "else");      ave = (float) 1.7;    }    return ave;  }  class TimeCount extends CountDownTimer {    public TimeCount(long millisInFuture, long countDownInterval) {      super(millisInFuture, countDownInterval);    }    @Override    public void onFinish() {      // 如果計時器正常結束,則開始計步      time.cancel();      StepSensorBase.CURRENT_SETP += TEMP_STEP;      lastStep = -1;      Log.v(TAG, "計時正常結束");      timer = new Timer(true);      TimerTask task = new TimerTask() {        public void run() {          if (lastStep == StepSensorBase.CURRENT_SETP) {            timer.cancel();            CountTimeState = 0;            lastStep = -1;            TEMP_STEP = 0;            Log.v(TAG, "停止計步:" + StepSensorBase.CURRENT_SETP);          } else {            lastStep = StepSensorBase.CURRENT_SETP;          }        }      };      timer.schedule(task, 0, 2000);      CountTimeState = 2;    }    @Override    public void onTick(long millisUntilFinished) {      if (lastStep == TEMP_STEP) {        Log.v(TAG, "onTick 計時停止:" + TEMP_STEP);        time.cancel();        CountTimeState = 0;        lastStep = -1;        TEMP_STEP = 0;      } else {        lastStep = TEMP_STEP;      }    }  }}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 德保县| 安多县| 略阳县| 新干县| 新乡市| 左权县| 威远县| 邮箱| 镶黄旗| 扎囊县| 改则县| 盐津县| 获嘉县| 赤城县| 西安市| 泰兴市| 张家川| 京山县| 涞源县| 吉林市| 宝兴县| 靖州| 仪征市| 玉林市| 绍兴县| 台前县| 红原县| 金湖县| 扶余县| 子长县| 海口市| 永修县| 朔州市| 皮山县| 光山县| 湛江市| 苍溪县| 通海县| 玉龙| 阿图什市| 长兴县|