連載
» 2014年06月26日 18時00分 公開

Android WearやIoTで注目のAndroidセンサー機能8選Androidで動く携帯Javaアプリ作成入門(52)(2/3 ページ)

[緒方聡,株式会社イーフロー]

歩数計のサンプル

 ステップカウンターはステップ検出器を使用して内部で保持している累計歩数をインクリメントしていると思うので、ステップカウンターのみが実装された端末が存在するかどうかは不明ですが、ステップ検出器のみが実装された端末は存在するかもしれません。そうした端末で歩数計を実装する方法をサンプルにしてみました。

図4 歩数計のサンプル

 少し長いので、要点部分のみ解説します。全ソースコードはサンプル内の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);
    }
}
Pedometer.javaより抜粋

 前述した通り、ステップカウンターの累計歩数値は1ずつ増えてイベント通知されるとは限らないため、ステップカウンターで歩数を計上する場合、前回の値を覚えておく必要があります。

 サンプルでは簡単のためActivityで全て実装していますが、実用的な歩数計を実装する場合、サービスを併用してバックグラウンドでも動作するようにすべきです。また、センサーが搭載されている端末でのみ動作させたいのであれば、「AndroidManifest.xml」に<uses-feature>タグで以下を記載します。

  • FEATURE_SENSOR_STEP_COUNTER
  • FEATURE_SENSOR_STEP_DETECTOR

コラム「歩数計のアルゴリズム」

 ステップ検出器を用いることで、拍子抜けするほど簡単に歩数計が実装できてしまいます。従来のセンサーを利用して歩数計を実装する場合、加速度センサーを用いるのが良さそうです。

 記事「3軸デジタル加速度センサーを使用したフル機能の歩数計の設計」には、加速度センサーを用いた歩数計を実装するための考察が詳しく記載されています。特に、体が上下に移動する加速度のピークを検出するアルゴリズムは、センサーデバイスの異なる複数の端末を同等に扱ったり、端末をどのような体制で保持しながら歩行しているかなども考慮したりすると、複雑なアルゴリズムになりそうです。

 こうした複雑なアルゴリズムをステップ検出器は隠蔽(いんぺい)してくれているわけです。さらにステップ検出器は、加速度センサーを駆使した歩数検出よりも高精度で省電力であることが期待できます。


端末の回転を検知する「回転ベクターセンサー」

 回転ベクターセンサーは、端末の回転を検知するセンサーで、ジャイロスコープと似ています。ジャイロスコープが各軸の回転速度を表すのに対し、回転ベクターセンサーは各軸の回転角を表します。

 Android SDKに付属するサンプルが優秀なので、今回はそのサンプルを流用しています。

図5 回転ベクターセンサー

 このサンプルのポイントはOpenGLで立方体を回転させて描画するところなのですが、その回転ベクターを「SensorManager#getRotationMatrixFromVector(...)」メソッドで完全にAPIに任せてしまっているところです。

    public void onSensorChanged(SensorEvent event) {
        SensorManager.getRotationMatrixFromVector(mRotationMatrix,
                event.values);
    }

 センサーから通知されてくる回転角を元に変換マトリックスを計算しなくても良いので、非常に楽にセンサーイベントと3Dグラフィックスを結び付けることができます。

端末に物体が近づいたことを検出できる「接近センサー」

 接近センサーは、端末に物体が近づいたことを検出できるセンサーです。通話アプリでは、通話時にデバイスが耳に近づいたことを検知し、誤操作防止と省電力のためにスクリーンロックを行いますが、これにも使用されています。

 ほぼ上記のケースで使用されることを想定したセンサーであるため、センサーデバイスの位置はスピーカー付近で固定されています。

図6 接近センサーの位置

 写真は上からNexus 5、Galaxy S4、Galaxy Nexusのセンサーの位置です。タブレットであるNexus 7は、このセンサーは実装されていません。

 このセンサーを通話アプリ以外で利用するケースは以下のようなシチュエーションが考えられます。

  • VoIPなどの音声通話アプリでの利用
  • カバーと連動させてスクリーンロックを行うアプリ
  • ポケットやかばんに入れたことを検知してスクリーンロックを行うアプリ

 検知される値は、物体との距離で、単位はcmです。

図7 接近センサー

 手元の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.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。