什么是傳感器
維基百科是這樣定義的:傳感器是一種物理裝置或生物器官,能夠探測、感受外界的信號、物理條件(如光、熱、濕度)或化學組成(如煙霧),并將探知的信息傳遞給其他裝置或器官。
常用傳感器介紹與用法
Android平臺支持三個大類的傳感器
- Motion sensors(運動傳感器)
這些傳感器測量加速力,并沿三個軸的旋轉力。此類別包括加速度計,重力感應器, 陀螺儀和旋轉矢量傳感器。
- Environmental sensors (環境傳感器)
這些傳感器測量各種環境參數,例如環境空氣溫度和壓力,照明和濕度。此類別包括氣壓計,光度計,和溫度計。
- Position sensors (位置傳感器)
這些傳感器測量設備的物理位置。這個類別包括方向傳感器和磁力計。
傳感器實現流程
第一步:得到SensorManager
SensorManager mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
第二步:注冊傳感器
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (null != sensor) mSensorManager.registerListener(this, sensor,SensorManager.SENSOR_DELAY_NORMAL);
registerListener這個方法有三個參數。
- 第一個參數是傳感器數據變化的監聽器
我們需要去實現SensorEventListener接口,他里面有兩個回調方法,
@Override public void onSensorChanged(SensorEvent event) { //當傳感器的數值發生變化時調用 }
@Override public void onAccuracyChanged(Sensor sensor, int accuracy) { //傳感器的精度發生變化時調用 }
onSensorChanged方法只有一個SensorEvent類型的參數event,其中SensorEvent類有一個values變量非常重要,該變量的類型是float[]。但該變量最多只有3個元素,而且根據傳感器的不同,values變量中元素所代表的含義也不同。
- 第二個參數是我們需要監聽的傳感器
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Sensor.TYPE_ACCELEROMETER則是Android設定傳感器類型,這里是指加速度傳感器,
- 第三個參數是傳感器數據更新數據的速度
有以下四個值可選,他們的速度是遞增的
SENSOR_DELAY_UI
SENSOR_DELAY_NORMAL
SENSOR_DELAY_GAME
SENSOR_DELAY_FASTEST
傳感器的注銷
//注銷所有傳感器對象
public void unregisterListener(SensorEventListener listener)
//注銷指定的傳感器對象
public void unregisterListener(SensorEventListener listener, Sensor sensor)
sensor的獲取依舊是通過SensorManager.getDefaultSensor()方法。
獲得手機支持的所有傳感器
Listsensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
Android傳感器類型表
加速度傳感器:TYPE_ACCELEROMETER
周圍溫度傳感器:TYPE_AMBIENT_TEMPERATURE
重力傳感器:TYPE_GRAVITY
陀螺儀傳感器:TYPE_GYROSCOPE
光照傳感器:TYPE_LIGHT
線性加速度傳感器:TYPE_LINEAR_ACCELERATION
磁力傳感器:TYPE_MAGNETIC_FIELD
方向傳感器: TYPE_ORIENTATION
壓力傳感器:TYPE_PRESSURE
接近傳感器:TYPE_PROXIMITY
相對濕度傳感器:TYPE_RELATIVE_HUMIDITY
旋轉矢量傳感器:TYPE_ROTATION_VECTOR
溫度傳感器: TYPE_TEMPERATURE
傳感器使用實踐
這里以方向傳感器為例
方向傳感器的獲取方式
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
上面這個,對,已經被google棄用了,了解就好。
Android中的坐標系
小喬畫圖的有點丑,將就著看吧,Z軸默認垂直于地面,所謂獲取的三個Values數組即對應手機與Z,Y,X形成的夾角,后面會說明,
前面說了,TYPE_ORIENTATION已被棄用,那么最新的方向傳感器是如何做的呢?
事實上,Android 獲取手機旋轉的方向和角度是通過加速度傳感器和地磁傳感器共同計算得出的
OK,我們這時候是需要同時使用兩個傳感器的,看代碼
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);
同時使用了加速度傳感器和地磁傳感器
獲取旋轉矩陣數組R
SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);
獲取手機旋轉數據
SensorManager.getOrientation(R, values);
values 是一個長度為 3 的 float 數組,手機在各個方向上的旋轉數據都會被存放到這個數組當中。
對應關系:
values[0]->Z軸、values[1]->X軸、values[2]->Y軸
values[0]的取值范圍是-180到180 度,其中±180 度表示正南方向,0 度表示正北方向,-90 度表示正西方向,90 度表示正東方向,如圖
所謂,實踐是檢驗真理的唯一標準,這是我檢測后自行畫的,大家看一下就明白該怎么根據獲取到的角度來做對應的處理了
一個完整的方向傳感器封裝類
public class DirectionSensorUtils implements SensorEventListener {
private static DirectionSensorUtils sInstance;
private SensorManager sensorManager;
float[] accelerometerValues = new float[3];
float[] magneticValues = new float[3];
public static DirectionSensorUtils getInstance() {
if (sInstance == null) {
synchronized (DirectionSensorUtils.class) {
if (sInstance == null) {
sInstance = new DirectionSensorUtils();
}
}
}
return sInstance;
}
private CompassChange compassChange;
public interface CompassChange {
void onCompassChange( float rotateDegree);
}
//注冊傳感器
public void registerSensor(Context context, CompassChange compassChange) {
this.compassChange = compassChange;
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
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);
}
//解除傳感器注冊
public void unregisterSensor() {
if (sensorManager != null) {
sensorManager.unregisterListener(this);
}
}
@Override
public void onSensorChanged(SensorEvent event) {
// 判斷當前是加速度傳感器還是地磁傳感器
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
// 通過clone()獲取不同的values引用
accelerometerValues = event.values.clone();
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
magneticValues = event.values.clone();
}
//獲取地磁與加速度傳感器組合的旋轉矩陣
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軸
//使用前請進行轉換,因為獲取到的值是弧度,示例如下
// Math.toDegrees(values[0]);
// Math.toDegrees(values[1]);
// Math.toDegrees(values[2]);
float rotateDegree = -(float) Math.toDegrees(values[0]);
if (compassChange!=null){
compassChange.onCompassChange(rotateDegree);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}