Android开发高级进阶——传感器
2017-06-21 11:37
357 查看
原文地址:http://www.jianshu.com/p/2e15b4e8dab2
Android系统提供了对传感器的支持,如果手机设备的硬件提供了这些传感器,Android应用可以通过传感器来获取设备的外界条件,包括手机设备的运行状态、当前摆放方向、外界的磁场、温度和压力等。Android系统提供了驱动程序去管理这些传感器硬件,当传感器感知到外部环境发生改变时,Android系统负责管理这些传感器数据。
加速度传感器:SENSOR_TYPE_ACCELEROMETER
磁力传感器:SENSOR_TYPE_FIELD
方向传感器:SENSOR_TYPE_ORIENTATION
陀螺仪传感器:SENSOR_TYPE_GYROSCOPE
光线感应传感器:SENSOR_TYPE_LIGHT
压力传感器:SENSOR_TYPE_PRESSURE
温度传感器:SENSOR_TYPE_TEMPERATURE
接近传感器:SENSOR_TYPE_PROXIMITY
重力传感器:SENSOR_TYPE_GRAVITY
线性加速度传感器:SENSOR_TYPE_LINEAR_ACCELERATION
旋转矢量传感器:SENSOR_TYPE_ROTATION_VECTOR
使用传感器的步骤分为5步:
获取SensorManager对象
调用Context的getSystemService(Context.SENSOR_SERVICE)方法获取SensorManager对象,SensorManager对象代表系统的传感器管理服务。
获取Sensor对象
调用SensorManager的getDefaultSensor(int type)方法获取指定类型的传感器。
注册Sensor对象
在Activity的onResume()方法中调用SensorManager的registerListener()方法为指定的传感器注册监听器,程序通过实现监听器即可获取传感器传来的数据。
重写onAccuracyChanged,onSensorChanged方法
当传感器的精度和数据发送变化时,在这两个方法中做相应的操作。
注销Sensor对象
在Activity的onPause()方法中调用SensorManager的unregisterListener()方法注销指定的传感器监听器。
SensorManager提供的注册传感器的方法为registerListener(SensorEventListener listener, Sensor sensor, int rate),该方法的三个参数说明如下:
listener:监听传感器事件的监听器。该监听器需要实现SensorEventListener接口。
sensor:传感器对象。
rate:指定获取传感器数据的频率。rate有以下几个频率值:
SensorManager.SENSOR_DELAY_FASTEST:最快。延迟最小,只有特别依赖于传感器数据的应用推荐采用这种频率,这种模式可能造成手机电量大量消耗。
SensorManager.SENSOR_DELAY_GAME:适合游戏的频率。一般有实时性要求的应用适合使用这种频率。
SensorManager.SENSOR_DELAY_NORMAL:正常频率。一般对实时性要求不是特别高的应用适合使用这种频率。
SensorManager.SENSOR_DELAY_UI:适合普通用户界面的频率。这种模式比较省电,而且系统开销也很小,但延迟较大。
在onSensorChanged(SensorEvent event)方法中有一个参数event,通过event可以获取传感器的类型以及传感器的数据。
获取传感器的类型:event.sensor.getType()
获取传感器的数据:event.values[i],i为0,1,2...,不同传感器,event.values[i]对应的数据不同,下面以加速度传感器为例,解释values[i]的含义。
从加速度传感器源代码中可以看出,values[0]表示x轴上的加速度,values[1]表示y轴上的加速度,values[2]表示z轴上的加速度。
因为并非所有手机都支持所有传感器,不用系统引入的传感器不同,所以在使用之前有必要判断一下,、从而提高性能。
判断是否有传感器有两种方法:
运行时检测
使用Android Market过滤器来限定目标设备必须带有指定传感器配置。
利用方向传感器,界面中的图片向手机旋转的反方向旋转。代码如下:
演示效果:
orientation_sensor_demo.gif
别忘记注销。
不要阻塞onSensorChanged方法。
避免使用过时的方法或传感器类型。
在使用前先验证传感器是否存在。
谨慎选择传感器延时。
Android系统提供了对传感器的支持,如果手机设备的硬件提供了这些传感器,Android应用可以通过传感器来获取设备的外界条件,包括手机设备的运行状态、当前摆放方向、外界的磁场、温度和压力等。Android系统提供了驱动程序去管理这些传感器硬件,当传感器感知到外部环境发生改变时,Android系统负责管理这些传感器数据。
一. Android中11中常见的传感器
加速度传感器:SENSOR_TYPE_ACCELEROMETER磁力传感器:SENSOR_TYPE_FIELD
方向传感器:SENSOR_TYPE_ORIENTATION
陀螺仪传感器:SENSOR_TYPE_GYROSCOPE
光线感应传感器:SENSOR_TYPE_LIGHT
压力传感器:SENSOR_TYPE_PRESSURE
温度传感器:SENSOR_TYPE_TEMPERATURE
接近传感器:SENSOR_TYPE_PROXIMITY
重力传感器:SENSOR_TYPE_GRAVITY
线性加速度传感器:SENSOR_TYPE_LINEAR_ACCELERATION
旋转矢量传感器:SENSOR_TYPE_ROTATION_VECTOR
二. 使用传感器
使用传感器的步骤分为5步:获取SensorManager对象
调用Context的getSystemService(Context.SENSOR_SERVICE)方法获取SensorManager对象,SensorManager对象代表系统的传感器管理服务。
获取Sensor对象
调用SensorManager的getDefaultSensor(int type)方法获取指定类型的传感器。
注册Sensor对象
在Activity的onResume()方法中调用SensorManager的registerListener()方法为指定的传感器注册监听器,程序通过实现监听器即可获取传感器传来的数据。
重写onAccuracyChanged,onSensorChanged方法
当传感器的精度和数据发送变化时,在这两个方法中做相应的操作。
注销Sensor对象
在Activity的onPause()方法中调用SensorManager的unregisterListener()方法注销指定的传感器监听器。
SensorManager提供的注册传感器的方法为registerListener(SensorEventListener listener, Sensor sensor, int rate),该方法的三个参数说明如下:
listener:监听传感器事件的监听器。该监听器需要实现SensorEventListener接口。
sensor:传感器对象。
rate:指定获取传感器数据的频率。rate有以下几个频率值:
SensorManager.SENSOR_DELAY_FASTEST:最快。延迟最小,只有特别依赖于传感器数据的应用推荐采用这种频率,这种模式可能造成手机电量大量消耗。
SensorManager.SENSOR_DELAY_GAME:适合游戏的频率。一般有实时性要求的应用适合使用这种频率。
SensorManager.SENSOR_DELAY_NORMAL:正常频率。一般对实时性要求不是特别高的应用适合使用这种频率。
SensorManager.SENSOR_DELAY_UI:适合普通用户界面的频率。这种模式比较省电,而且系统开销也很小,但延迟较大。
三. 读取传感器数据
在onSensorChanged(SensorEvent event)方法中有一个参数event,通过event可以获取传感器的类型以及传感器的数据。获取传感器的类型:event.sensor.getType()
获取传感器的数据:event.values[i],i为0,1,2...,不同传感器,event.values[i]对应的数据不同,下面以加速度传感器为例,解释values[i]的含义。
* <h4>{@link android.hardware.Sensor#TYPE_ACCELEROMETER * Sensor.TYPE_ACCELEROMETER}:</h4> All values are in SI units (m/s^2) * <ul> * <li> values[0]: Acceleration minus Gx on the x-axis </li> * <li> values[1]: Acceleration minus Gy on the y-axis </li> * <li> values[2]: Acceleration minus Gz on the z-axis </li> * </ul> * <p> * A sensor of this type measures the acceleration applied to the device * (<b>Ad</b>). Conceptually, it does so by measuring forces applied to the * sensor itself (<b>Fs</b>) using the relation: * </p> * <b><center>Ad = - ∑Fs / mass</center></b> * <p> * In particular, the force of gravity is always influencing the measured * acceleration: * </p> * <b><center>Ad = -g - ∑F / mass</center></b> * <p> * For this reason, when the device is sitting on a table (and obviously not * accelerating), the accelerometer reads a magnitude of <b>g</b> = 9.81 * m/s^2 * </p> * <p> * Similarly, when the device is in free-fall and therefore dangerously * accelerating towards to ground at 9.81 m/s^2, its accelerometer reads a * magnitude of 0 m/s^2. * </p> * <p> * It should be apparent that in order to measure the real acceleration of * the device, the contribution of the force of gravity must be eliminated. * This can be achieved by applying a <i>high-pass</i> filter. Conversely, a * <i>low-pass</i> filter can be used to isolate the force of gravity. * </p> * <pre class="prettyprint"> * public void onSensorChanged(SensorEvent event) * { * // alpha is calculated as t / (t + dT) * // with t, the low-pass filter's time-constant * // and dT, the event delivery rate * final float alpha = 0.8; * gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0]; * gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1]; * gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2]; * linear_acceleration[0] = event.values[0] - gravity[0]; * linear_acceleration[1] = event.values[1] - gravity[1]; * linear_acceleration[2] = event.values[2] - gravity[2]; * } * </pre> * <p> * <u>Examples</u>: * <ul> * <li>When the device lies flat on a table and is pushed on its left side * toward the right, the x acceleration value is positive.</li> * <li>When the device lies flat on a table, the acceleration value is * +9.81, which correspond to the acceleration of the device (0 m/s^2) minus * the force of gravity (-9.81 m/s^2).</li> * <li>When the device lies flat on a table and is pushed toward the sky * with an acceleration of A m/s^2, the acceleration value is equal to * A+9.81 which correspond to the acceleration of the device (+A m/s^2) * minus the force of gravity (-9.81 m/s^2).</li> * </ul>
从加速度传感器源代码中可以看出,values[0]表示x轴上的加速度,values[1]表示y轴上的加速度,values[2]表示z轴上的加速度。
四. 针对是否有传感器功能优化
因为并非所有手机都支持所有传感器,不用系统引入的传感器不同,所以在使用之前有必要判断一下,、从而提高性能。判断是否有传感器有两种方法:
运行时检测
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); if (sensor != null){ //传感器存在 }else{ //传感器不存在 }
使用Android Market过滤器来限定目标设备必须带有指定传感器配置。
<use-feature name = "android.hardware.sensor.orientation" android:required = "true"/>
五. 方向传感器小Demo
利用方向传感器,界面中的图片向手机旋转的反方向旋转。代码如下:public class MainActivity extends AppCompatActivity implements SensorEventListener{ private ImageView mIvSensor; private Sensor mSensor; private SensorManager mSensorManager; private float mDegress = 0f; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mIvSensor = (ImageView) findViewById(R.id.iv_sensor); mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); } @Override protected void onResume() { super.onResume(); mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_UI); //rate suitable for the user interface } @Override protected void onPause() { super.onPause(); mSensorManager.unregisterListener(this); } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ORIENTATION){ float degree = - event.values[0]; RotateAnimation rotateAnimation = new RotateAnimation(mDegress, degree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnimation.setDuration(100); mIvSensor.startAnimation(rotateAnimation); mDegress = degree; } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { //TODO:当传感器精度发生变化时 } }
演示效果:
orientation_sensor_demo.gif
六. 注意
别忘记注销。不要阻塞onSensorChanged方法。
避免使用过时的方法或传感器类型。
在使用前先验证传感器是否存在。
谨慎选择传感器延时。
相关文章推荐
- android开发笔记之高级主题—传感器的简单介绍
- Android开发高级进阶
- android开发笔记之高级主题—传感器的简单应用
- Android开发高级进阶02
- Android开发高级进阶——多进程间通信
- Android高级进阶四 Android OpenGL开发多边形
- Android开发高级进阶04(段子手爆发)
- Android开发高级进阶——多进程间通信
- Android探索之旅(第二十四篇)进阶安卓高级开发工程师需要掌握的知识体系
- Android开发高级进阶(二)—多线程(实现简单下载器)
- Android高级进阶七 Android OpenGL开发四棱锥和立方体
- Android高级进阶三 Android OpenGL | ES开发框架
- 高级Android开发工程师进阶路线
- Android高手进阶教程(八)之----Android Widget开发案例(世界杯倒计时!)
- Android 3D游戏开发(高级篇)——Opengl ES游戏引擎实现(送源代码)
- 【Android游戏开发十八】解放手指,利用传感器开发游戏!
- Android开发之广播机制进阶
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- Android JNI开发高级篇
- Android开发进阶之NIO非阻塞包(二)