从这篇文章开始,主要记录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;}

从源码这里我们可以看到这个方法有两个参数,

  1. 第一个参数是R用来保存磁场和加速度的数据,通过该函数获取方位角。
  2. 第二个参数是函数输出,数据自动填充。

也就是说第二个参数就是我们需要的模拟方向的数据。

  • 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 传感器篇:(一)方向传感器相关推荐

  1. Android 电子罗盘 --指南针(方向传感器的应用)

    ,图片神马的在网上搜个指南针图片就好了,本来没有注释,发上来之后感觉不行,还是加上吧,方便学习 main.xml <?xml version="1.0" encoding=& ...

  2. Android 电子罗盘--指南针(方向传感器的应用)

    转载自: http://blog.csdn.net/onlyonecoder/article/details/8475653 图片神马的在网上搜个指南针图片就好了,本来没有注释,发上来之后感觉不行,还 ...

  3. Android学习-指南针(方向传感器)

    Android学习-指南针 效果图(背景图片网上随便找的): 1.编写布局文件activity_main.xml文件 主要放一个东南西北方向图片,一个指针图片用来指明方向 <?xml versi ...

  4. Android百度地图(二)结合方向传感器我们自己定位哪里走

    Android百度地图(二)结合方向传感器我们自己定位哪里走 本文代码在http://blog.csdn.net/xyzz609/article/details/51943556的基础上进一步修改,有 ...

  5. Android传感器之-方向传感器Orientation功能实现与源码

    先明确一下空间坐标系的三个方向: x 方向就是手机的水平方向,右为正: y 方向就是手机的水平垂直方向,前为正: z 方向就是手机的空间垂直方向,天空的方向为正,地球的方向为负. 方向角的定义是手机y ...

  6. Android 传感器之方向传感器

    一般情况下,在android系统中获取手机的方位信息在api中有TYPE_ORIENTATION常量,可以像得到加速度传感器那样得到方向传感器sm.getDefaultSensor(Sensor.TY ...

  7. Android 方向传感器与磁力计和加速度传感器之间的关系

    一般情况下,在android系统中获取手机的方位信息azimuth似乎是很简单的事情,在api中有TYPE_ORIENTATION常量,可以像得到加速度传感器那样得到方向传感器sm.getDefaul ...

  8. Android -- 传感器使用示例, 用方向传感器做指南针

    1. 传感器类型:方向.加速度(重力).光线.磁场.距离(临近性).温度等. 方向传感器:   Sensor.TYPE_ORIENTATION 加速度(重力)传感器: Sensor.TYPE_ACCE ...

  9. 浅谈百度地图的简单开发之结合方向传感器实现定位功能(三)

    今天我们来谈下百度地图的定位功能,在此之前我已经将百度地图的基本地图大概说了下,其实百度地图的基本功能还有很多的内容.感兴趣的可以到百度地图的开发者的官网看看.今天就开始来讲下百度地图中的定位功能. ...

  10. 百度地图的简单开发之方向传感器实现定位功能

    今天我们来谈下百度地图的定位功能,在此之前我已经将百度地图的基本地图大概说了下,其实百度地图的基本功能还有很多的内容.感兴趣的可以到百度地图的开发者的官网看看.今天就开始来讲下百度地图中的定位功能. ...

最新文章

  1. 全球农企对话国际农民丰收节贸易会·万祥军:拜耳谋定领先
  2. Ajax联动下拉框的实现例子
  3. 《敏捷敬业度》作者访谈
  4. Train Problem I hdu 1022(栈)
  5. Idea进行远程Debug
  6. 怎么把外部参照合并到图纸_CAD图纸中插入的参照底图如何使用
  7. 正则表达式的性能评测
  8. Ai Challenger Caption图像中文描述(2017)
  9. Cocosd-x”设计模式“之五 :防御式编程”模式“
  10. 微软产品居然出现中文兼容问题
  11. 获取小程序页面跳转链接
  12. Python学习笔记之小派读诗
  13. wireshark详细图文入门教程
  14. 1116: 删除元素(数组)
  15. 小程序自定义tabbar,不同用户显示不同页面
  16. 第86场双周赛 NO.3 被列覆盖的最多行数
  17. 走迷宫爆压,21行突破B站记录(自创,自设地图)
  18. JavaScript放大镜插件magnifier实现图像放大效果
  19. 用计算机画画教学设计,电脑版你画画教学设计
  20. raise ImportError(“html5lib not found, please install it“) ImportError: html5lib not found

热门文章

  1. 英语之脆弱的,易受伤的
  2. python招聘-的python招聘
  3. 【12月英语博客】念念不忘,必有回响
  4. 手动扩展oracle表空间,Oracle如何扩展表空间
  5. 为什么Go语言在今天能如此火热?
  6. 在三层交换机上配置Trunk并指定接口封装为802.1q
  7. VLAN间的三层通信
  8. 电子签名具备法律效力吗?这些知识点你需要了解
  9. node 压缩图片_Tinypng - 比ps更厉害的免费图片压缩神器
  10. Excel 录制宏 - 制作工资条