方向传感器
16lz
2021-01-26
- 可以使用与光照传感器类似的方法:
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
- 但 Android 早就废弃了 Sensor.TYPE_ORIENTATION 这种传感器类型,不再推荐这样写了。
- 事实上,Android 获取手机旋转的方向和角度是通过加速度传感器和地磁传感器共同计算得出的。
一、方向传感器的用法
1. 获取 SensorManager 实例。
SensorManager senserManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
2. 通过 getDefaultSensor() 得到加速度传感器和地磁传感器的实例。
Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
3. 借助 SensorEventListener 对传感器输出的信号进行监听。
SensorEventListener listener = new SensorEventListener() { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { }};
4. 调用 SensorManager 的 registerListener() 方法来注册SensorEventListener 使其生效。
sensorManager.registerListener(listener, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_GAME);
- 由于方向传感器的精确度要求通常都比较高,这里把传感器输出信息的更新速率提高了一些,使用的是 SENSOR_DELAY_GAME。
5. 在 onSensorChanged() 方法中可以获取到 SensorEvent 的 values 数组,分别记录着加速度传感器和地磁传感器输出的值。然后将这两个值传入到 SensorManager 的 getRotationMatrix() 方法中就可以得到一个包含旋转矩阵的 R 数组。
SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);
- 第一个参数:R 是一个长度为 9 的 float 数组,getRotationMatrix() 方法计算出的旋转数据就会赋值到这个数组当中。
- 第二个参数:用于将地磁向量转换成重力坐标的旋转矩阵,通常指定为 null 即可。
- 第三个参数:加速度传感器输出的 values 值。
- 第四个参数:地磁传感器输出的 values 值。
6. 调用 SensorManager 的 getOrientation() 方法来计算手机的旋转数据。
SensorManager.getOrientation(R, values);
- values 是一个长度为 3 的 float 数组,手机在各个方向上的旋转数据都会被存放到这个数组当中。
- values[0] 记录着手机围绕** Z 轴**的旋转弧度。
- values[1] 记录着手机围绕** X 轴**的旋转弧度。
- values[2] 记录着手机围绕 Y 轴的旋转弧度。
7. 将弧度转换为角度。
Math.toDegrees(values[0]);
8. 最后调用 unregisterListener() 方法将使用的资源释放掉。
sensorManager.unregisterListener(listener);
二、制作简易指南针
public class MainActivity extends Activity { private SensorManager sensorManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); Sensor accelerometerSensor = sensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER); sensorManager.registerListener(listener, magneticSensor, SensorManager.SENSOR_DELAY_GAME); sensorManager.registerListener(listener, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME); } @Override protected void onDestroy() { super.onDestroy(); if (sensorManager != null) { sensorManager.unregisterListener(listener); } } private SensorEventListener listener = new SensorEventListener() { float[] accelerometerValues = new float[3]; float[] magneticValues = new float[3]; @Override public void onSensorChanged(SensorEvent event) { // 判断当前是加速度传感器还是地磁传感器 if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { // 注意赋值时要调用clone()方法 accelerometerValues = event.values.clone(); } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { // 注意赋值时要调用clone()方法 magneticValues = event.values.clone(); } float[] R = new float[9]; float[] values = new float[3]; SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues); SensorManager.getOrientation(R, values); Log.d("MainActivity", "value[0] is " + Math.toDegrees(values[0])); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } };}
- 注意在赋值的时候一定要调用一下 values 数组的 **clone() **方法,不
然 accelerometerValues 和 magneticValues 将会指向同一个引用。
更多相关文章
- 8、android代码优化技术记录
- Android(安卓)adapter适配器的使用
- laravel使用Dingo\Api通过response()->json()返回空对象
- Android(安卓)传感器(Sensor)API教程 (二) 传感器事件
- android中的适配器
- android 绘制虚线和虚线圆
- 利用OpenGL ES、手机传感器、相机和调用百度语音包服务,实现AR+语
- 热修复
- Android:ArrayAdapter 与 entries的使用