AndroidのTYPE_STEP_COUNTER/TYPE_STEP_DETECTORセンサーの使い方

歩数計などに使えるTYPE_STEP_COUNTER/TYPE_STEP_DETECTORセンサーの使い方をまとめました。

 

1 SensorListenerを利用する

SensorManagerでSensorの取得し、SensorListenerを登録します。

センサーの値が変化すると、登録したSensorListenerのonSensorChangedメソッドが呼ばれます。

onSensorChangedメソッドの引数eventのvaluesにセンサの値が、timestampにタイムスタンプが格納されています。

1.1 TYPE_STEP_DETECTORセンサーでonSensorChangedの回数を表示するコード

以下ではTYPE_STEP_DETECTORセンサーが実行された回数を端末振動時に表示します。

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

  SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
  Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
  sensorManager.registerListener(new SensorEventListener() {
    private int mCounter = 0;
    @Override
    public void onSensorChanged(SensorEvent event) {
      Log.i("TYPE_STEP_DETECTOR", "" + mCounter++);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
  }, sensor, SensorManager.SENSOR_DELAY_UI);
}

SensorEventのメンバvaluesは常に1となるので、変数で回数を記録する必要があります。

TYPE_STEP_DETECTOR: 0
TYPE_STEP_DETECTOR: 1
TYPE_STEP_DETECTOR: 2

1.2 TYPE_STEP_COUNTERセンサーの値を表示するコード

以下ではTYPE_STEP_COUNTERセンサーの値を端末振動時に表示します。

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

  SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
  Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
  sensorManager.registerListener(new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
      Log.i("TYPE_STEP_COUNTER", "" + (int) event.values[0]);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
  }, sensor, SensorManager.SENSOR_DELAY_UI);
}

SensorEventのメンバvaluesに振動の回数が記録されています。

TYPE_STEP_COUNTER: 241
TYPE_STEP_COUNTER: 242
TYPE_STEP_COUNTER: 243

2 留意点

実装上の留意点を記載します。

2.1 TYPE_STEP_COUNTERの値は起動時に0クリアされる

TYPE_STEP_COUNTERは端末起動時に0クリアされる為、アプリケーション起動時に値が0から始まるとは限りません。

 

アプリケーションで0から始まる値が必要な場合は、イベントリスナが最初に呼ばれる時にTYPE_STEP_COUNTERの初期値を保存する必要があります。

あるいは初期値を取得するイベントリスナと初期値を利用するイベントリスナを作成し、前者のイベントリスナ実行時に前者イベントリスナの削除と後者のイベントリスナ登録をするようなトリッキーな処理が必要です。

2.2 TYPE_STEP_COUNTERの値はregisterListener後に更新されるようになる

端末依存かもしれませんが、TYPE_STEP_COUNTERの値はregisterListener実行後に更新されるようになります。

 

周期タイマーでregisterListenerとunregisterListenerを実行し、定期的にTYPE_STEP_COUNTERの値を取得するようなワンショットイベントを実装すればば消費電力を少なくできそうですが、registerListener実行後にのみTYPE_STEP_COUNTERの値が更新されるので、unregisterListener以降の歩数がカウントされません。

 

REPORTING_MODE_ON_CHANGEはregisterListenerのみ使用できると記述されおり、ワンショットイベント実装にTriggerEventListenerを使用できません。

2.3 onSensorChangedメソッドは起動時間がある

端末依存かもしれませんが、端末を振動させてもonSensorChangedメソッドはしばらく動かず、1秒ほど経ってからonSensorChangedが初めて呼び出されるようです。

 

動き出してからはSensorManager.SENSOR_DELAY_UI等の精度で動作します。さらに振動を止めてから1秒ほど待つと、再度起動時間が必要になります。

TYPE_STEP_COUNTER: 241
TYPE_STEP_COUNTER: 242
TYPE_STEP_COUNTER: 243
/** Stop shaking and wait. And then start shaking. */
TYPE_STEP_COUNTER: 246
TYPE_STEP_COUNTER: 247
TYPE_STEP_COUNTER: 248

上のログはisWakeUpSensorメソッドがfalseのTYPE_STEP_COUNTERを利用しています。

上のログでは243の時に振動を止めて1秒待ち、再度降り出すと1秒後に246と表示されています。

onSensorChangedメソッドは止まっていてもTYPE_STEP_COUNTERの値は更新されているようです。

 

Non-wake-up sensorでも起動時間があるということを留意して、アプリケーションを設計する必要があります。