實現指南針的新方法SensorManager.getOrientation( )

研究了下傳感器,一時興起做了個小的指南針APP,網上講的比較多的方法:

1、註冊一個針對方位傳感器的事件監聽器;

        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

Sensor compassSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);

mSensorManager.registerListener(this, compassSensor, SensorManager.SENSOR_DELAY_NORMAL);

2、得到傳感器事件的values[0],作爲手機頭部朝向的方位角,從而得到相對正北的角度(順時針)

@Override
    public void onSensorChanged(SensorEvent event) {
                // 獲取繞Z軸轉過的角度
                float degree = event.values[0];
                System.out.println("方位角=" + degree);

但是其實谷歌官方已經在API 8 開始就已經棄用了Sensor.TYPE_ORIENTATION這種方式,轉而推薦使用SensorManager.getOrientation( )的方式來獲取到方位、橫滾、俯仰值。

我看了看API文檔,試着用新方法實現了,肉眼對比了一下,大概和舊方法獲取的方位值有不到1度的誤差,也可以使用了。

不多說,關鍵代碼如下,大家一看便知。

public class CompassActivity extends Activity implements SensorEventListener {

    private static final String TAG = "CompassActivity";
    //記錄rotationMatrix矩陣值
    private float[] r = new float[9];
    //記錄通過getOrientation()計算出來的方位橫滾俯仰值
    private float[] values = new float[3];
    private float[] gravity = null;
    private float[] geomagnetic = null;
    // 定義真機的Sensor管理器
    private SensorManager mSensorManager;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if(gravity!=null && geomagnetic!=null) {
                if(SensorManager.getRotationMatrix(r, null, gravity, geomagnetic)) {
                    SensorManager.getOrientation(r, values);
                    float degree = (float) ((360f+values[0]*180f/Math.PI)%360);
                    Log.i(TAG, "計算出來的方位角=" + degree);
                }
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_compass);
        // 獲取真機的傳感器管理服務
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    }

    @Override
    protected void onResume() {
        super.onResume();
        //註冊加速度傳感器監聽
        Sensor acceleSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorManager.registerListener(this, acceleSensor, SensorManager.SENSOR_DELAY_NORMAL);
        //註冊磁場傳感器監聽
        Sensor magSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        mSensorManager.registerListener(this, magSensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 取消所有註冊
        mSensorManager.unregisterListener(this);
    }

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

    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        switch (event.sensor.getType()) {
            case Sensor.TYPE_ACCELEROMETER: //加速度傳感器
                gravity = event.values;
                handler.sendEmptyMessage(0);
                break;
            case Sensor.TYPE_MAGNETIC_FIELD://磁場傳感器
                geomagnetic = event.values;
                handler.sendEmptyMessage(0);
                break;
        }
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章