研究了下传感器,一时兴起做了个小的指南针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;
}
}
}