ステップカウンターはステップ検出器を使用して内部で保持している累計歩数をインクリメントしていると思うので、ステップカウンターのみが実装された端末が存在するかどうかは不明ですが、ステップ検出器のみが実装された端末は存在するかもしれません。そうした端末で歩数計を実装する方法をサンプルにしてみました。
少し長いので、要点部分のみ解説します。全ソースコードはサンプル内のPedometer.javaを参照してください。
// SensorEventListenerを実装 public class PedometerActivity extends Activity implements SensorEventListener, View.OnClickListener, RadioGroup.OnCheckedChangeListener { private float mPrevCount; // ステップカウンターの前回値 private float mCount; // アプリで管理する歩数 @Override public void onSensorChanged(SensorEvent event) { // ステップカウンターとステップ検出器で同じリスナーを共有しているため、 // どちらのイベントであるかを判定し、それぞれ歩数を計上する if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) { if (mPrevCount != 0) { mCount += event.values[0] - mPrevCount; } mPrevCount = event.values[0]; } else { mCount++; } } @Override public void onClick(View v) { if (Integer.valueOf(android.R.drawable.ic_media_pause).equals(tag)) { // 停止ボタンだったらリスナーを解除する resid = android.R.drawable.ic_media_play; onCheckedChanged(mRadioGroup, checkedId); } else { // 再生ボタンだったらリスナーを登録する mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI); } } @Override public void onCheckedChanged(RadioGroup group, int checkedId) { // ラジオボタン切り替えでもリスナー解除する mCount = mPrevCount = 0; mSensorManager.unregisterListener(this); mStartStopButton.setImageResource(android.R.drawable.ic_media_play); mStartStopButton.setTag(android.R.drawable.ic_media_play); } }
前述した通り、ステップカウンターの累計歩数値は1ずつ増えてイベント通知されるとは限らないため、ステップカウンターで歩数を計上する場合、前回の値を覚えておく必要があります。
サンプルでは簡単のためActivityで全て実装していますが、実用的な歩数計を実装する場合、サービスを併用してバックグラウンドでも動作するようにすべきです。また、センサーが搭載されている端末でのみ動作させたいのであれば、「AndroidManifest.xml」に<uses-feature>タグで以下を記載します。
ステップ検出器を用いることで、拍子抜けするほど簡単に歩数計が実装できてしまいます。従来のセンサーを利用して歩数計を実装する場合、加速度センサーを用いるのが良さそうです。
記事「3軸デジタル加速度センサーを使用したフル機能の歩数計の設計」には、加速度センサーを用いた歩数計を実装するための考察が詳しく記載されています。特に、体が上下に移動する加速度のピークを検出するアルゴリズムは、センサーデバイスの異なる複数の端末を同等に扱ったり、端末をどのような体制で保持しながら歩行しているかなども考慮したりすると、複雑なアルゴリズムになりそうです。
こうした複雑なアルゴリズムをステップ検出器は隠蔽(いんぺい)してくれているわけです。さらにステップ検出器は、加速度センサーを駆使した歩数検出よりも高精度で省電力であることが期待できます。
回転ベクターセンサーは、端末の回転を検知するセンサーで、ジャイロスコープと似ています。ジャイロスコープが各軸の回転速度を表すのに対し、回転ベクターセンサーは各軸の回転角を表します。
Android SDKに付属するサンプルが優秀なので、今回はそのサンプルを流用しています。
このサンプルのポイントはOpenGLで立方体を回転させて描画するところなのですが、その回転ベクターを「SensorManager#getRotationMatrixFromVector(...)」メソッドで完全にAPIに任せてしまっているところです。
public void onSensorChanged(SensorEvent event) { SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values); }
センサーから通知されてくる回転角を元に変換マトリックスを計算しなくても良いので、非常に楽にセンサーイベントと3Dグラフィックスを結び付けることができます。
接近センサーは、端末に物体が近づいたことを検出できるセンサーです。通話アプリでは、通話時にデバイスが耳に近づいたことを検知し、誤操作防止と省電力のためにスクリーンロックを行いますが、これにも使用されています。
ほぼ上記のケースで使用されることを想定したセンサーであるため、センサーデバイスの位置はスピーカー付近で固定されています。
写真は上からNexus 5、Galaxy S4、Galaxy Nexusのセンサーの位置です。タブレットであるNexus 7は、このセンサーは実装されていません。
このセンサーを通話アプリ以外で利用するケースは以下のようなシチュエーションが考えられます。
検知される値は、物体との距離で、単位はcmです。
手元の3機種で確認したところ、以下のような値が検出されました。
端末 | 非接近時 | 接近時 |
---|---|---|
Galaxy Nexus | 5.0 | 0.0 |
Galaxy S4 | 8.0 | 0.0 |
Nexus 5 | 5.0003.5 | 0.0 |
ドキュメント上では非接近時と接近時の両方でどのような値が通知されるかは定義されていませんが、上記結果から値が0.0の場合に接近していると判断して良さそうです。
Copyright © ITmedia, Inc. All Rights Reserved.