Android 传感器篇:(一)方向传感器
从这篇文章开始,主要记录android 传感器相关的知识:
这是这个系列的第一篇,主要讲解android 主要的传感器,以及方向传感器详解。
一:传感器基础
官网上我们看到,android中涉及的传感器主要有
1:Motion sensors
这些传感器沿三个轴测量加速力和旋转力。此类别包括加速度计,重力传感器,陀螺仪和旋转矢量传感器。
2:Position sensors
这些传感器测量各种环境参数,例如环境空气温度和压力,照明和湿度。此类别包括气压计,光度计和温度计。
3:Environment sensrs
这些传感器测量设备的物理位置。此类别包括方向传感器和磁力计。
下面这个截图是android平台支持的传感器类型。
传感器部分主要用到几个类: 1:sensor 2:sensorManager 3:SensorEvent 4:SensorEventListener
我们先通过sensorManger获取下android设备支持的sensor列表,同时熟悉下对应的方法。
第一步:获取传感器管理对象。
manager= (SensorManager) getSystemService(SENSOR_SERVICE);
第二步:获取所有支持的sensor
// 得到设备支持的所有传感器的ListsensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
第三步:编写adapter,展示。这里展示的sensor的name属性。
这里我是在模拟器运行的。4.4的设备,所以支持的较少。
二:方向传感器
这一部分具体介绍传感器的方向传感器。
具体对应的就是
我们通过TYPE_ORIENTATION来获取方向传感器对象,具体获取方法如下:
//获取传感器管理对象manager= (SensorManager) getSystemService(SENSOR_SERVICE);//获取方向传感器orientationSensor=manager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
获取到对象后,我们需要在onresume()方法中注册监听事件,在onpause()中解除监听。
protected void onResume() {super.onResume();if (orientationSensor!=null){//三个参数分别是SensorEventListener,sensor,速率manager.registerListener(this,orientationSensor,SensorManager.SENSOR_DELAY_NORMAL);}}@Overrideprotected void onPause() {super.onPause();if (manager!=null){manager.unregisterListener(this);}}
注册监听时第三个参数指的是延迟时间:有四种类型
/** get sensor data as fast as possible */public static final int SENSOR_DELAY_FASTEST = 0;/** rate suitable for games */public static final int SENSOR_DELAY_GAME = 1;/** rate suitable for the user interface */public static final int SENSOR_DELAY_UI = 2;/** rate (default) suitable for screen orientation changes */public static final int SENSOR_DELAY_NORMAL = 3;
查看源码,我们可以得到每个类型对应的延迟时间。
private static int getDelay(int rate) {int delay = -1;switch (rate) {case SENSOR_DELAY_FASTEST:delay = 0;break;case SENSOR_DELAY_GAME:delay = 20000;break;case SENSOR_DELAY_UI:delay = 66667;break;case SENSOR_DELAY_NORMAL:delay = 200000;break;default:delay = rate;break;}return delay;}
具体的数据在SensorEventListener的返回方法中,下面是对应的方法。
根据SensorEvent.values获取返回的数据,我们可以看到返回的是一个数组。
//当有新的传感器事件时调用 @Overridepublic void onSensorChanged(SensorEvent event) {float[] values = event.values;StringBuilder sb=new StringBuilder();sb.append("z轴:"+values[0]+"\n");sb.append("x轴:"+values[1]+"\n");sb.append("y轴:"+values[2]+"\n");binding.tvValue.setText("旧API:\n"+sb.toString());}//当已注册传感器的精度发生变化时调用@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}
运行下看下结果:
当我们使用TYPE_ORIENTATION时,会发现这是个已经过时的方法,那最新的获取设备方向的方法是什么呢?
/*** A constant describing an orientation sensor type.* <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}* for more details.** @deprecated use {@link android.hardware.SensorManager#getOrientation* SensorManager.getOrientation()} instead.*/@Deprecatedpublic static final int TYPE_ORIENTATION = 3;
查看源码我们发现,官方已经给出了替代的方法,那就是使用SensorManager.getOrientation()。
那这个方法具体是怎么使用,或者返回的是什么呢?
/* @param R* rotation matrix see {@link #getRotationMatrix}.** @param values* an array of 3 floats to hold the result.* */public static float[] getOrientation(float[] R, float[] values) {/** 4x4 (length=16) case:* / R[ 0] R[ 1] R[ 2] 0 \* | R[ 4] R[ 5] R[ 6] 0 |* | R[ 8] R[ 9] R[10] 0 |* \ 0 0 0 1 /** 3x3 (length=9) case:* / R[ 0] R[ 1] R[ 2] \* | R[ 3] R[ 4] R[ 5] |* \ R[ 6] R[ 7] R[ 8] /**/if (R.length == 9) {values[0] = (float) Math.atan2(R[1], R[4]);values[1] = (float) Math.asin(-R[7]);values[2] = (float) Math.atan2(-R[6], R[8]);} else {values[0] = (float) Math.atan2(R[1], R[5]);values[1] = (float) Math.asin(-R[9]);values[2] = (float) Math.atan2(-R[8], R[10]);}return values;}
从源码这里我们可以看到这个方法有两个参数,
- 第一个参数是
R
用来保存磁场和加速度的数据,通过该函数获取方位角。 - 第二个参数是函数输出,数据自动填充。
也就是说第二个参数就是我们需要的模拟方向的数据。
- value[0] 方位角(绕-z轴旋转的度数)。这是设备当前罗盘方向与磁北极之间的角度。如果器件的上边缘朝向磁北,则方位角为0度; 如果顶部边缘朝南,则方位角为180度。类似地,如果顶部边缘朝向东方,则方位角为90度,如果顶部边缘朝向西方,则方位角为270度。
- value[1] 间距(围绕x轴的旋转度)。这是平行于设备屏幕的平面与平行于地面的平面之间的角度。如果您将设备平行于地面,底边与您最接近,并将设备的顶边向地面倾斜,则俯仰角变为正。向相反方向倾斜 - 将设备的顶部边缘移离地面 - 导致俯仰角变为负。值的范围是-180度到180度。
- value[2] 滚动(绕y轴旋转的角度)。这是垂直于设备屏幕的平面与垂直于地面的平面之间的角度。如果您将设备平行于地面,底边最靠近您,并将设备的左边缘向地面倾斜,则滚动角度变为正值。向相反方向倾斜 - 将设备的右边缘朝向地面移动 - 导致滚动角度变为负值。值范围为-90度至90度。
另外第一个参数数组R我们可以看到是通过getRotationMatrix()获取到的。
public static boolean getRotationMatrix(float[] R, float[] I,float[] gravity, float[] geomagnetic) {// TODO: move this to native code for efficiencyfloat Ax = gravity[0];float Ay = gravity[1];float Az = gravity[2];final float normsqA = (Ax * Ax + Ay * Ay + Az * Az);final float g = 9.81f;final float freeFallGravitySquared = 0.01f * g * g;if (normsqA < freeFallGravitySquared) {// gravity less than 10% of normal valuereturn false;}final float Ex = geomagnetic[0];final float Ey = geomagnetic[1];final float Ez = geomagnetic[2];float Hx = Ey * Az - Ez * Ay;float Hy = Ez * Ax - Ex * Az;float Hz = Ex * Ay - Ey * Ax;final float normH = (float) Math.sqrt(Hx * Hx + Hy * Hy + Hz * Hz);if (normH < 0.1f) {// device is close to free fall (or in space?), or close to// magnetic north pole. Typical values are > 100.return false;}final float invH = 1.0f / normH;Hx *= invH;Hy *= invH;Hz *= invH;final float invA = 1.0f / (float) Math.sqrt(Ax * Ax + Ay * Ay + Az * Az);Ax *= invA;Ay *= invA;Az *= invA;final float Mx = Ay * Hz - Az * Hy;final float My = Az * Hx - Ax * Hz;final float Mz = Ax * Hy - Ay * Hx;if (R != null) {if (R.length == 9) {R[0] = Hx; R[1] = Hy; R[2] = Hz;R[3] = Mx; R[4] = My; R[5] = Mz;R[6] = Ax; R[7] = Ay; R[8] = Az;} else if (R.length == 16) {R[0] = Hx; R[1] = Hy; R[2] = Hz; R[3] = 0;R[4] = Mx; R[5] = My; R[6] = Mz; R[7] = 0;R[8] = Ax; R[9] = Ay; R[10] = Az; R[11] = 0;R[12] = 0; R[13] = 0; R[14] = 0; R[15] = 1;}}if (I != null) {// compute the inclination matrix by projecting the geomagnetic// vector onto the Z (gravity) and X (horizontal component// of geomagnetic vector) axes.final float invE = 1.0f / (float) Math.sqrt(Ex * Ex + Ey * Ey + Ez * Ez);final float c = (Ex * Mx + Ey * My + Ez * Mz) * invE;final float s = (Ex * Ax + Ey * Ay + Ez * Az) * invE;if (I.length == 9) {I[0] = 1; I[1] = 0; I[2] = 0;I[3] = 0; I[4] = c; I[5] = s;I[6] = 0; I[7] = -s; I[8] = c;} else if (I.length == 16) {I[0] = 1; I[1] = 0; I[2] = 0;I[4] = 0; I[5] = c; I[6] = s;I[8] = 0; I[9] = -s; I[10] = c;I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0;I[15] = 1;}}return true;}
我们看到getRotationMatrix()这个方法有四个参数,这四个参数分别是什么呢?
1:float[] R 是一个包含旋转矩阵的浮点数组,也是要填充的数组
2:float[] I 将磁场数据转换进实际的重力坐标中,一般传null。
3:float[] gravity 加速度传感器数据 数组长度3
4:float[] geomagnetic 地磁传感器数据 长度 3
具体使用步骤
首先定义参数:
//加速度传感器数据private final float[] accelerometerReading = new float[3];//地磁传感器数据private final float[] magnetometerReading = new float[3];//旋转矩阵,用来保存磁场和加速度的数据private final float[] rotationMatrix = new float[9];//方向数据private final float[] orientationAngles = new float[3];
注册listener:
@Overrideprotected void onResume() {super.onResume();//加速度传感器Sensor accelerometer = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);if (accelerometer != null) {manager.registerListener(this, accelerometer,SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);}//地磁传感器Sensor magneticField = manager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);if (magneticField != null) {manager.registerListener(this, magneticField,SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);}}//另外这几行代码是在官网上复制的,但是有个问题,官网两个传感器在获取对象时传的type是同一个,注意下。。。。。
@Overridepublic void onSensorChanged(SensorEvent event) {//判断sensor类型if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {System.arraycopy(event.values, 0, accelerometerReading,0, accelerometerReading.length);} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {System.arraycopy(event.values, 0, magnetometerReading,0, magnetometerReading.length);}updateOrientationAngles();}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}public void updateOrientationAngles() {// 更新旋转矩阵.// 参数1:// 参数2 :将磁场数据转换进实际的重力坐标中,一般默认情况下可以设置为null// 参数3:加速度// 参数4:地磁SensorManager.getRotationMatrix(rotationMatrix, null,accelerometerReading, magnetometerReading);//根据旋转矩阵计算设备的方向//参数1:旋转数组//参数2:模拟方向传感器的数据SensorManager.getOrientation(rotationMatrix, orientationAngles);StringBuilder sb=new StringBuilder();if (orientationAngles.length>=3){sb.append("z轴:"+orientationAngles[0]+"\n");sb.append("x轴:"+orientationAngles[1]+"\n");sb.append("y轴:"+orientationAngles[2]+"\n");binding.tvValueNew.setText("\n新API:\n"+sb.toString());}}
看下结果:
另外加个指南针图片,根据获取的degrees旋转。
//顺时针转动为正,故手机顺时针转动时,图片得逆时针转动//让图片相对自身中心点转动,开始角度默认为0;此后开始角度等于上一次结束角度RotateAnimation ra = new RotateAnimation(fromDegrees, -degrees, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);//动画时间200毫秒ra.setDuration(200);ra.setFillAfter(true);binding.ivCompass.startAnimation(ra);fromDegrees = -degrees;
最后附上git的地址:
Github地址
Android 传感器篇:(一)方向传感器相关推荐
- Android 电子罗盘 --指南针(方向传感器的应用)
,图片神马的在网上搜个指南针图片就好了,本来没有注释,发上来之后感觉不行,还是加上吧,方便学习 main.xml <?xml version="1.0" encoding=& ...
- Android 电子罗盘--指南针(方向传感器的应用)
转载自: http://blog.csdn.net/onlyonecoder/article/details/8475653 图片神马的在网上搜个指南针图片就好了,本来没有注释,发上来之后感觉不行,还 ...
- Android学习-指南针(方向传感器)
Android学习-指南针 效果图(背景图片网上随便找的): 1.编写布局文件activity_main.xml文件 主要放一个东南西北方向图片,一个指针图片用来指明方向 <?xml versi ...
- Android百度地图(二)结合方向传感器我们自己定位哪里走
Android百度地图(二)结合方向传感器我们自己定位哪里走 本文代码在http://blog.csdn.net/xyzz609/article/details/51943556的基础上进一步修改,有 ...
- Android传感器之-方向传感器Orientation功能实现与源码
先明确一下空间坐标系的三个方向: x 方向就是手机的水平方向,右为正: y 方向就是手机的水平垂直方向,前为正: z 方向就是手机的空间垂直方向,天空的方向为正,地球的方向为负. 方向角的定义是手机y ...
- Android 传感器之方向传感器
一般情况下,在android系统中获取手机的方位信息在api中有TYPE_ORIENTATION常量,可以像得到加速度传感器那样得到方向传感器sm.getDefaultSensor(Sensor.TY ...
- Android 方向传感器与磁力计和加速度传感器之间的关系
一般情况下,在android系统中获取手机的方位信息azimuth似乎是很简单的事情,在api中有TYPE_ORIENTATION常量,可以像得到加速度传感器那样得到方向传感器sm.getDefaul ...
- Android -- 传感器使用示例, 用方向传感器做指南针
1. 传感器类型:方向.加速度(重力).光线.磁场.距离(临近性).温度等. 方向传感器: Sensor.TYPE_ORIENTATION 加速度(重力)传感器: Sensor.TYPE_ACCE ...
- 浅谈百度地图的简单开发之结合方向传感器实现定位功能(三)
今天我们来谈下百度地图的定位功能,在此之前我已经将百度地图的基本地图大概说了下,其实百度地图的基本功能还有很多的内容.感兴趣的可以到百度地图的开发者的官网看看.今天就开始来讲下百度地图中的定位功能. ...
- 百度地图的简单开发之方向传感器实现定位功能
今天我们来谈下百度地图的定位功能,在此之前我已经将百度地图的基本地图大概说了下,其实百度地图的基本功能还有很多的内容.感兴趣的可以到百度地图的开发者的官网看看.今天就开始来讲下百度地图中的定位功能. ...
最新文章
- 全球农企对话国际农民丰收节贸易会·万祥军:拜耳谋定领先
- Ajax联动下拉框的实现例子
- 《敏捷敬业度》作者访谈
- Train Problem I hdu 1022(栈)
- Idea进行远程Debug
- 怎么把外部参照合并到图纸_CAD图纸中插入的参照底图如何使用
- 正则表达式的性能评测
- Ai Challenger Caption图像中文描述(2017)
- Cocosd-x”设计模式“之五 :防御式编程”模式“
- 微软产品居然出现中文兼容问题
- 获取小程序页面跳转链接
- Python学习笔记之小派读诗
- wireshark详细图文入门教程
- 1116: 删除元素(数组)
- 小程序自定义tabbar,不同用户显示不同页面
- 第86场双周赛 NO.3 被列覆盖的最多行数
- 走迷宫爆压,21行突破B站记录(自创,自设地图)
- JavaScript放大镜插件magnifier实现图像放大效果
- 用计算机画画教学设计,电脑版你画画教学设计
- raise ImportError(“html5lib not found, please install it“) ImportError: html5lib not found