文章目录

  • 概述
    • getOrientation 方法根据 旋转矩阵R 获取 设备旋转弧度
    • getRotationMatrix 方法根据 地磁场、加速度传感器对象 获取 旋转矩阵R
  • 代码
  • 参考资料

概述

Sensor.TYPE_ORIENTATION 常数在 API 8 中已弃用,官方推荐使用 SensorManager.getOrientation() 替代。关于 Orientation Sensor(被弃用的方向传感器) 在官方文档中的概述里有这样一句话:

The orientation sensor is software-based and derives its data from the accelerometer and the geomagnetic field sensor. (方向传感器是基于软件的,并且它的数据是通过加速度传感器和磁场传感器共同获得的)

上面的描述其实少了一个重要角色,即 SensorManager.getOrientation()方向传感器 在被弃用之前,正是通过 SensorManager.getOrientation() 来借助 加速度传感器(Sensor.TYPE_ACCELEROMETER)地磁场传感器(TYPE_MAGNETIC_FIELD) 的数据得到的。


getOrientation 方法根据 旋转矩阵R 获取 设备旋转弧度

官方文档中,对于 getOrientation 方法的介绍如下:

该函数有两个参数,Rvalues。传入时 R 有具体值而 values 是空的,然后在方法内部根据 旋转矩阵R 计算设备的方向,将结果存储在 values 中:

  • values[0] 记录着手机围绕 Z 轴的旋转弧度
  • values[1] 记录着手机围绕 X 轴的旋转弧度
  • values[2] 记录着手机围绕 Y 轴的旋转弧度

而后可以通过 Math.toDegrees() 方法将旋转弧度转化为角度。

但是这里还有个问题,旋转矩阵R 的值从何而来呢?事实上,其值通过我们之前提到 加速度传感器(Sensor.TYPE_ACCELEROMETER)地磁场传感器(TYPE_MAGNETIC_FIELD) 的获得。

首先通过 SensorEvent 对象获得两个传感器对象 Sensor ,一个是 加速度传感器,另一个是 地磁场传感器

public void onSensorChanged(SensorEvent event) {// SensorEvent:保存精度(accuracy)、传感器类型(sensor)、时间戳(timestamp)// 以及不同传感器(Sensor)具有的不同传感器数组(values)。SensorManager.getOrientation(r, values);// TYPE_MAGNETIC_FIELD:描述磁场传感器类型的常量。if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {geomagnetic = event.values; // 地磁场传感器对象}// TYPE_ACCELEROMETER:描述加速度传感器类型的常量。if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {gravity = event.values; // 加速度传感器对象}
}

getRotationMatrix 方法根据 地磁场、加速度传感器对象 获取 旋转矩阵R

之后通过这两个对象结合 SensorManager.getRotationMatrix() 方法获取 旋转矩阵R 的具体值。官方文档中,对于 getRotationMatrix 方法的介绍如下:

该函数有四个参数,通过计算 gravitygeomagnetic 得到 旋转矩阵R。(第二个参数 倾斜矩阵I 用于将磁场数据转换进实际的重力坐标系中,一般默认设置为NULL即可。)


代码

/** 方向传感器 */
public class MyOrientationListener implements SensorEventListener {private static final String TAG = "WeatherActivity";private final Context context;private SensorManager sensorManager;private Sensor magneticSensor, accelerometerSensor;private float[] gravity = new float[3];private float[] geomagnetic= new float[3];private OnOrientationListener onOrientationListener;  //内部接口实现回调private double lastX;/** 当有新的传感器事件时(手机方向改变时调用)调用。 */@Overridepublic void onSensorChanged(SensorEvent event) {Log.e(TAG, "onSensorChanged 开始");// SensorEvent:保存精度(accuracy)、传感器类型(sensor)、时间戳(timestamp)// 以及不同传感器(Sensor)具有的不同传感器数组(values)。// TYPE_MAGNETIC_FIELD:描述磁场传感器类型的常量。if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {geomagnetic = event.values;Log.e(TAG, "onSensorChanged 得到磁场传感器: " + Arrays.toString(geomagnetic));}// TYPE_ACCELEROMETER:描述加速度传感器类型的常量。if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {gravity = event.values;Log.e(TAG, "onSensorChanged 得到加速度传感器: " + Arrays.toString(gravity));}getValue();}/** 当注册传感器的精度发生变化时调用。 */@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}/** 通过加速度和磁场变化获取方向变化的信息 */public void getValue() {//初始化数组float[] values = new float[3]; // 用来保存手机的旋转弧度float[] r = new float[9]; // 被填充的旋转矩阵// 传入gravity和geomagnetic,通过计算它们得到旋转矩阵R。// 而第二个参数倾斜矩阵I是用于将磁场数据转换进实际的重力坐标系中的,一般默认设置为NULL即可。SensorManager.getRotationMatrix(r, null, gravity, geomagnetic);// 根据旋转矩阵R计算设备的方向,将结果存储在values中。// values[0]记录着手机围绕 Z 轴的旋转弧度,// values[1]记录着手机围绕 X 轴的旋转弧度,// values[2]记录着手机围绕 Y 轴的旋转弧度。SensorManager.getOrientation(r, values);Log.e(TAG, "getValue R: " + Arrays.toString(r));Log.e(TAG, "getValue values: " + Arrays.toString(values));// 旋转弧度转为角度float pitch = (float) Math.toDegrees(values[0]);Log.e(TAG, "getValue pitch: "+ pitch);if (Math.abs(lastX) > 1.0) { // 设置条件防止频繁回调onOrientationListener.onOrientationChanged(pitch);}lastX = pitch;}public interface  OnOrientationListener{void onOrientationChanged(float x);}public void setOnOrientationListener(OnOrientationListener onOrientationListener){this.onOrientationListener = onOrientationListener;Log.e(TAG, "setOnOrientationListener: 接口设置完成");}public MyOrientationListener(Context context){this.context=context;}public void onStart(){sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);if (sensorManager != null) { // 初始化两个传感器// getDefaultSensor:获取Sensor,使用给定的类型和唤醒属性返回传感器。magneticSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);}if (magneticSensor != null) {assert sensorManager != null;sensorManager.registerListener(this, magneticSensor,SensorManager.SENSOR_DELAY_UI);}if (accelerometerSensor != null) {assert sensorManager != null;sensorManager.registerListener(this, accelerometerSensor,SensorManager.SENSOR_DELAY_UI);}}public void onStop(){sensorManager.unregisterListener(this); // 传感器解除绑定}
}

参考资料

传感器的相关知识讲的很详细

Android之传感器(三)方向传感器

Android | Sensor.TYPE_ORIENTATION被废弃后的解决办法相关推荐

  1. 抱歉,进程android.process.media,已停止运行的解决办法

    android模似器4.03下载了QQ,搜狗拼音后,双击提示:抱歉,进程android.process.media,已停止运行的解决办法 去到下载内容图标,找到你已经下载的软件(注:可以安装的软件的图 ...

  2. Eclipse之Android项目名有红感叹号的解决办法

    问题: Eclipse之Android项目名有红感叹号的解决办法 代码都没有错,然后项目有红感叹号 1.找问题原因 点击项目右键,然后点击Build Path,然后再Configure Buil Pa ...

  3. 桌面的回收站或IE图标不见后的解决办法

    在平时使用电脑的过程中,我们都会碰到桌面的回收站或IE图标不见的现象,影响我们的使用,下面我们就来说说碰到这种情况后的解决方法. 1.回收站图标不见后的解决办法: 我在网上找了,有各种各样的方法,但是 ...

  4. 雷蛇Razer鼠标固件升级失败后的解决办法

    雷蛇Razer鼠标固件升级失败后的解决办法 背景:昨天一同事说在家闲得蛋疼,刷鼠标固件.他的是炼狱蝰蛇套装的,结果把鼠标刷成砖头了.他把鼠标拿给我,让我给试试能不能刷回来. 过程: 接在电脑上没有任何 ...

  5. android edittext字数显示不全,Android的EditText字数检测和限制解决办法

    Android的EditText字数检测和限制解决办法 控件EditText在Android布局中经常用到,对EditText中输入的内容也经常需要进行限制,我们可以通过TextWatcher去观察输 ...

  6. Android Studio之Instant Run requires ‘Tools | Android | Enable ADB integration‘ to be enabled解决办法

    1.问题 Android studio运行项目时候出现这个提示 Instant Run requires 'Tools | Android | Enable ADB integration' to b ...

  7. Android SDK Manager更新不了的解决办法

    android SDK Manager更新不了,出现错误提示:"Failed to fetch URL..."! 可以用以下办法解决: 使用SDK Manager更新时出现问题 F ...

  8. android开发中遇到的技术难题,android开发过程中遇到的问题以及解决办法

    ####编译的时候遇到的问题: "android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original th ...

  9. Android 更新版本 应用程序未安装 解决办法

    问题描述 在做Android应用版本更新时遇到一个问题,在原始的版本中进行升级,下载了新版的app后安装时,手机报"应用未安装",升级失败. 如下图所示: 分析原因 主要有两个方面 ...

  10. Android编译出现FAILED: setup-jack-server问题的解决办法

    在编译Android的时候出现了如下错误: [ 28% 1127/3932] Ensuring Jack server is installed and started FAILED: setup-j ...

最新文章

  1. Ethereal使用入门
  2. 巧用FTP命令进行文件传输
  3. 简单的基于hash和hashchange的前端路由
  4. 【LeetCode从零单排】No27.Remove Element
  5. 大神TP_英雄联盟:男枪瞬秒大龙,佐伊遍地TP,新版本BUG谁来监管?
  6. CentOS7.4 搭建ngrok 内网穿透
  7. 如果从SVN到GIT
  8. android记事本项目案例,Android实现记事本项目完整实例源代码
  9. 《大数据》专题征文:国产环境下的大数据处理系统
  10. 林肯android auto,林肯mkz仪表盘怎么设置中文
  11. 初学者-C语言基础练习(二)——C语言编译器的使用方法
  12. 自动控制原理知识点梳理——1. 自动控制的一般概念 2. 控制系统的数学模型
  13. 洛菲创意字体设计分享--绿斗堂字体网
  14. 基于 EMD 和小波包的降噪方法研究
  15. 短视频“音频化”,音乐“视频化”
  16. UBUNTU下安装热键驱动及触摸板禁用驱动
  17. 生活记录:突然“醒来”
  18. mysql escape python_Python 操作 MYSQL
  19. Bootrap 项目实战(微金所前端首页)第一部分
  20. java 中showinfo方法,jmockito模拟方法中参数如何指定

热门文章

  1. 砸蛋程序php,基于JQuery+PHP编写砸金蛋中奖程序
  2. 朱晔的互联网架构实践心得S1E5:不断耕耘的基础中间件
  3. python+基于Python的资产管理系统 毕业设计-附源码201117
  4. openGPS.cn - 高精度IP定位原理,定位误差说明
  5. B-JUI表单验证规则总结
  6. windows7副本不是正版解决方法
  7. Pandas学习——文本数据
  8. java 实现matlab spline_关于MATLAB中spline函数
  9. 平面向量内积坐标公式推导_平面向量的所有公式-平面向量公式
  10. python实现乘法口诀表