Android:端末の傾きと方位を、センサーを利用して取得する

地磁気センサーと加速度センサーを組み合わせることで、Android端末の傾き、方位を取得することが出来ます。

傾き、方位の取得方法

コピー&ペーストで使用出来るソースコードを用意しました。

アプリ起動時にresume()メソッド、終了時にpause()メソッドを実行してください。

pause()メソッドを実行せずにアプリ終了すると、登録したリスナーが参照されたままとなり、メモリリークが発生する恐れがあります。

端末の傾きはX軸方向がgetPitch()、Y軸方向がgetRoll()、Z軸方向(方位)がgetAzimuth()メソッドでそれぞれ取得出来ます。

値の範囲はそれぞれ0~359、方位については「0度:北、90度:東、180度:南、270度:西」となっています。

※ソースコードはダブルクリックで全選択出来ます。また使用する際は必要に応じて改修して頂いて構いません。

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;

/**
 * 回転角度取得クラス
 *
 * @author
 *
 */
public class OrientationListener implements SensorEventListener {
    /** デバッグ用 */
    private static final boolean DEBUG = true;
    private static final String TAG = "OrientationListener";
    /** 行列数 */
    private static final int MATRIX_SIZE = 16;
    /** 三次元(XYZ) */
    private static final int DIMENSION = 3;
    /** センサー管理クラス */
    private SensorManager mManager;
    /** 地磁気行列 */
    private float[] mMagneticValues;
    /** 加速度行列 */
    private float[] mAccelerometerValues;
    /** X軸の回転角度 */
    private int mPitchX;
    /** Y軸の回転角度 */
    private int mRollY;
    /** Z軸の回転角度(方位角) */
    private int mAzimuthZ;

    /**
     * センサーイベント取得開始
     *
     * @param context
     *            コンテキスト
     */
    public synchronized void resume(Context context) {
        if (context == null) {
            // 引数不正
            return;
        }
        // 登録済なら一旦止める
        pause();
        if (mManager == null) {
            // 初回実行時
            mManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        }
        // 地磁気センサー登録
        mManager.registerListener(this, mManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI);
        // 加速度センサー登録
        mManager.registerListener(this, mManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
    }

    /**
     * センサーイベント取得終了
     */
    public synchronized void pause() {
        if (mManager != null) {
            mManager.unregisterListener(this);
        }
    }

    /**
     * X軸の回転角度を取得する
     *
     * @return X軸の回転角度
     */
    public synchronized int getPitch() {
        return mPitchX;
    }

    /**
     * Y軸の回転角度を取得する
     *
     * @return Y軸の回転角度
     */
    public synchronized int getRoll() {
        return mRollY;
    }

    /**
     * Z軸の回転角度(方位角)を取得する
     *
     * @return Z軸の回転角度
     */
    public synchronized int getAzimuth() {
        return mAzimuthZ;
    }

    /**
     * ラジアンを角度に変換する
     *
     * @param angrad
     *            ラジアン
     * @return 角度
     */
    private int radianToDegrees(float angrad) {
		return (int) Math.floor(angrad > = 0 ? Math.toDegrees(angrad) : 360 + Math.toDegrees(angrad));
	}

    @Override
    public synchronized void onAccuracyChanged(Sensor sensor, int accuracy) {
        // 処理なし
    }

    @Override
    public synchronized void onSensorChanged(SensorEvent event) {
        // センサーイベント
        switch (event.sensor.getType()) {
        case Sensor.TYPE_MAGNETIC_FIELD:
            // 地磁気センサー
            mMagneticValues = event.values.clone();
            break;
        case Sensor.TYPE_ACCELEROMETER:
            // 加速度センサー
            mAccelerometerValues = event.values.clone();
            break;
        default:
            // それ以外は無視
            return;
        }
        if (mMagneticValues != null && mAccelerometerValues != null) {
            float[] rotationMatrix = new float[MATRIX_SIZE];
            float[] inclinationMatrix = new float[MATRIX_SIZE];
            float[] remapedMatrix = new float[MATRIX_SIZE];
            float[] orientationValues = new float[DIMENSION];
            // 加速度センサーと地磁気センサーから回転行列を取得
            SensorManager.getRotationMatrix(rotationMatrix, inclinationMatrix, mAccelerometerValues, mMagneticValues);
            SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, remapedMatrix);
            SensorManager.getOrientation(remapedMatrix, orientationValues);
            // ラジアン値を変換し、それぞれの回転角度を取得する
            mAzimuthZ = radianToDegrees(orientationValues[0]);
            mPitchX = radianToDegrees(orientationValues[1]);
            mRollY = radianToDegrees(orientationValues[2]);
            if (DEBUG) {
                Log.d(TAG, "X=" + mPitchX + "Y=" + mRollY + "Z=" + mAzimuthZ);
            }
        }
    }
}

傾きセンサー(Sensor.TYPE_ORIENTATION)は使用するべきではありません。

なお、Androidには傾きセンサー(Sensor.TYPE_ORIENTATION)の実装もされていますが、これはレガシー(古くなった)な実装であるため、使用するべきではありません。

端末によっては想定通りの値が取得出来ないことがあるようですので、注意してください。

スポンサーリンク


コメントを残す

このページの先頭へ