常用傳感器介紹與用法
Android平臺(tái)支持三個(gè)大類的傳感器
Motion sensors(運(yùn)動(dòng)傳感器)
這些傳感器測(cè)量加速力,并沿三個(gè)軸的旋轉(zhuǎn)力。此類別包括加速度計(jì),重力感應(yīng)器, 陀螺儀和旋轉(zhuǎn)矢量傳感器。
Environmental sensors (環(huán)境傳感器)
這些傳感器測(cè)量各種環(huán)境參數(shù),例如環(huán)境空氣溫度和壓力,照明和濕度。此類別包括氣壓計(jì),光度計(jì),和溫度計(jì)。
Position sensors (位置傳感器)
這些傳感器測(cè)量設(shè)備的物理位置。這個(gè)類別包括方向傳感器和磁力計(jì)。
傳感器實(shí)現(xiàn)流程
第一步:得到SensorManager
SensorManager mSensorManager = (SensorManager) mContext
.getSystemService(Context.SENSOR_SERVICE);12
第二步:注冊(cè)傳感器
Sensor sensor = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (null != sensor)
mSensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_NORMAL);12345
registerListener這個(gè)方法有三個(gè)參數(shù)。
第一個(gè)參數(shù)是傳感器數(shù)據(jù)變化的監(jiān)聽器
我們需要去實(shí)現(xiàn)SensorEventListener接口,他里面有兩個(gè)回調(diào)方法,
@Override
public void onSensorChanged(SensorEvent event) {
//當(dāng)傳感器的數(shù)值發(fā)生變化時(shí)調(diào)用
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//傳感器的精度發(fā)生變化時(shí)調(diào)用
}123456789
onSensorChanged方法只有一個(gè)SensorEvent類型的參數(shù)event,其中SensorEvent類有一個(gè)values變量非常重要,該變量的類型是float[]。但該變量最多只有3個(gè)元素,而且根據(jù)傳感器的不同,values變量中元素所代表的含義也不同。
關(guān)于values值的詳細(xì)含義請(qǐng)看參考文章?。?!
第二個(gè)參數(shù)是我們需要監(jiān)聽的傳感器
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);1
Sensor.TYPE_ACCELEROMETER則是Android設(shè)定傳感器類型,這里是指加速度傳感器,
第三個(gè)參數(shù)是傳感器數(shù)據(jù)更新數(shù)據(jù)的速度
有以下四個(gè)值可選,他們的速度是遞增的
SENSOR_DELAY_UI
SENSOR_DELAY_NORMAL
SENSOR_DELAY_GAME
SENSOR_DELAY_FASTEST
傳感器的注銷
//注銷所有傳感器對(duì)象
public voidunregisterListener(SensorEventListener listener)
//注銷指定的傳感器對(duì)象
public voidunregisterListener(SensorEventListener listener, Sensor sensor)1234
sensor的獲取依舊是通過(guò)SensorManager.getDefaultSensor()方法。
獲得手機(jī)支持的所有傳感器
Listsensors = sensorManager.getSensorList(Sensor.TYPE_ALL);1
Android傳感器類型表
加速度傳感器:TYPE_ACCELEROMETER
以m/s2測(cè)量它設(shè)備所有三個(gè)物理軸線方向(x,y,和z)加速度。
周圍溫度傳感器:TYPE_AMBIENT_TEMPERATURE
檢測(cè)周圍空氣溫度。
重力傳感器:TYPE_GRAVITY
測(cè)量重力
陀螺儀傳感器:TYPE_GYROSCOPE
以rad/s測(cè)量設(shè)備三個(gè)物理軸線方向(x,y,和z)。旋轉(zhuǎn)速度。
光照傳感器:TYPE_LIGHT
以lx測(cè)量周圍的光線級(jí)別。
線性加速度傳感器:TYPE_LINEAR_ACCELERATION
檢測(cè)沿著一個(gè)軸向的加速度。
磁力傳感器:TYPE_MAGNETIC_FIELD
測(cè)量周圍的三個(gè)物理軸線方向的磁場(chǎng)。
方向傳感器: TYPE_ORIENTATION
測(cè)量設(shè)備所有三個(gè)物理軸線方向(x,y和x)的旋轉(zhuǎn)角度。
壓力傳感器:TYPE_PRESSURE
測(cè)量周圍空氣氣壓
接近傳感器:TYPE_PROXIMITY
檢測(cè)物體與手機(jī)的距離
相對(duì)濕度傳感器:TYPE_RELATIVE_HUMIDITY
檢測(cè)周圍空氣相對(duì)濕度
旋轉(zhuǎn)矢量傳感器:TYPE_ROTATION_VECTOR
用于檢測(cè)運(yùn)動(dòng)和檢測(cè)旋轉(zhuǎn)。
溫度傳感器: TYPE_TEMPERATURE
檢測(cè)設(shè)備的溫度
傳感器使用實(shí)踐
這里以方向傳感器為例
方向傳感器的獲取方式
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);1
上面這個(gè),對(duì),已經(jīng)被google棄用了,了解就好。
Android中的坐標(biāo)系
自己畫的有點(diǎn)丑,將就著看吧,Z軸默認(rèn)垂直于地面,所謂獲取的三個(gè)Values數(shù)組即對(duì)應(yīng)手機(jī)與Z,Y,X形成的夾角,后面會(huì)說(shuō)明,
前面說(shuō)了,TYPE_ORIENTATION已被棄用,那么最新的方向傳感器是如何做的呢?
事實(shí)上,Android 獲取手機(jī)旋轉(zhuǎn)的方向和角度是通過(guò)加速度傳感器和地磁傳感器共同計(jì)算得出的
OK,我們這時(shí)候是需要同時(shí)使用兩個(gè)傳感器的,看代碼
Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.
TYPE_ACCELEROMETER);
Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.
TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(listener, accelerometerSensor,
SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(listener, magneticSensor,
SensorManager.SENSOR_DELAY_GAME);12345678
同時(shí)使用了加速度傳感器和地磁傳感器
獲取旋轉(zhuǎn)矩陣數(shù)組R
SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);1
獲取手機(jī)旋轉(zhuǎn)數(shù)據(jù)
SensorManager.getOrientation(R, values);1
values 是一個(gè)長(zhǎng)度為 3 的 float 數(shù)組,手機(jī)在各個(gè)方向上的旋轉(zhuǎn)數(shù)據(jù)都會(huì)被存放到這個(gè)數(shù)組當(dāng)中。
對(duì)應(yīng)關(guān)系:
values[0]-》Z軸、values[1]-》X軸、values[2]-》Y軸
values[0]的取值范圍是-180到180 度,其中±180 度表示正南方向,0 度表示正北方向,-90 度表示正西方向,90 度表示正東方向,如圖
所謂,實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),這是我檢測(cè)后自行畫的,大家看一下就明白該怎么根據(jù)獲取到的角度來(lái)做對(duì)應(yīng)的處理了
一個(gè)完整的方向傳感器封裝類
public class DirectionSensorUtils implements SensorEventListener {
private SensorManager sensorManager;
float[] accelerometerValues = new float[3];
float[] magneticValues = new float[3];
float lastRotateDegree;
private ImageView compassImg;//指南針背景圖
public DirectionSensorUtils(Context context , ImageView compassImg) {
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
this.compassImg = compassImg;
}
//注冊(cè)傳感器
public void registerSensor(){
Sensor accelerometerSensor = sensorManager.getDefaultSensor(Sensor.
TYPE_ACCELEROMETER);
Sensor magneticSensor = sensorManager.getDefaultSensor(Sensor.
TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(this, accelerometerSensor,
SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(this, magneticSensor,
SensorManager.SENSOR_DELAY_GAME);
}
//解除傳感器注冊(cè)
public void unregisterSensor(){
if (sensorManager != null) {
sensorManager.unregisterListener(this);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
// 判斷當(dāng)前是加速度傳感器還是地磁傳感器
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// 通過(guò)clone()獲取不同的values引用
accelerometerValues = event.values.clone();
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
magneticValues = event.values.clone();
}
//獲取地磁與加速度傳感器組合的旋轉(zhuǎn)矩陣
float[] R = new float[9];
float[] values = new float[3];
SensorManager.getRotationMatrix(R, null, accelerometerValues,
magneticValues);
SensorManager.getOrientation(R, values);
//values[0]-》Z軸、values[1]-》X軸、values[2]-》Y軸
//使用前請(qǐng)進(jìn)行轉(zhuǎn)換,因?yàn)楂@取到的值是弧度,示例如下
// Math.toDegrees(values[0]);
// Math.toDegrees(values[1]);
// Math.toDegrees(values[2]);
handleEvent(values);
}
public void handleEvent(float[] values){
// 這里實(shí)現(xiàn)了一個(gè)指南針
float rotateDegree = -(float) Math.toDegrees(values[0]);
if (Math.abs(rotateDegree - lastRotateDegree) 》 1) {
RotateAnimation animation = new RotateAnimation
(lastRotateDegree, rotateDegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.
RELATIVE_TO_SELF, 0.5f);
animation.setFillAfter(true);
compassImg.startAnimation(animation);
lastRotateDegree = rotateDegree;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}