方位情報の取得
〜 Android Studio の使い方 7 〜
2023-05-05 作成 福島
TOP > androidstudio > compus

使用ツール

    Android Studio Flamingo | 2022.2.1 Patch 2  


1. アクティビティにテキストボックスを配置する。

activity_main にテキストボックスを配置する。(方位・傾き情報をこのテキストボックスに表示する)
要素名内容備考
アクティビティ/ app/ res/ layout/ activity_main.xml-
部品種類TextView-
idtextViewプログラムから R.id.textView として参照される。


2. 方位取得の実装

このコードは、Android デベロッパーガイドにある位置センサーの項で推奨している計算方法に従っています。

プログラムを分かりやすくするため、アプリの開始・停止処理を使っていません。(それでも分かりにくい)

アプリをリリースするときは開始・停止処理 (onResume, onPause 等) を使ってください。
(そうしないと、プロセスがバックグラウンドになっても停止しないので、無駄に電力を消費する)

2-1. センサーイベントリスナを追加する。
クラス MainActivity (MainActivity.java) に以下を記述する。
public class MainActivity extends AppCompatActivity {

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


if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return; // 加速度計・磁力計センサをリスナ登録できるのは KITKAT(API19) 以降 SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); OnSensorEventListener onSensorEventListener = new OnSensorEventListener(); // 加速度計のリスナを登録 Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if(accelerometer != null) { sensorManager.registerListener(onSensorEventListener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); } // 磁力計 (方位) のリスナを登録 Sensor magneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); if(magneticField != null) { sensorManager.registerListener(onSensorEventListener, magneticField, SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI); }
}
private final float[] accelerometerReading = new float[3]; // 加速度計の値を保持 // センサーイベントリスナを定義 private class OnSensorEventListener implements SensorEventListener { @Override public void onSensorChanged(SensorEvent sensorEvent) { final float[] magnetometerReading = new float[3]; // 磁力計の値 int sensorType = sensorEvent.sensor.getType(); switch(sensorType) { case Sensor.TYPE_ACCELEROMETER: // 加速度計 System.arraycopy(sensorEvent.values, 0, accelerometerReading, 0, accelerometerReading.length); break; case Sensor.TYPE_MAGNETIC_FIELD: // 磁力計 System.arraycopy(sensorEvent.values, 0, magnetometerReading, 0, magnetometerReading.length); break; } if(sensorType == Sensor.TYPE_MAGNETIC_FIELD) { // 加速度計の値(デバイス座標系) → ワールド座標系の変換 float[] rotationMatrix = new float[9]; SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading); // スマホの向き (方位角・前後角・左右角) を計算する float[] orientationAngles = new float[3]; SensorManager.getOrientation(rotationMatrix, orientationAngles); // ラジアン → ディグリー 変換 float fYaw = rad2deg(orientationAngles[0]); float fPitch = rad2deg(orientationAngles[1]); float fRoll = rad2deg(orientationAngles[2]); @SuppressLint("DefaultLocale") // リテラルに日本語を直接記述した警告を抑止 String msg = "方位: " + String.format(" %6.1f°\n", deg360(fYaw)) // 0 - 360° + "前後: " + String.format("+%6.1f°\n", fPitch) // -180 - +180° + "左右: " + String.format("+%6.1f°\n", fRoll); // -180 - +180° ((TextView) findViewById(R.id.textView)).setText(msg); } } @Override public void onAccuracyChanged(Sensor sensor, int i) { // センサーの精度が変更されたときの処理 // 今回はすることが無いが、省略できない } } // ラジアンをディグリーに変換 (-180°~ +180°) private float rad2deg(float rad) { return (float) (rad * 180.0 / Math.PI); } // -180°~ +180°の角度を 0°~ 360°の角度に変換 private float deg360(float deg) { return (float) ((deg + 360.0) % 360.0); }
}