研究了下傳感器,一時興起做了個小的指南針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;
}
}
}