Android 6.0 系统支持的传感器多达26种:加速度传感器 (accelerometer)、磁力传感器(magnetic field)、方向传感器(orientation)、陀螺仪(gyroscope)、环境光照传感器(light)、压力传感器(pressure)、温度传感器(temperature)和距离传感器(proximity)等等, Sensor.java 中有相关定义 源码。
Sensor 架构图
主要包括2个进程,服务端和客户端。 Sensor的整体逻辑非常清晰,一个控制流,一个数据流。
SensorManager:可以通过这个类去创建一个传感器服务的实例,这个类提供的各种方法可以访问传感器列表、注册或解除注册传感器事件监听、获取方位信息等。
Sensor:用于创建一个特定的传感器实例,这个类提供的方法可以让你决定一个传感器的功能。
SensorEvent:系统会通过这个类创建一个传感器事件对象,提供了一个传感器的事件信息,包含一下内容,原生的传感器数据、触发传感器的事件类型、精确的数据以及事件发生的时间。
SensorEventListener:可以通过这个接口创建两个回调用法来接收传感器的事件通知,比如当传感器的值发生变化时。
第一步:获取SensorManager对象
第二步:获取Sensor对象
第三步:注册Sensor对象
第四步:重写onAccuracyChanged,onSensorChanged这两个方法
第五步:注销Sensor对象
public class SensorActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
@Override
public final void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//第一步:通过getSystemService获得SensorManager实例对象
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//第二步:通过SensorManager实例对象获得想要的传感器对象:参数决定获取哪个传感器
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
}
//第四步:必须重写的两个方法:onAccuracyChanged,onSensorChanged
/**
* 传感器精度发生改变的回调接口
*/
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {
//TODO 在传感器精度发生改变时做些操作,accuracy为当前传感器精度
}
/**
* 传感器事件值改变时的回调接口:执行此方法的频率与注册传感器时的频率有关
*/
@Override
public final void onSensorChanged(SensorEvent event) {
// 大部分传感器会返回三个轴方向x,y,x的event值,值的意义因传感器而异
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
//TODO 利用获得的三个float传感器值做些操作
}
/**
* 第三步:在获得焦点时注册传感器并让本类实现SensorEventListener接口
*/
@Override
protected void onResume() {
super.onResume();
/*
*第一个参数:SensorEventListener接口的实例对象
*第二个参数:需要注册的传感器实例
*第三个参数:传感器获取传感器事件event值频率:
* SensorManager.SENSOR_DELAY_FASTEST = 0:对应0微秒的更新间隔,最快,1微秒 = 1 % 1000000秒
* SensorManager.SENSOR_DELAY_GAME = 1:对应20000微秒的更新间隔,游戏中常用
* SensorManager.SENSOR_DELAY_UI = 2:对应60000微秒的更新间隔
* SensorManager.SENSOR_DELAY_NORMAL = 3:对应200000微秒的更新间隔
* 键入自定义的int值x时:对应x微秒的更新间隔
*
*/
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
/**
* 第五步:在失去焦点时注销传感器
*/
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
}
注意,设备不一定支持你需要的sensor,使用前可以先判断下可用性
private SensorManager mSensorManager;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
// Success! There's a magnetometer.
} else {
// Failure! No magnetometer.
}
//或者
List deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
加速度传感器又叫G-sensor,返回x、y、z三轴的加速度数值。
该数值包含地心引力的影响,单位是m/s^2。
将手机平放在桌面上,x轴默认为0,y轴默认0,z轴默认9.81。 将手机朝下放在桌面上,z轴为-9.81。 将手机向左倾斜,x轴为正值。 将手机向右倾斜,x轴为负值。 将手机向上倾斜,y轴为负值。 将手机向下倾斜,y轴为正值。
磁力传感器简称为M-sensor,返回x、y、z三轴的环境磁场数据。
该数值的单位是微特斯拉(micro-Tesla),用uT表示。 单位也可以是高斯(Gauss),1Tesla=10000Gauss。
硬件上一般没有独立的磁力传感器,磁力数据由电子罗盘传感器提供(E-compass)。电子罗盘传感器同时提供下文的方向传感器数据。
方向传感器简称为O-sensor,返回三轴的角度数据,方向数据的单位是角度。
为了得到精确的角度数据,E-compass(电子罗盘传感器)需要获取G-sensor(加速度传感器)的数据, 经过计算生产O-sensor数据,否则只能获取水平方向的角度。
方向传感器提供三个数据,分别为azimuth、pitch和roll。
azimuth:方位,返回水平时磁北极和Y轴的夹角,范围为0°至360°。 0°=北,90°=东,180°=南,270°=西。
pitch:x轴和水平面的夹角,范围为-180°至180°。 当z轴向y轴转动时,角度为正值。
roll:y轴和水平面的夹角,由于历史原因,范围为-90°至90°。 当x轴向z轴移动时,角度为正值。
电子罗盘在获取正确的数据前需要进行校准,通常可用8字校准法。 8字校准法要求用户使用需要校准的设备在空中做8字晃动, 原则上尽量多的让设备法线方向指向空间的所有8个象限。
陀螺仪传感器叫做Gyro-sensor,返回x、y、z三轴的角速度数据。
角速度的单位是radians/second。
根据Nexus S手机实测: 水平逆时针旋转,Z轴为正。 水平逆时针旋转,z轴为负。 向左旋转,y轴为负。 向右旋转,y轴为正。 向上旋转,x轴为负。 向下旋转,x轴为正。
重力传感器简称GV-sensor,输出重力数据。
在地球上,重力数值为9.8,单位是m/s^2。 坐标系统与加速度传感器相同。 当设备复位时,重力传感器的输出与加速度传感器相同。
线性加速度传感器简称LA-sensor。线性加速度传感器是加速度传感器减去重力影响获取的数据。 单位是m/s^2,坐标系统与加速度传感器相同。
加速度传感器、重力传感器和线性加速度传感器的计算公式如下:== 加速度 = 重力 + 线性加速度==
当一个设备被放在其默认的方向上时,X轴是水平指向右的,Y轴是垂直向上的,Z轴是指向屏幕正面之外的,即屏幕背面是Z的负值。
当设备运动或者旋转的时候,这些坐标轴是不会改变的,即它们是跟随手机的。
即是说,手机坐标系是跟随设备的自然方向的(但是请记住自然方向不一定是竖直,比如平板它的自然方向就很有可能是横向)。
使用这个坐标系的传感器:
常常要考虑屏幕的旋转,即 屏幕画面相对于自然方向的旋转。
于是就需要使用 getRotation() 方法来获取屏幕的旋转值。
这个方法是Display类中的,跟传感器不相关。
这个方法的返回值只对应0,90,180,270四种旋转情况,它说明屏幕显示区域的旋转情况。
有一些传感器和方法使用相对于世界的坐标系,因为它们返回的数据反映设备相对于地球及真实环境的位置信息。
请见getOrientation() 方法,getRotationMatrix() 方法,Orientation Sensor, 和 Rotation Vector Sensor。
getRotationMatrix()
getRotationMatrix() 方法说明中,定义的世界坐标系如下:
X轴平行于地面,指向东方。
Y轴平行于地面,指向北极方向。
Z轴垂直于地面,指向天空。
getOrientation()
getOrientation() 方法中所用的坐标系与上面的不同:
X轴平行于地面,指向西方;
Y轴平行于地面,指向地磁场北极。
Z轴垂直于地面,指向地心。
getOrientation方法的返回值表示:
values[0]: azimuth, rotation around the Z axis.
values[1]: pitch, rotation around the X axis.
values[2]: roll, rotation around the Y axis.
并且这三个角度值都是以弧度做单位,逆时针方向为正。