センサー (2) いろいろなセンサー ================================================================================ ■ 各種センサーの値を取得する Android2.2 と DELL の実機で使えるセンサーをすべて確認する。これは、センサー(1) http://blog.goo.ne.jp/marunomarunogoo/d/20110828 の「○」がついているセンサーの値を取得して表示するアプリケーション。 ソースは以下のとおり。 SensorValue01Activity.java 各種センサーの値を表示するアクティビティ・クラス SensorEventListenerAdapter.java TextViewを保持するセンサー・リスナーのアダプタークラス OneDimensionalSensorListenerAdapter.java 1 次元の値を取得するセンサー・リスナーのアダプタークラス ThreeDimensionalSensorListenerAdapter.java 3 次元の値を取得するセンサー・リスナーのアダプタークラス AcceleraterSensorListener.java 加速度センサーリスナー 3 次元値 GyroscopeSensorListener.java ジャイロ・センサー・リスナー 3 次元値 LightSensorListener.java 光センサー・リスナー 1 次元値 MagneticFieldSensorListener.java 地磁気センサー・リスナー 3 次元値 PressureSensorListener.java 圧力センサー・リスナー 1 次元値 ProximitySensorListener.java 近接センサー・リスナー 1 次元値 TemperatureSensorListener.java 温度センサー・リスナー 1 次元値 少し複雑な階層の関係になっているが、基本は、1 次元の値を取得するセンサー系と、3 次元の値を取得するセンサー系に分かれる。これらに対するリスナーのアダプタークラス を用意して、それぞれのセンサー・リスナーは、このアダプター・クラスのサブクラスとし て作る。なお、1次元系と3次元系もほぼ同じ形式になっているので、このスーパークラス SensorEventListenerAdapter を準備する。 ◆ アクティビティのクラス。 □ SensorValue01Activity.java --- package jp.marunomaruno.android.sample; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.hardware.Sensor; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.widget.TextView; /** * Android2.2でサポートされているセンサーの状態を表示する。 * @author marunomaruno * @version 1.0, 2011-06-25 */ public class SensorValue01Activity extends Activity { // TextView private TextView acceleraterTextView; // 加速度センサー // (1) private TextView gravityTextView; // 重力センサー private TextView gyroscopeTextView; // ジャイロスコープセンサー private TextView lightTextView; // 光センサー private TextView linearAccelerationTextView; // 線形加速度センサー private TextView magneticFieldTextView; // 地磁気センサー private TextView pressureTextView; // 圧力センサー private TextView proximityTextView; // 近接センサー private TextView rotationVectorTextView; // 回転ベクトルセンサー private TextView temperatureTextView; // 温度センサー private SensorManager sensorManager; // (2) private List<SensorEventListener> sensorEventListenerList; // onPause()が呼ばれたときに、すべてのリスナーを解除するため // (3) @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); acceleraterTextView = (TextView) findViewById(R.id.accelerater); // (4) gravityTextView = (TextView) findViewById(R.id.gravity); gyroscopeTextView = (TextView) findViewById(R.id.gyroscope); lightTextView = (TextView) findViewById(R.id.light); linearAccelerationTextView = (TextView) findViewById(R.id.linearAcceleration); magneticFieldTextView = (TextView) findViewById(R.id.magneticField); pressureTextView = (TextView) findViewById(R.id.pressure); proximityTextView = (TextView) findViewById(R.id.proximity); rotationVectorTextView = (TextView) findViewById(R.id.rotationVector); temperatureTextView = (TextView) findViewById(R.id.temperature); sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);// (5) sensorEventListenerList = new ArrayList<SensorEventListener>(); // (6) } @Override protected void onResume() { super.onResume(); // 加速度センサーを取得して登録する getSensorAndAddToListener(Sensor.TYPE_ACCELEROMETER, new AcceleraterSensorListener(acceleraterTextView), R.string.accelerater); // (7) // ジャイロスコープ・センサーを取得して登録する getSensorAndAddToListener(Sensor.TYPE_GYROSCOPE, new GyroscopeSensorListener(gyroscopeTextView), R.string.gyroscope); // 光センサーを取得して登録する getSensorAndAddToListener(Sensor.TYPE_LIGHT, new LightSensorListener( lightTextView), R.string.light); // 地磁気センサーを取得して登録する getSensorAndAddToListener(Sensor.TYPE_MAGNETIC_FIELD, new MagneticFieldSensorListener(magneticFieldTextView), R.string.magneticField); // 圧力センサーを取得して登録する getSensorAndAddToListener(Sensor.TYPE_PRESSURE, new PressureSensorListener(pressureTextView), R.string.pressure); // 近接センサーを取得して登録する getSensorAndAddToListener(Sensor.TYPE_PROXIMITY, new ProximitySensorListener(proximityTextView), R.string.proximity); // 温度センサーを取得して登録する getSensorAndAddToListener(Sensor.TYPE_TEMPERATURE, new TemperatureSensorListener(temperatureTextView), R.string.temperature); // Android2.2での未サポートセンサー gravityTextView.setText(String.format( getString(R.string.not_support_format) + "\n", getString(R.string.gravity))); // (8) linearAccelerationTextView.setText(String.format( getString(R.string.not_support_format) + "\n", getString(R.string.linearAcceleration))); rotationVectorTextView.setText(String.format( getString(R.string.not_support_format) + "\n", getString(R.string.rotationVector))); } /** * センサーを取得して、リスナーを設定する。 * @param type センサーのタイプ * @param listener 設定するべきリスナー * @param name センサー名のID */ private void getSensorAndAddToListener(int type, SensorEventListenerAdapter listener, int name) { // (9) List<Sensor> sensors = sensorManager.getSensorList(type); // (10) if (sensors.size() > 0) { sensorEventListenerList.add(listener); // (11) for (Sensor sensor : sensors) { sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL); // (12) } } else { listener.getTextView().setText( String.format(getString(R.string.no_sensor_format) + "\n", getString(name))); // (13) } } @Override public void onPause() { super.onPause(); // すべてのリスナーを解除する for (SensorEventListener listener : sensorEventListenerList) { sensorManager.unregisterListener(listener); // (14) } } } --- (1)(4) 各種センサーから取得した値を表示するためのテキストビューを宣言する。 private TextView acceleraterTextView; // 加速度センサー // (1) acceleraterTextView = (TextView) findViewById(R.id.accelerater); // (4) (2)(5) SensorManager を宣言する。 private SensorManager sensorManager; // (2) sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);// (5) (3)(6)(7)(14) onPause()が呼ばれたときに、すべてのリスナーを解除するために、センサーのリスナーを登録しておくリストを宣言する。 private List<SensorEventListener> sensorEventListenerList; // onPause()が呼ばれたときに、すべてのリスナーを解除するため // (3) sensorEventListenerList = new ArrayList<SensorEventListener>(); // (6) リスナーの解除は、(14) にあるように、SensorManager クラスの unregisterListener( listener) メソッドを使う。 sensorManager.unregisterListener(listener); // (14) (7)、(9)~(13) センサーのデバイスを取得して、そのリスナーと紐付ける getSensorAndAddToListener(Sensor.TYPE_ACCELEROMETER, new AcceleraterSensorListener(acceleraterTextView), R.string.accelerater); // (7) これは、自分で定義したプライベート・メソッドを呼び出す。 メソッドの詳細は、(9)~(13) を参照のこと。 private void getSensorAndAddToListener(int type, SensorEventListenerAdapter listener, int name) { // (9) メソッドの宣言。センサーのタイプ type を受け取り、そのタイプのリスナーをリスト listener に入れて戻す。そのとき、そのセンサーが実機にない場合は、センサー名の ID name を基に、メッセージを出す。 List<Sensor> sensors = sensorManager.getSensorList(type); // (10) センサーのタイプ type を基に、センサーを取得する。引数の type は、センサーの種類 を表す定数で、Sensor クラスに定数が定義されている。 sensorEventListenerList.add(listener); // (11) (10) で取得したセンサーをリストに登録する。このとき、センサーがなければ、リスト には登録しないので、まずはリスナーを登録する。 sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL); // (12) センサーをリスナーに登録する。 getString(name))); // (13) センサーがない場合に、センサー名を取得する。name はりソース ID。 (8) センサーがサポートされていないとき、その旨のメッセージを表示する。 gravityTextView.setText(String.format( getString(R.string.not_support_format) + "\n", getString(R.string.gravity))); // (8) ◆ センサーのリスナーに対するアダプターのクラス。 SensorEventListener インターフェースを実装する。これは、 SensorEventListenerAdapter クラスとするが、実際にはセンサーから取得する値は、1次 元のパターンと3次元のパターンがある。そのため、共通のメンバーを持つスーパークラ ス SensorEventListenerAdapter をつくり、それぞれの次元の値を表示する用のサブクラ スとして、OneDimensionalSensorListenerAdapter クラスと ThreeDimensionalSensorListenerAdapter クラスをつくる。実際のセンサーに対するリス ナー・クラスは、このいずれかのクラスを継承する。 SensorEventListenerAdapter クラスは、インスタンス変数として、センサーから取得し た値を表示するテキスト・ビューを持つ。 また、実装すべきメソッドのうち、onAccuracyChanged() を実装するが、中は何もしてい ない。 □ SensorEventListenerAdapter.java --- package jp.marunomaruno.android.sample; import android.hardware.Sensor; import android.hardware.SensorEventListener; import android.widget.TextView; /** * リスナー用アダプター * @author maruno * @version 1.0, 2011-06-23 * @since 1.0 */ public abstract class SensorEventListenerAdapter implements SensorEventListener { // (1) protected TextView textView; // (2) public SensorEventListenerAdapter(TextView textView) { this.textView = textView; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // (3) assert true; // 何もしない // (4) } public TextView getTextView() { return textView; } } --- (1) センサー・リスナー・インターフェースのアダプター・クラス SensorEventListener インターフェースを実装する。 public abstract class SensorEventListenerAdapter implements SensorEventListener { // (1) (2) 取得した値を表示するためのテキストビュー・オブジェクト protected TextView textView; // (2) (3)、(4) センサーの精度が変わったときのハンドラー・メソッドの実装 メソッドとしては、何もしない。ここでは、何もしないことを明記するため、 assert true; を使っている。 public void onAccuracyChanged(Sensor sensor, int accuracy) { // (3) assert true; // 何もしない // (4) □ OneDimensionalSensorListenerAdapter.java --- package jp.marunomaruno.android.sample; import android.hardware.SensorEvent; import android.widget.TextView; /** * 1次元の値のリスナー用アダプター * @author maruno * @version 1.0, 2011-06-23 * @since 1.0 */ public abstract class OneDimensionalSensorListenerAdapter extends SensorEventListenerAdapter { // (1) public OneDimensionalSensorListenerAdapter(TextView textView) { super(textView); } /** * センサーの値をTextViewに表示する。 * @param event センサー・イベント * @param name センサー名のリソースID * @param unit 単位名のリソースID */ public void out(SensorEvent event, int name, int unit) { // 値を取得する float x = event.values[0]; // (2) // TextViewに表示する textView.setText(String.format( textView.getResources().getString(R.string.sensor_1d_value_format) + "\n", textView.getResources().getString(name), event.sensor.getName(), textView.getResources().getString(unit), event.sensor.getPower(), x )); } } --- (1) 1次元用のアダプター・クラス public abstract class OneDimensionalSensorListenerAdapter extends SensorEventListenerAdapter { // (1) (2) センサーからの値を取得 float x = event.values[0]; // (2) 今回は、1次元の値なので、values[0] のみを取得。 □ ThreeDimensionalSensorListenerAdapter.java --- package jp.marunomaruno.android.sample; import android.hardware.SensorEvent; import android.widget.TextView; /** * 3次元の値のリスナー用アダプター * @author maruno * @version 1.0, 2011-06-23 * @since 1.0 */ public abstract class ThreeDimensionalSensorListenerAdapter extends SensorEventListenerAdapter { // (1) public ThreeDimensionalSensorListenerAdapter(TextView textView) { super(textView); } /** * センサーの値をTextViewに表示する。 * @param event センサー・イベント * @param name センサー名のリソースID * @param unit 単位名のリソースID */ public void out(SensorEvent event, int name, int unit) { // 値を取得する float x = event.values[0]; // (2) float y = event.values[1]; // (3) float z = event.values[2]; // (4) // TextViewに表示する textView.setText(String.format( textView.getResources().getString(R.string.sensor_3d_value_format) + "\n", textView.getResources().getString(name), event.sensor.getName(), textView.getResources().getString(unit), event.sensor.getPower(), x, y, z )); } } --- (1) 3 次元用のアダプター・クラス public abstract class ThreeDimensionalSensorListenerAdapter extends SensorEventListenerAdapter { // (1) (2)~(4) センサーからの値を取得 float x = event.values[0]; // (2) float y = event.values[1]; // (3) float z = event.values[2]; // (4) 今回は、3 次元の値なので、values[0]~values[2] を取得。 ◆ センサーのリスナーのクラス。 それぞれのセンサーに対するリスナーのクラス。 取得する値が 1 次元か、3 次元かによって、OneDimensionalSensorListenerAdapter ク ラスか ThreeDimensionalSensorListenerAdapter クラスを継承する。 □ AcceleraterSensorListener.java --- package jp.marunomaruno.android.sample; import android.hardware.SensorEvent; import android.widget.TextView; /** * 加速度センサーのリスナー * @author maruno * @version 1.0, 2011-06-23 * @since 1.0 */ public class AcceleraterSensorListener extends ThreeDimensionalSensorListenerAdapter { // (1) public AcceleraterSensorListener(TextView textView) { super(textView); } @Override public void onSensorChanged(SensorEvent event) { // (2) out(event, R.string.accelerater, R.string.acceleraterUnit); } } --- (1) 加速度センサーのハンドラー・クラス public class AcceleraterSensorListener extends ThreeDimensionalSensorListenerAdapter { // (1) 3次元値なので、ThreeDimensionalSensorListenerAdapter クラスを継承する。 (2) センサーの値が変化したときに呼ばれるハンドラー・メソッド public void onSensorChanged(SensorEvent event) { // (2) □ GyroscopeSensorListener.java 3次元の値なので、AcceleraterSensorListener.java と同じパターン □ LightSensorListener.java --- package jp.marunomaruno.android.sample; import android.hardware.SensorEvent; import android.widget.TextView; /** * 光センサーのリスナー * @author maruno * @version 1.0, 2011-06-23 * @since 1.0 */ public class LightSensorListener extends OneDimensionalSensorListenerAdapter { public LightSensorListener(TextView textView) { super(textView); } @Override public void onSensorChanged(SensorEvent event) { out(event, R.string.light, R.string.lightUnit); } } --- □ MagneticFieldSensorListener.java 3 次元の値なので、AcceleraterSensorListener.java と同じパターン □ PressureSensorListener.java 1 次元の値なので、LightSensorListener.java と同じパターン □ ProximitySensorListener.java 1 次元の値なので、LightSensorListener.java と同じパターン □ TemperatureSensorListener.java 1 次元の値なので、LightSensorListener.java と同じパターン ■ レイアウト □ res/layout/main.xml --- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/accelerater" android:id="@+id/accelerater" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/gravity" android:id="@+id/gravity" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/gyroscope" android:id="@+id/gyroscope" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/light" android:id="@+id/light" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/magneticField" android:id="@+id/magneticField" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/linearAcceleration" android:id="@+id/linearAcceleration" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/pressure" android:id="@+id/pressure" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/proximity" android:id="@+id/proximity" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/rotationVector" android:id="@+id/rotationVector" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/temperature" android:id="@+id/temperature" /> </LinearLayout> --- ■ 文字列の定数 □ プログラム中での取得 ここに文字列の名前と値を <string name="名前">値</string> というように定義しておくと、プログラムの中では、 R.string.名前 でその文字列のIDを取得できる。 そのIDをつかって、ActivityクラスのgetString()メソッドを使えば、文字列の値を取得 できる。したがって、Activityクラスのサブクラスでは、 getString(R.string.名前) とすれば、名前に対する文字列の値を取得できる。 また、Activityクラスのサブクラスでない場合、たとえば、リスナークラスで使いたいと きは、Resoucesオブジェクトを取得して、その中のgetString()メソッドを使う。 Resoucesオブジェクトは、resディレクトリーをカプセル化したオブジェクトである。 Resoucesオブジェクトの取得は、たとえば、Viewクラスであれば、 getResources() メソッドがある。したがって、 textView.getResources().getString(R.string.名前) で、名前に対する文字列の値を取得できる。 □ res/values/string.xml センサーの名前と合わせて、そのセンサーで取得する値の単位も定義した。 --- <resources> <string name="app_name">SensorValue01</string> <string name="accelerater">加速度</string> <string name="acceleraterUnit">m/s^2</string> <string name="gravity">重力</string> <string name="gravityUnit">m/s^2</string> <string name="gyroscope">ジャイロ</string> <string name="gyroscopeUnit">rad/s</string> <string name="light">光</string> <string name="lightUnit">lux</string> <string name="magneticField">地磁気</string> <string name="magneticFieldUnit">uT</string> <string name="linearAcceleration">線形加速度</string> <string name="linearAccelerationUnit">m/s^2</string> <string name="pressure">圧力</string> <string name="pressureUnit">Pa</string> <string name="proximity">近接</string> <string name="proximityUnit">cm</string> <string name="rotationVector">回転ベクトル</string> <string name="rotationVectorUnit">-</string> <string name="temperature">温度</string> <string name="temperatureUnit">℃</string> <string name="sensor_1d_value_format"> %1$s: %2$s = %5$.2f (%3$s), 消費バッテリー = %4$.6f mA</string> <string name="sensor_3d_value_format"> %1$s: %2$s = (X, Y, Z) = (%5$.2f, %6$.2f, %7$.2f) (%3$s), 消費バッテリー = %4$.6f mA </string> <string name="not_support_format"> Android2.2 では、%s センサーはサポートされていません。</string> <string name="no_sensor_format">%s センサーはありません。</string> </resources> ---
最新の画像[もっと見る]
-
あけましておめでとうございます 11年前
-
今年もよろしくお願いいたします 12年前
-
あけましておめでとうございます 13年前
-
あけましておめでとうございます 16年前
※コメント投稿者のブログIDはブログ作成者のみに通知されます