关键词:传感器、Sensor
- 使用Sensor Manager(传感器管理器)
- 可用的传感器类型
- 找出设备的自然方向
- 重新映射设备的方向参考框架
- 监视传感器并解释传感器的值
- 使用传感器见识设备的移动和方向
- 使用传感器见识设备的环境
使用传感器和传感器管理器
String service_name = Context.SENSOR_SERVICE;
SensorManager sensorManager = (SensorManager)getSystemService(service_name);
Sensor对象描述了它们代表的硬件传感器的属性,包括传感器的类型、名称、制造商以及与精确度和范围有关的详细信息。
Sensors
| Sensor | Type | Description | Common Uses |
|---|---|---|---|
TYPE_ACCELEROMETER |
Hardware | Measures the acceleration force in m/s2 that is applied to a device on all three physical axes (x, y, and z), including the force of gravity. | Motion detection (shake, tilt, etc.). |
TYPE_AMBIENT_TEMPERATURE |
Hardware | Measures the ambient room temperature in degrees Celsius (°C). See note below. | Monitoring air temperatures. |
TYPE_GRAVITY |
Software or Hardware | Measures the force of gravity in m/s2 that is applied to a device on all three physical axes (x, y, z). | Motion detection (shake, tilt, etc.). |
TYPE_GYROSCOPE |
Hardware | Measures a device\'s rate of rotation in rad/s around each of the three physical axes (x, y, and z). | Rotation detection (spin, turn, etc.). |
TYPE_LIGHT |
Hardware | Measures the ambient light level (illumination) in lx. | Controlling screen brightness. |
TYPE_LINEAR_ACCELERATION |
Software or Hardware | Measures the acceleration force in m/s2 that is applied to a device on all three physical axes (x, y, and z), excluding the force of gravity. | Monitoring acceleration along a single axis. |
TYPE_MAGNETIC_FIELD |
Hardware | Measures the ambient geomagnetic field for all three physical axes (x, y, z) in μT. | Creating a compass. |
TYPE_ORIENTATION |
Software | Measures degrees of rotation that a device makes around all three physical axes (x, y, z). As of API level 3 you can obtain the inclination matrix and rotation matrix for a device by using the gravity sensor and the geomagnetic field sensor in conjunction with the getRotationMatrix() method. |
Determining device position. |
TYPE_PRESSURE |
Hardware | Measures the ambient air pressure in hPa or mbar. | Monitoring air pressure changes. |
TYPE_PROXIMITY |
Hardware | Measures the proximity of an object in cm relative to the view screen of a device. This sensor is typically used to determine whether a handset is being held up to a person\'s ear. | Phone position during a call. |
TYPE_RELATIVE_HUMIDITY |
Hardware | Measures the relative ambient humidity in percent (%). | Monitoring dewpoint, absolute, and relative humidity. |
TYPE_ROTATION_VECTOR |
Software or Hardware | Measures the orientation of a device by providing the three elements of the device\'s rotation vector. | Motion detection and rotation detection. |
TYPE_TEMPERATURE |
Hardware | Measures the temperature of the device in degrees Celsius (°C). This sensor implementation varies across devices and this sensor was replaced with theTYPE_AMBIENT_TEMPERATURE sensor in API Level 14 |
Monitoring temperatures. |
虚拟传感器
通常,Android传感器是彼此独立地工作的,每个传感器报告特定硬件得到的结果,而不应用任何过滤或者平滑处理。
在一些情况中,使用虚拟传感器很有帮助,因为它们可以提供简化的、经过校正的或者复合的数据,使它们更易于在一些应用程序中使用。
重力传感器、线性加速度传感器和旋转向量传感器都是Android框架提供的虚拟传感器的例子。它们可以使用加速计传感器、磁场传感器和陀螺仪传感器的组合,而不是单独一种硬件的输出。
查找传感器
// 获取所有的传感器列表,传入参数Sensor.TYPE_ALL List<Sensor> deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL); // 获取指定的传感器,下面示例返回可用的陀螺仪 List<Sensor> gravSensors = mSensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);
如果指定的传感器类型有多个传感器实现,那么可以通过查询每个返回的Sensor对象来决定使用哪个传感器。
每个Sensor对象都会报告其名称、用电量、最小延迟、最大工作范围、分辨率和供应商的类型。
按照约定,硬件传感器实现位于返回的列表的顶部,虚拟的校正实现位于列表的地底部。
通过使用传感器管理器的getDefaultSensor方法,可以找到指定类型的传感器的默认实现。如果指定的传感器类型没有默认传感器实现,该方法将返回null。
// 返回默认的三轴加速计传感器 mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
以下示例代码显示了如何选择一个工作范围最大并且耗电量最低的光传感器,以及校正过的陀螺仪(如果存在的话)
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); List<Sensor> lightSensor = sensorManager.getSensorList(Sensor.TYPE_LIGHT); List<Sensor> gyoscopes = sensorManager.getSensorList(Sensor.TYPE_GYROSCOPE); Sensor bestLightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); Sensor correctedGyro = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); if (bestLightSensor != null) { for (Sensor lightSensor : lightSensor) { float range = lightSensor.getMaximumRange(); float power = lightSensor.getPower(); if (range >= bestLightSensor.getMaximumRange()) { if (power > bestLightSensor.getPower() || range > bestLightSensor.getMaximumRange()) { bestLightSensor = lightSensor; } } } } if (gyoscopes != null && gyoscopes.size() > 1) { correctedGyro = gyoscopes.get(gyoscopes.size() - 1); }
监视传感器
为了监视传感器,需要实现一个SensorEventListener。使用onSensorChanged方法监视传感器值,使用onAccuracyChanged方法响应传感器精确度的变化。
final SensorEventListener mySensorEventListener = new SensorEventListener() { public void onSensorChanged(SensorEvent sensorEvent) { // 监视传感器改变 } public void onAccuracyChanged(Sensor sensor, int accuracy) { // 对传感器精度的改变作出反应 } };
以下示例使用默认的更新速度为默认的近距离传感器注册一个传感器事件监听器。
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
sensorManager.registerListener(mySensorEventListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
int |
SENSOR_DELAY_FASTEST
get sensor data as fast as possible |
int |
SENSOR_DELAY_GAME
rate suitable for games |
int |
SENSOR_DELAY_NORMAL
rate (default) suitable for screen orientation changes |
int |
SENSOR_DELAY_UI
rate suitable for the user interface |
所选择的速率并不是绝对固定的;传感器管理器返回结果的速率可能比指定的速率更快或者更慢一点,不过一般都是更快一点,为了最小化在应用程序中与使用传感器相关的资源开销,最好选择可接受的最慢速率。
同样重要的时当应用程序不在需要接受更新时,注销其传感器事件监听器:
sensorManager.unregisterListener(mySensorEventListener);
分别在Activity的onResume和onPause方法中注册和注销其传感器事件监听器,以确保仅在Activity处于活动状态时才使用它们。
解释传感器
监视设备的移动和方向
设备的自然防线是指在三个坐标轴的方向都为0的方向。
对于典型的智能手机,当它平放在桌上并且上部指向正北方时的方向就是其自然方向。
为了确保正确的解释方向,你需要相对于自然方向确定当前的显示方向,而不是假定当前的显示方向是竖直方向或水平方向。
以下示例使用默认的Display对象的getRotation方法,找出当前屏幕的旋转方向。
String windowSrvc = Context.WINDOW_SERVICE; WindowManager wm = ((WindowManager)getSystemService(windowSrvc)); Display display = wm.getDefaultDisplay(); int rotation = display.getRotation(); switch (rotation) { case (Surface.ROTATION_0) : break; // Natural case (Surface.ROTATION_90) : break; // On its left side case (Surface.ROTATION_180) : break; // Updside down case (Surface.ROTATION_270) : break; // On its right side default: break; }
加速计
加速计有时也叫作重力传感器,因为它们能够测量移动和重力引起的加速度。因此,如果加速计检测与地球表面垂直的坐标轴上的加速度,那么当其处于静止状态时取值将为9.80665。STANDARD_GRAVITY
需要注意的是,加速计并不能测量速度,因此不能够基于一个单独的加速计读数直接测量速度。你需要在一段时间内对加速度求积分来计算出速度。然后,可以通过在一段时间内对速度求积分来计算出走过的距离。
[未完待续]
陀螺仪
陀螺仪传感器用于测量指定轴上的角速度(单位为弧度/秒),它使用的坐标系与加速计传感器相同。
Android陀螺仪回返回绕三个轴的旋转速率,它们的敏感度和高频更新速率保证了极其平滑和精确的更新。因此,陀螺仪传感器特别适合那些使用方向变化作为输入机制的应用程序。
因为陀螺仪测量的是速度而不是方向,所以为了确定当前防线,必须在一段时间内对陀螺仪的结果求积分。计算得到的结果表示方向绕指定轴的变化,所以必须通过校准或者结合其他传感器来确定最初的方向。
下例展示了使用陀螺仪传感器计算方向变化
final float nanosecondsPerSecond = 1.0f / 1000000000.0f; private long lastTime = 0; final float[] angle = new float[3]; SensorEventListener myGyroListener = new SensorEventListener() { public void onSensorChanged(SensorEvent sensorEvent) { if (lastTime != 0) { final float dT = (sensorEvent.timestamp - lastTime) * nanosecondsPerSecond; angle[0] += sensorEvent.values[0] * dT; angle[1] += sensorEvent.values[1] * dT; angle[2] += sensorEvent.values[2] * dT; } lastTime = sensorEvent.timestamp; } public void onAccuracyChanged(Sensor sensor, int accuracy) {} }; private void registerGyro() { SensorManager sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE); int sensorType = Sensor.TYPE_GYROSCOPE; sm.registerListener(myGyroListener, sm.getDefaultSensor(sensorType), SensorManager.SENSOR_DELAY_NORMAL); }
值得注意的是,由于校准错误和噪声的存在,只使用陀螺仪传感器得到的方向值会变得越来越不够精确。为了解决这类问题,通常将陀螺仪和其他传感器(主要是加速计)结合使用,以提供更加平滑,更加精确的方向结果。Android4.0中引入了一个虚拟陀螺仪来尝试减小这种“漂移”效果。
环境传感器
气压传感器
气压计用来测量大气压力。Android设备中包含了气压计传感器,使用户能够确定当前海拔,甚至有可能预测天气变化。
为了检测气压变化,需要使用Sensor.TYPE_PRESSURE类型的Sensor对象,在Sensor Manager中注册SensorEventListener的实现。该方法返回的值数组中的第一个值就是当前气压,其单位为hPa。
以下示例使用气压计传感器确定当前海拔
final SensorEventListener myPressureListener = new SensorEventListener() { public void onSensorChanged(SensorEvent sensorEvent) { if (sensorEvent.sensor.getType() == Sensor.TYPE_PRESSURE) { float currentPressure = sensorEvent.values[0]; /* * 计算当前海拔,可以使用SensorManager的静态方法getAltitude,并为其提供当前气压和当地海平面气压作为参数 * 为了确保得到精确的结果,应该为海平面大气压使用一个当地值, * 不过传感器管理器通过PRESSURE_STANDARD_ATMOSPHERE常亮提供了一个标准大气压值,可作为一个近似值使用。 */ float altitude = SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, currentPressure); } } public void onAccuracyChanged(Sensor sensor, int accuracy) {} }; SensorManager sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE); int sensorType = Sensor.TYPE_PRESSURE; sm.registerListener(myPressureListener,sm.getDefaultSensor(sensorType),SensorManager.SENSOR_DELAY_NORMAL);