Androidの端末姿勢監視

このエントリーを Google ブックマーク に追加
Pocket
[`yahoo` not found]

アプリケーション内で端末がどのような姿勢になっているかを取得したいときは端末に内蔵されている下記のセンサーを使います。
  • 加速度センサー:x,y,z方向のそれぞれの重力加速度をセンシングする。
  • 地磁気センサー:x(東西),y(南北),z(天地)方向のそれぞれの地磁気をセンシングする。
上記の二つから得られる6つの値を使い、端末の姿勢を取得します。
複雑な計算が必要になりますが、SensorManagerには計算を行ってくれる便利なメソッドが用意されています。
public class DeviceAttitudeManager implements SensorEventListener {

    private boolean mIsMagSensor;

    private boolean mIsAccSensor;

    private final SensorManager mManager;

    private DeviceAttitude mDeviceAttitude;

    public DeviceAttitudeManager(Context context) {
        mManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
        mDeviceAttitude = new DeviceAttitude();
    }

    public void onResume() {
        // センサの取得
        List<Sensor> sensors = mManager.getSensorList(Sensor.TYPE_ALL);
        for (Sensor sensor : sensors) {
            if (sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                mManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI);
                mIsMagSensor = true;
            }
            if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                mManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI);
                mIsAccSensor = true;
            }
        }
    }

    public void onPause() {
        //センサーマネージャのリスナ登録破棄
        if (mIsMagSensor || mIsAccSensor) {
            mManager.unregisterListener(this);
            mIsMagSensor = false;
            mIsAccSensor = false;
        }
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
            return;
        }
        switch (event.sensor.getType()) {
            case Sensor.TYPE_MAGNETIC_FIELD:
                mDeviceAttitude.setMagneticValues(event.values.clone());
            break;
            case Sensor.TYPE_ACCELEROMETER:
                mDeviceAttitude.setAccelerometerValues(event.values.clone());
            break;
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    public DeviceAttitude getDeviceAttitude() {
        return mDeviceAttitude;
    }

    static public class DeviceAttitude {

        private static final int MATRIX_SIZE = 16;

        /**
        * 傾斜角
        */
        private int mPitch;

        /**
        * 回転角
        */
        private int mRoll;

        /**
        * 方位角
        */
        private int mAzimuth;

        /* 回転行列 */
        float[] inR = new float[MATRIX_SIZE];
        float[] outR = new float[MATRIX_SIZE];
        float[] I = new float[MATRIX_SIZE];

        /* センサーの値 */
        float[] orientationValues = new float[3];
        float[] magneticValues = new float[3];
        float[] accelerometerValues = new float[3];

        public int getPitch() {
            return mPitch;
        }

        public int getRoll() {
            return mRoll;
        }

        public int getAzimuth() {
            return mAzimuth;
        }

        public void setMagneticValues(float[] magneticValues) {
            this.magneticValues = magneticValues;
            updateAttitude();
        }

        public void setAccelerometerValues(float[] accelerometerValues) {
            this.accelerometerValues = accelerometerValues;
            updateAttitude();
        }

        private void updateAttitude() {
            if (magneticValues != null &amp;&amp; accelerometerValues != null) {
                SensorManager.getRotationMatrix(inR, I, accelerometerValues, magneticValues);
                SensorManager.remapCoordinateSystem(inR, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR);
                SensorManager.getOrientation(outR, orientationValues);
                mPitch = radianToDegree(orientationValues[1]);
                mRoll = radianToDegree(orientationValues[2]);
                mAzimuth = radianToDegree(orientationValues[0]);
                if (mAzimuth < 0) {
                    mAzimuth += 360;
                }
            }
        }

        int radianToDegree(float rad) {
            return (int) Math.floor(Math.toDegrees(rad));
        }
    }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)