refs: https://developer.android.google.cn/guide/topics/sensors/
1. 傳感器分類
Android平臺支持三個(gè)大類的傳感器
- Motion sensors(運(yùn)動傳感器)
這些傳感器測量加速力脆诉,并沿三個(gè)軸的旋轉(zhuǎn)力十绑。此類別包括加速度計(jì),重力感應(yīng)器, 陀螺儀和旋轉(zhuǎn)矢量傳感器来屠。 - Environmental sensors (環(huán)境傳感器)
這些傳感器測量各種環(huán)境參數(shù),例如環(huán)境空氣溫度和壓力,照明和濕度。此類別包括氣壓計(jì)躲舌,光度計(jì),和溫度計(jì)性雄。 - Position sensors (位置傳感器)
這些傳感器測量設(shè)備的物理位置没卸。這個(gè)類別包括方向傳感器和磁力計(jì)。
目前 Android 平臺支持的傳感器type如下:
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 the TYPE_AMBIENT_TEMPERATURE sensor in API Level 14 |
Monitoring temperatures. |
2. 常規(guī)使用流程
2.1 常用api
SensorManager:可以通過這個(gè)類去創(chuàng)建一個(gè)傳感器服務(wù)的實(shí)例毅贮,這個(gè)類提供的各種方法可以訪問傳感器列表办悟、注冊或解除注冊傳感器事件監(jiān)聽、獲取方位信息等滩褥。
Sensor:用于創(chuàng)建一個(gè)特定的傳感器實(shí)例,這個(gè)類提供的方法可以讓你決定一個(gè)傳感器的功能炫加。
SensorEvent:系統(tǒng)會通過這個(gè)類創(chuàng)建一個(gè)傳感器事件對象瑰煎,提供了一個(gè)傳感器的事件信息,包含一下內(nèi)容俗孝,原生的傳感器數(shù)據(jù)酒甸、觸發(fā)傳感器的事件類型、精確的數(shù)據(jù)以及事件發(fā)生的時(shí)間赋铝。
SensorEventListener:可以通過這個(gè)接口創(chuàng)建兩個(gè)回調(diào)用法來接收傳感器的事件通知插勤,比如當(dāng)傳感器的值發(fā)生變化時(shí)。
2.2 使用方式
第一步:獲取SensorManager對象
第二步:獲取Sensor對象
第三步:注冊Sensor對象
第四步:重寫onAccuracyChanged,onSensorChanged這兩個(gè)方法
第五步:注銷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實(shí)例對象
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//第二步:通過SensorManager實(shí)例對象獲得想要的傳感器對象:參數(shù)決定獲取哪個(gè)傳感器
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
}
//第四步:必須重寫的兩個(gè)方法:onAccuracyChanged农尖,onSensorChanged
/**
* 傳感器精度發(fā)生改變的回調(diào)接口
*/
@Override
public final void onAccuracyChanged(Sensor sensor, int accuracy) {
//TODO 在傳感器精度發(fā)生改變時(shí)做些操作析恋,accuracy為當(dāng)前傳感器精度
}
/**
* 傳感器事件值改變時(shí)的回調(diào)接口:執(zhí)行此方法的頻率與注冊傳感器時(shí)的頻率有關(guān)
*/
@Override
public final void onSensorChanged(SensorEvent event) {
// 大部分傳感器會返回三個(gè)軸方向x,y,x的event值,值的意義因傳感器而異
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
//TODO 利用獲得的三個(gè)float傳感器值做些操作
}
/**
* 第三步:在獲得焦點(diǎn)時(shí)注冊傳感器并讓本類實(shí)現(xiàn)SensorEventListener接口
*/
@Override
protected void onResume() {
super.onResume();
/*
*第一個(gè)參數(shù):SensorEventListener接口的實(shí)例對象
*第二個(gè)參數(shù):需要注冊的傳感器實(shí)例
*第三個(gè)參數(shù):傳感器獲取傳感器事件event值頻率:
* SensorManager.SENSOR_DELAY_FASTEST = 0:對應(yīng)0微秒的更新間隔盛卡,最快助隧,1微秒 = 1 % 1000000秒
* SensorManager.SENSOR_DELAY_GAME = 1:對應(yīng)20000微秒的更新間隔,游戲中常用
* SensorManager.SENSOR_DELAY_UI = 2:對應(yīng)60000微秒的更新間隔
* SensorManager.SENSOR_DELAY_NORMAL = 3:對應(yīng)200000微秒的更新間隔
* 鍵入自定義的int值x時(shí):對應(yīng)x微秒的更新間隔
*
*/
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
/**
* 第五步:在失去焦點(diǎn)時(shí)注銷傳感器
*/
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
}
注意滑沧,設(shè)備不一定支持你需要的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<Sensor> deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
3. 常用Sensor的解釋
Accelerometer 加速度傳感器
加速度傳感器又叫G-sensor,返回x滓技、y哩牍、z三軸的加速度數(shù)值。
該數(shù)值包含地心引力的影響令漂,單位是m/s^2膝昆。
將手機(jī)平放在桌面上,x軸默認(rèn)為0洗显,y軸默認(rèn)0外潜,z軸默認(rèn)9.81。 將手機(jī)朝下放在桌面上挠唆,z軸為-9.81处窥。 將手機(jī)向左傾斜,x軸為正值玄组。 將手機(jī)向右傾斜滔驾,x軸為負(fù)值。 將手機(jī)向上傾斜俄讹,y軸為負(fù)值哆致。 將手機(jī)向下傾斜,y軸為正值患膛。
Magnetometer 磁力傳感器
磁力傳感器簡稱為M-sensor摊阀,返回x、y踪蹬、z三軸的環(huán)境磁場數(shù)據(jù)胞此。
該數(shù)值的單位是微特斯拉(micro-Tesla),用uT表示跃捣。 單位也可以是高斯(Gauss)漱牵,1Tesla=10000Gauss。 硬件上一般沒有獨(dú)立的磁力傳感器疚漆,磁力數(shù)據(jù)由電子羅盤傳感器提供(E-compass)酣胀。
電子羅盤傳感器同時(shí)提供下文的方向傳感器數(shù)據(jù)刁赦。
Orientation 方向傳感器
方向傳感器簡稱為O-sensor,返回三軸的角度數(shù)據(jù)闻镶,方向數(shù)據(jù)的單位是角度甚脉。
為了得到精確的角度數(shù)據(jù),E-compass(電子羅盤傳感器)需要獲取G-sensor(加速度傳感器)的數(shù)據(jù)儒溉, 經(jīng)過計(jì)算生產(chǎn)O-sensor數(shù)據(jù)宦焦,否則只能獲取水平方向的角度。
方向傳感器提供三個(gè)數(shù)據(jù)顿涣,分別為azimuth波闹、pitch和roll。
azimuth:方位涛碑,返回水平時(shí)磁北極和Y軸的夾角精堕,范圍為0°至360°。 0°=北蒲障,90°=東歹篓,180°=南,270°=西揉阎。
pitch:x軸和水平面的夾角庄撮,范圍為-180°至180°。 當(dāng)z軸向y軸轉(zhuǎn)動時(shí)毙籽,角度為正值洞斯。
roll:y軸和水平面的夾角,由于歷史原因坑赡,范圍為-90°至90°烙如。 當(dāng)x軸向z軸移動時(shí),角度為正值毅否。
電子羅盤在獲取正確的數(shù)據(jù)前需要進(jìn)行校準(zhǔn)亚铁,通常可用8字校準(zhǔn)法螟加。 8字校準(zhǔn)法要求用戶使用需要校準(zhǔn)的設(shè)備在空中做8字晃動徘溢, 原則上盡量多的讓設(shè)備法線方向指向空間的所有8個(gè)象限。
Gyroscope 陀螺儀傳感器
陀螺儀傳感器叫做Gyro-sensor捆探,返回x甸昏、y、z三軸的角速度數(shù)據(jù)徐许。
角速度的單位是radians/second。
根據(jù)Nexus S手機(jī)實(shí)測: 水平逆時(shí)針旋轉(zhuǎn)卒蘸,Z軸為正雌隅。 水平逆時(shí)針旋轉(zhuǎn)翻默,z軸為負(fù)。 向左旋轉(zhuǎn)恰起,y軸為負(fù)修械。 向右旋轉(zhuǎn),y軸為正检盼。 向上旋轉(zhuǎn)肯污,x軸為負(fù)。 向下旋轉(zhuǎn)吨枉,x軸為正蹦渣。
Ambient Light Sensor (環(huán)境)光線感應(yīng)傳感器
光線感應(yīng)傳感器檢測實(shí)時(shí)的光線強(qiáng)度,光強(qiáng)單位是lux(勒克司度)貌亭,其物理意義是照射到單位面積上的光通量柬唯。
光線感應(yīng)傳感器主要用于Android系統(tǒng)的LCD自動亮度功能。
可以根據(jù)采樣到的光強(qiáng)數(shù)值實(shí)時(shí)調(diào)整LCD的亮度圃庭。
Barometer Sensor (氣)壓力傳感器
壓力傳感器返回當(dāng)前的壓強(qiáng)锄奢,單位是百帕斯卡hectopascal(hPa)。
Temperature Sensor 溫度傳感器
溫度傳感器返回當(dāng)前的溫度剧腻。
Proximity Sensor (近)距離傳感器
又稱接近傳感器拘央,檢測物體與手機(jī)的距離,單位是cm(厘米)书在。
一些接近傳感器只能返回遠(yuǎn)和近兩個(gè)狀態(tài)灰伟, 因此,接近傳感器將最大距離返回遠(yuǎn)狀態(tài)蕊温,小于最大距離返回近狀態(tài)袱箱。 接近傳感器可用于接聽電話時(shí)自動關(guān)閉LCD屏幕以節(jié)省電量。
一些芯片集成了接近傳感器和光線傳感器兩者功能义矛。
Gravity 重力傳感器
重力傳感器簡稱GV-sensor发笔,輸出重力數(shù)據(jù)。
在地球上凉翻,重力數(shù)值為9.8了讨,單位是m/s^2。 坐標(biāo)系統(tǒng)與加速度傳感器相同制轰。 當(dāng)設(shè)備復(fù)位時(shí)前计,重力傳感器的輸出與加速度傳感器相同。
Linear Acceleration 線性加速度傳感器
線性加速度傳感器簡稱LA-sensor垃杖。
線性加速度傳感器是加速度傳感器減去重力影響獲取的數(shù)據(jù)男杈。 單位是m/s^2,坐標(biāo)系統(tǒng)與加速度傳感器相同调俘。
加速度傳感器伶棒、重力傳感器和線性加速度傳感器的計(jì)算公式如下: 加速度 = 重力 + 線性加速度
Rotation Vector 旋轉(zhuǎn)矢量傳感器
旋轉(zhuǎn)矢量傳感器簡稱RV-sensor旺垒。
旋轉(zhuǎn)矢量代表設(shè)備的方向,是一個(gè)將坐標(biāo)軸和角度混合計(jì)算得到的數(shù)據(jù)肤无。
RV-sensor輸出三個(gè)數(shù)據(jù): xsin(theta/2) ysin(theta/2) z*sin(theta/2) sin(theta/2)是RV的數(shù)量級先蒋。
RV的方向與軸旋轉(zhuǎn)的方向相同。 RV的三個(gè)數(shù)值宛渐,與cos(theta/2)組成一個(gè)四元組竞漾。 RV的數(shù)據(jù)沒有單位,使用的坐標(biāo)系與加速度相同窥翩。
舉例:
sensors_event_t.data[0] = x*sin(theta/2)
sensors_event_t.data[1] = ysin(theta/2)
sensors_event_t.data[2] = z*sin(theta/2)
sensors_event_t.data[3] = cos(theta/2)
其他傳感器
Step Detector 步數(shù)探測器
Step Counter 計(jì)步器
Significant Motion Detector 運(yùn)動檢測器
Game Rotation Vector 游戲旋轉(zhuǎn)矢量
Geomagnetic Rotation Vector 地磁旋轉(zhuǎn)矢量
Basic Gestures 基本手勢
Motion Accel 運(yùn)動加速度
4. 坐標(biāo)系統(tǒng)
手機(jī)的自然坐標(biāo)系
當(dāng)一個(gè)設(shè)備被放在其默認(rèn)的方向上時(shí)业岁,X軸是水平指向右的,Y軸是垂直向上的鳍烁,Z軸是指向屏幕正面之外的叨襟,即屏幕背面是Z的負(fù)值。
當(dāng)設(shè)備運(yùn)動或者旋轉(zhuǎn)的時(shí)候幔荒,這些坐標(biāo)軸是不會改變的糊闽,即它們是跟隨手機(jī)的。
即是說爹梁,手機(jī)坐標(biāo)系是跟隨設(shè)備的自然方向的(但是請記住自然方向不一定是豎直右犹,比如平板它的自然方向就很有可能是橫向)。
使用這個(gè)坐標(biāo)系的傳感器:
即是說它們的度數(shù)顯示了在手機(jī)的這三個(gè)軸上的數(shù)字大小姚垃。
屏幕旋轉(zhuǎn)
常常要考慮屏幕的旋轉(zhuǎn)念链,即屏幕畫面相對于自然方向的旋轉(zhuǎn)。
于是就需要使用 getRotation()方法來獲取屏幕的旋轉(zhuǎn)值积糯。
這個(gè)方法是Display類中的掂墓,跟傳感器不相關(guān)。
這個(gè)方法的返回值只對應(yīng)0看成,90,180,270四種旋轉(zhuǎn)情況君编,它說明屏幕顯示區(qū)域的旋轉(zhuǎn)情況。
世界坐標(biāo)系
有一些傳感器和方法使用相對于世界的坐標(biāo)系川慌,因?yàn)樗鼈兎祷氐臄?shù)據(jù)反映設(shè)備相對于地球及真實(shí)環(huán)境的位置信息吃嘿。
請見getOrientation() 方法,getRotationMatrix() 方法梦重,Orientation Sensor, 和 Rotation Vector Sensor兑燥。
getRotationMatrix()
getRotationMatrix()方法說明中,定義的世界坐標(biāo)系如下:
?X軸平行于地面琴拧,指向東方降瞳。
Y軸平行于地面,指向北極方向蚓胸。
Z軸垂直于地面力崇,指向天空斗塘。
getOrientation()
getOrientation() 方法中所用的坐標(biāo)系與上面的不同:
?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.
并且這三個(gè)角度值都是以弧度做單位八毯,逆時(shí)針方向?yàn)檎?/p>
方向傳感器的返回值說明
方向傳感器是利用加速度計(jì)和地磁場傳感器得到自己的數(shù)據(jù)搓侄。
方向傳感器比較特殊,因?yàn)樗臄?shù)值是相對于絕對方向的话速。它得到的是手機(jī)設(shè)備的絕對姿態(tài)值讶踪。
一個(gè)方向傳感器得到的三維數(shù)據(jù)如下:
(參見http://developer.android.com/guide/topics/sensors/sensors_position.html#sensors-pos-orient)
方向傳感器返回的都是角度值,以度數(shù)為單位泊交。
注意下面說的x乳讥、y、z軸均是手機(jī)自身的坐標(biāo)軸廓俭。
第一個(gè)角度:Azimuth (degrees of rotation around the z axis).
表示手機(jī)自身的y軸與地磁場北極方向的角度云石,即手機(jī)頂部朝向與正北方向的角度。
(This is the angle between magnetic north and the device's y axis. )
當(dāng)手機(jī)繞著自身的z軸旋轉(zhuǎn)時(shí)法严,該角度值將發(fā)生改變痊土。
例如該角度值為0時(shí)挽封,表示手機(jī)頂部指向正北;該角度為90度時(shí)宽菜,代表手機(jī)頂部指向正東;該角度為180度時(shí)竿报,代表手機(jī)頂部指向正南铅乡;該角度為270度時(shí),代表手機(jī)頂部指向正西仰楚。
第二個(gè)角度:Pitch (degrees of rotation around the x axis).
表示手機(jī)頂部或尾部翹起的角度隆判。
當(dāng)手機(jī)繞著自身的x軸旋轉(zhuǎn),該角度會發(fā)生變化僧界,值的范圍是-180到180度侨嘀。
當(dāng)z軸正向朝著y軸正向旋轉(zhuǎn)時(shí),該角度是正值捂襟;當(dāng)z軸正向朝著y軸負(fù)向旋轉(zhuǎn)時(shí)咬腕,該角度是負(fù)值。
假設(shè)將手機(jī)屏幕朝上水平放在桌子上葬荷,如果桌子是完全水平的涨共,該角度應(yīng)該是0纽帖。
假如從手機(jī)頂部抬起,直到將手機(jī)沿x軸旋轉(zhuǎn)180度(屏幕向下水平放在桌面上)举反,這個(gè)過程中懊直,該角度值會從0變化到-180。
如果從手機(jī)底部開始抬起火鼻,直到將手機(jī)沿x軸旋轉(zhuǎn)180度(屏幕向下水平放在桌面上)室囊,該角度的值會從0變化到180。
第三個(gè)角度:Roll (degrees of rotation around the y axis).
表示手機(jī)左側(cè)或右側(cè)翹起的角度魁索。
當(dāng)手機(jī)繞著自身x軸旋轉(zhuǎn)時(shí)融撞,該角度值將會發(fā)生變化,取值范圍是-90到90度粗蔚。
當(dāng)z軸正向朝著x軸正向旋轉(zhuǎn)時(shí)尝偎,該角度是負(fù)值;
當(dāng)z軸正向朝著x軸負(fù)向旋轉(zhuǎn)時(shí)鹏控,該角度是正值致扯。\
(這里跟官方文檔的說法有點(diǎn)不太一致,即第三個(gè)角度的正負(fù)號正好相反牧挣,我不知道是文檔寫錯(cuò)了急前,還是它用了別的什么坐標(biāo)系)。
因?yàn)橥ㄟ^真機(jī)測試瀑构,結(jié)果如下:
將手機(jī)屏幕朝上水平放在桌子上裆针,如果桌子是完全水平的,該角度應(yīng)該是0寺晌。
假如將手機(jī)左側(cè)逐漸抬起世吨,直到將手機(jī)沿Y軸旋轉(zhuǎn)90度(手機(jī)與桌面垂直),在這個(gè)旋轉(zhuǎn)過程中呻征,該角度會從0變化到-90耘婚。
如果從手機(jī)的右側(cè)開始抬起,直到將手機(jī)沿Y軸旋轉(zhuǎn)90度(手機(jī)與桌面垂直)陆赋,該角度的值會從0變化到90度沐祷。
其他說明:
由于需要計(jì)算,所以方向傳感器的準(zhǔn)確度和精度都會受到影響攒岛。
官方文檔上說赖临,只有當(dāng)?shù)谌齻€(gè)roll的角度值為0的時(shí)候得到的值比較可靠。
specifically, this sensor is only reliable when the roll component is 0灾锯。
所以從Android 2.2 (API level 8)開始兢榨,不建議使用方向傳感器。
建議使用 getRotationMatrix()
和getOrientation()
結(jié)合來計(jì)算方向值。
也可以利用 remapCoordinateSystem()
方法來進(jìn)行一些方向值向其他坐標(biāo)系的轉(zhuǎn)換吵聪。
5. 運(yùn)動傳感器 Motion Sensors
Android平臺提供了一些監(jiān)控設(shè)備運(yùn)動的傳感器凌那。
運(yùn)動傳感器中有兩個(gè)永遠(yuǎn)是基于硬件的,即加速度計(jì)和陀螺儀(accelerometer and gyroscope)吟逝。
運(yùn)動傳感器中有三個(gè)是既可以基于硬件又可以基于軟件的帽蝶,即重力感應(yīng)器、線性加速度計(jì)澎办、旋轉(zhuǎn)向量傳感器嘲碱。
運(yùn)動傳感器用來監(jiān)測設(shè)備的運(yùn)動,比如傾斜局蚀,震動,旋轉(zhuǎn)或搖擺(tilt, shake, rotation, or swing)恕稠。
運(yùn)動傳感器的返回值
所有的運(yùn)動傳感器都返回一個(gè)多維的向量值琅绅,保存在SensorEvent的values數(shù)組中。
參見鏈接:https://developer.android.google.cn/guide/topics/sensors/sensors_motion
加速度計(jì)Accelerometer
加速度傳感器測量作用于設(shè)備的加速度Ad:
Ad = -∑Fs / mass
公式中是施加于設(shè)備的外力之和和設(shè)備質(zhì)量的比值鹅巍。
但是千扶,重力加速度會影響這個(gè)公式:
Ad = -g -∑F / mass
我的理解是:Ad是設(shè)備的實(shí)際加速度(我們想知道的值),而加速度的讀數(shù)是一個(gè)受到了重力影響的讀數(shù)骆捧。即Ad+9.81澎羞;
比如,把設(shè)備靜止地平放在桌面上敛苇,這時(shí)妆绞,Ad是零;加速度計(jì)的讀數(shù)大小是重力加速度的數(shù)值g = 9.81 m/s2枫攀。這個(gè)常量值的大小可以用STANDARD_GRAVITY來表示括饶。
而當(dāng)設(shè)備自由落體時(shí),它以9.81 m/s2的加速度向地面運(yùn)動来涨,Ad為-9.81 m/s2图焰,這時(shí)加速度計(jì)的讀數(shù)應(yīng)該是0。
坐標(biāo)系的設(shè)置
當(dāng)把設(shè)備平放在桌面上蹦掐,以它的自然方向放置:
如果你從設(shè)備左邊推它技羔,它往右移,這時(shí)它的X加速度值是正的卧抗;
如果你從設(shè)備下方推它藤滥,它將朝著遠(yuǎn)離你的方向移動,這時(shí)它的Y加速度值是正的颗味;
如果你把設(shè)備以A m/s2的加速度推向天空超陆,Z軸的加速度值應(yīng)當(dāng)?shù)扔贏 + 9.81,(which corresponds to the acceleration of the device (+A m/s2) minus the force of gravity (-9.81 m/s2))。
重力傳感器Gravity Sensor
重力傳感器測量的是重力值在三個(gè)方向上的大小时呀。
重力傳感器和加速度傳感器的單位一樣m/s2张漂,并且它們使用的坐標(biāo)系也一樣。
當(dāng)設(shè)備靜止時(shí)谨娜,重力傳感器的輸出和加速度傳感器的輸出是完全一致的航攒。
陀螺儀Gyroscope
陀螺儀測量的是設(shè)備繞三個(gè)軸向的旋轉(zhuǎn)速度,單位是rad/s趴梢。
所使用的坐標(biāo)系統(tǒng)仍然和加速度計(jì)的一樣漠畜。
旋轉(zhuǎn)的值在逆時(shí)針方向?yàn)檎次氚校绻粋€(gè)觀察者從某個(gè)軸的正向某點(diǎn)向原點(diǎn)看憔狞,如果觀察到的旋轉(zhuǎn)是逆時(shí)針的,則是一個(gè)正值的旋轉(zhuǎn)彰阴。這是一個(gè)關(guān)于旋轉(zhuǎn)方向的標(biāo)準(zhǔn)的數(shù)學(xué)定義瘾敢,注意,這個(gè)和方向傳感器所用的定義不同尿这。
陀螺儀的輸出需要對時(shí)間積分來計(jì)算簇抵。有一個(gè)例子見:http://developer.android.com/guide/topics/sensors/sensors_motion.html
標(biāo)準(zhǔn)的陀螺儀提供原始的旋轉(zhuǎn)數(shù)據(jù),對噪聲和漂移沒有過濾和校正射众。
實(shí)際運(yùn)用時(shí)碟摆,陀螺儀的噪聲和漂移會引入錯(cuò)誤,所以需要被補(bǔ)償叨橱。通车渫桑可以通過其他傳感器(重力傳感器或加速度計(jì))來檢測噪聲和漂移。
線性加速度計(jì)Linear Accelerometer
線性加速度計(jì)提供了沿著每個(gè)軸的加速度值雏逾,并且是排除了重力的值嘉裤。
即:linear acceleration = acceleration - acceleration due to gravity
它所使用的單位和坐標(biāo)系都和加速度計(jì)相同。
線性加速度計(jì)有一個(gè)偏移值(offset)栖博,你需要移除這個(gè)偏移值屑宠,比較簡單的方法是在你的應(yīng)用一開始設(shè)置一個(gè)標(biāo)定步驟:讓用戶把設(shè)備放在桌子上,然后讀出三個(gè)軸的offset值仇让,之后典奉,在從線性加速度計(jì)中讀數(shù)的時(shí)候減去這個(gè)offset值,就可以得到實(shí)際的線性加速度值丧叽。
旋轉(zhuǎn)向量傳感器Rotation Vector Sensor
旋轉(zhuǎn)向量用一個(gè)角度和軸向的組合來表達(dá)設(shè)備的方向信息卫玖。比如,設(shè)備繞著某一個(gè)軸向旋轉(zhuǎn)了一個(gè)角度 θ踊淳。
旋轉(zhuǎn)向量的三個(gè)元素的值如下:
x*sin(θ/2)
y*sin(θ/2)
z*sin(θ/2)
rotation vector的大小是sin(θ/2)假瞬,方向是它的旋轉(zhuǎn)軸向陕靠。
旋轉(zhuǎn)向量沒有單位。
X軸指向東脱茉,Y軸指向北剪芥,Z軸與地面垂直,指向天空琴许。
6. 位置傳感器Position Sensors
Android平臺提供了兩種決定設(shè)備位置的傳感器:
地磁場傳感器和方向傳感器(the geomagnetic field sensor and the orientation sensor)税肪。
還有一種傳感器用于檢測設(shè)備正面和其他物體的距離,叫做接近傳感器(proximity sensor)榜田。
地磁場傳感器和接近傳感器是基于硬件的益兄。
方向傳感器是基于軟件的,它的數(shù)據(jù)是根據(jù)加速度計(jì)和地磁場傳感器導(dǎo)出的箭券。
但是方向傳感器自從Android 2.2 (API Level 8)開始就被廢棄了净捅。
位置傳感器也是返回一個(gè)多維向量,放在 SensorEvent
中的values數(shù)組中辩块。
返回值見表:
方向傳感器Orientation Sensor
方向傳感器是根據(jù)地磁場傳感器和加速度計(jì)推導(dǎo)出輸出數(shù)據(jù)的灸叼。
使用這兩個(gè)硬件傳感器,方向傳感器為下面三個(gè)方向提供了數(shù)據(jù):
1. Azimuth:繞Z軸旋轉(zhuǎn)的度數(shù)庆捺。這是設(shè)備的y軸和地磁場北極的夾角。比如屁魏,設(shè)備的y軸指向東滔以,這個(gè)度數(shù)就為90。
2. Pitch:繞X軸旋轉(zhuǎn)的度數(shù)氓拼。當(dāng)設(shè)備的z軸朝著y軸正向旋轉(zhuǎn)時(shí)你画,這個(gè)值是正值,反之桃漾,當(dāng)設(shè)備的z軸朝著y軸的負(fù)向旋轉(zhuǎn)時(shí)坏匪,這個(gè)值為負(fù)值。它的取值范圍是-180到180撬统。
3. Roll:繞Y軸旋轉(zhuǎn)的度數(shù)适滓。當(dāng)設(shè)備的z軸朝著x軸正向旋轉(zhuǎn)時(shí),這個(gè)值是正值恋追,反之凭迹,當(dāng)設(shè)備的z軸朝著x軸的負(fù)向旋轉(zhuǎn)時(shí),這個(gè)值為負(fù)值苦囱。它的取值范圍是-90到90嗅绸。
注意這個(gè)定義是非常特殊的,因?yàn)樗陧槙r(shí)針旋轉(zhuǎn)的時(shí)候是正值撕彤,而數(shù)學(xué)上總是逆時(shí)針為正值鱼鸠。
因?yàn)榉较騻鞲衅餍枰罅康奶幚磉\(yùn)算,所以它的準(zhǔn)確度和精度都有所下降。后來蚀狰,自Android 2.2 (API level 8)愉昆,方向傳感器被廢棄。自Android 4.4W (API level 20)造锅,方向傳感器類型被廢棄撼唾。
官方建議使用下面的方法:
利用getRotationMatrix()結(jié)合getOrientation()方法可以計(jì)算方向值。
https://developer.android.google.cn/guide/topics/sensors/sensors_position#sensors-pos-orient
還可以利用remapCoordinateSystem()把方向值轉(zhuǎn)換到你的應(yīng)用的參考坐標(biāo)系哥蔚。
地磁場傳感器Geomagnetic Field Sensor
地磁場傳感器監(jiān)測地球地磁場變化倒谷。
傳感器提供三個(gè)坐標(biāo)上的原始的磁場強(qiáng)度值(in μT)。
一般情況下糙箍,你不需要直接使用這個(gè)傳感器渤愁,你可以使用旋轉(zhuǎn)向量傳感器來決定原始的旋轉(zhuǎn)運(yùn)動;你也可以使用加速度計(jì)和地磁場傳感器并結(jié)合getRotationMatrix()方法來獲得旋轉(zhuǎn)矩陣和傾斜矩陣深夯。
你可以結(jié)合 getOrientation()
和 getInclination()
方法來使用這些矩陣抖格,從而得到方位和地磁場偏移數(shù)據(jù)。
接近傳感器Proximity Sensor
接近傳感器可以讓你得到設(shè)備離另一個(gè)物體的距離咕晋。
接近傳感器通常用于檢測設(shè)備正面和用戶頭部的距離雹拄,比如用戶正在打電話。
大多數(shù)Proximity Sensor返回絕對的距離數(shù)值掌呜,以cm為單位滓玖。但是也有一些只返回近或者遠(yuǎn)。
7. Android Sensor Framework 概覽
7.1 Overview
Android Sensor Framework 的整體架構(gòu)如圖所示:
Android Sensor Framework 可以分為 3 大部分质蕉,各個(gè)部分的主要功能如下:
SDK
這一部分主要功能是為 Application 提供 Java API 接口势篡,以便 Application 可以開啟所需的 Sensor 并獲取數(shù)據(jù)。
Framework
這一部分主要有 Sensor Service 構(gòu)成模暗,主要實(shí)現(xiàn)了 Sensor 數(shù)據(jù)流和控制流禁悠。
Libraries
這一部分是 Sensor 的硬件抽象層(HAL),它實(shí)現(xiàn)了 Sensor 的具體操作和數(shù)據(jù)獲取功能兑宇。同時(shí)碍侦,它還進(jìn)行虛擬 Sensor,電子羅盤等相關(guān)的算法處理過程顾孽。此模塊通常以一個(gè)動態(tài)鏈接庫的形式提供祝钢。
7.2 Android Sensor Framework 類圖
7.3 Android Sensor SDK
上圖中的 Client 部分內(nèi)容即為 Android Sensor SDK 的主要構(gòu)成。主要類的主要功能如下:
SensorManager
該類主要封裝了 Sensor 相關(guān)的 API 若厚,提供給 Application 使用拦英。
文件路徑:frameworks/base/core/java/android/hardware/SensorManager.java
SystemSensorManager
該類主要實(shí)現(xiàn) SensorManager 控制和數(shù)據(jù)獲取的邏輯。
文件路徑:frameworks/base/core/java/android/hardware/SystemSensorManager.java
android_hardware_SensorManager.cpp
該文件負(fù)責(zé) jave 層和 native 層通信的 JNI 實(shí)現(xiàn)测秸,上層的 Java 代碼通過 JNI 調(diào)用 Native 層提供的服務(wù)疤估。
文件路徑:frameworks/base/core/jni/android_hardware_SensorManager.cpp
SensorManager.cpp
Sensor 在 Native 層的客戶端灾常,負(fù)責(zé)與服務(wù)端 SensorService.cpp 的通信
文件路徑:frameworks/native/libs/gui/SensorManager.cpp
7.4 Android Sensor Native Framework
上圖中的 Server 部分內(nèi)容即為 Android Sensor Native Framwork 的主要構(gòu)成。主要類的主要功能如下:
SensorService.cpp
SensorService 是 Android Sensor Framework 最核心的模塊铃拇,它實(shí)現(xiàn)了主要的 Sensor控制流和數(shù)據(jù)流邏輯钞瀑,完成 Sensor 參數(shù)配置,數(shù)據(jù)分發(fā)慷荔,Client 請求處理等功能雕什。
文件路徑:frameworks/native/services/sensorservice/SensorService.cpp
BinderService
BinderService 是 Android Service 框架的主要類,它提供了 Service 的生命周期管理显晶、進(jìn)程間通信贷岸、請求響應(yīng)處理等功能。Android 中的絕大部分 Service 都會繼承此類磷雇。
文件路徑:frameworks/native/include/binder/BinderService.h
BnSensorServer
該類提供類 Sensor 信息獲取以及 SensorEventConnection 創(chuàng)建的功能偿警。
文件路徑:frameworks/native/include/gui/ISensorServer.h
SensorEventConnection
SensorEventConnection 是 Sensor 數(shù)據(jù)的傳輸通道,當(dāng) Client 開始監(jiān)聽某一個(gè) Sensor 是唯笙,一個(gè)對應(yīng)的 SensorEventConnection 將會被創(chuàng)建螟蒸,Server 端在接收到 Sensor 數(shù)據(jù)后,通過寫入到 SensorEventConnection 傳遞給 Client 端崩掘。
文件路徑:frameworks/native/libs/gui/ISensorEventConnection.cpp
Bittube
該類為單向字節(jié)管道七嫌,提供進(jìn)程間單向數(shù)據(jù)通信功能。SensorEventConnection 是基于 Bittube 實(shí)現(xiàn)的苞慢。
文件路徑:frameworks/native/libs/gui/BitTube.cpp
SensorDevice
該類負(fù)責(zé)管理和維護(hù)系統(tǒng)中的所有 Sensor抄瑟,封裝了 Sensor 的使能、配置枉疼、數(shù)據(jù)讀取等功能。
文件路徑:frameworks/native/services/sensorservice/SensorDevice.cpp
7.5 Android Sensor HAL
Android 定義了一系列 Sensor HAL 接口鞋拟,實(shí)際的 Sensor HAL 庫需要實(shí)現(xiàn)這些接口骂维,主要的接口如下:
7.5.1 SensorList
SensorList 定義了 HAL 層提供的 Sensor,提供 Sensor 類型贺纲、供應(yīng)商航闺、功耗等信息。同時(shí)猴誊,HAL 層需要實(shí)現(xiàn)獲取 SensorList 的回調(diào)接口潦刃。
7.5.2 sensors_module_t
HAL 層需要定義一個(gè) sensors_module_t,供系統(tǒng)在啟動時(shí)加載 Sensor HAL 動態(tài)庫懈叹。sensors_module_t 向上層注冊獲取 SensorList 和獲取 Sensor 控制接口的相關(guān)回調(diào)函數(shù)乖杠。
7.5.3 Sensor 控制和數(shù)據(jù)獲取接口
HAL 層還需要提供實(shí)際控制和獲取 Sensor 數(shù)據(jù)的接口,SensorService 中對 Sensor 的控制和數(shù)據(jù)的獲取最終會調(diào)用到這些接口澄成。
7.6 Android Sensor Framework的初始化流程
7.6.1 Android Sensor Service 初始化
圖片 3Kernel 在啟動完成后胧洒,會執(zhí)行 init 程序畏吓,該程序接著解析 init.rc 文件,啟動 zygote卫漫,最終會執(zhí)行 Zyoteinit.java 中的 main 函數(shù)菲饼。
在 Zygoteinit 的main 函數(shù)執(zhí)行過程中,會調(diào)用 startSystemServer 接口列赎,該接口最終會調(diào)用 native 層的 nativeforkSystemServer 接口宏悦,進(jìn)而啟動 SystemServer ,調(diào)用其 main 函數(shù)包吝。
在 SystemServer 的 main 函數(shù)中饼煞,會調(diào)用對應(yīng)的 nativeInit 接口。在 nativeInit 中漏策,會創(chuàng)建第一個(gè) SensorService 實(shí)例派哲。當(dāng) SensorService 第一個(gè)實(shí)例創(chuàng)建時(shí),其 onFirstRef 接口將會被調(diào)用掺喻。
圖片 4在 SensorService 的 onFirstRef 接口中芭届,會創(chuàng)建 SensorDevice 的實(shí)例。在 SensorDevice 的構(gòu)造函數(shù)中感耙,會調(diào)用 hw_get_module 接口加載 Sensor HAL 的動態(tài)庫褂乍,接著調(diào)用 Sensor HAL 提供的 open 接口,執(zhí)行 Sensor HAL 的初始化即硼。 接著 SensorService 通過 SensorDevice逃片,調(diào)用 Sensor HAL 提供的 get_sensors_list 接口,獲取所支持的 Sensor 信息只酥。 而后褥实,SensorService 會創(chuàng)建一個(gè) Looper 和 SensorEventAckReceiver。其中 Looper 用于 enable sensor 后裂允,進(jìn)行數(shù)據(jù)的接收损离;而 SensorEventAckReceiver 則用于在 dispatch wake up sensor event 給上層后,接收上層返回的確認(rèn) ACK绝编。 至此僻澎,SensorService 初始化完畢。
7.6.2 Android Sensor HAL 加載
在 SensorService 創(chuàng)建 SensorDevice 時(shí)十饥,會調(diào)用 hw_get_module 接口加載 SensorHAL 的動態(tài)庫文件窟勃。 在64位的系統(tǒng)中,hw_get_module 接口會在 /vendor/lib64/hw 和 /system/lib64/hw 目錄下搜索 SensorHAL 動態(tài)庫文件逗堵,前者的優(yōu)先級高秉氧。 hw_get_module 會獲取依次獲取 “ro.hardware.sensors”,”ro.hardware”蜒秤,”ro.product.board”谬运,”ro.board.platform”隙赁,”ro.arch” property 的值作為 subname,并以 sensors.subname.so 作為 SensorHAL 動態(tài)庫的文件名梆暖,在上述兩個(gè)目錄中搜索文件是否存在伞访,如果都沒有搜索到,那么最后會用 sensors.default.so 作為文件名轰驳,進(jìn)行搜索厚掷。 當(dāng)搜索到 SensorHAL 的動態(tài)庫文件后,就會調(diào)用 load 接口進(jìn)行加載操作级解。 具體的流程可以查看參考鏈接中的源代碼:
7.6.3 Android Sensor Manager 初始化
APP 在獲取 Sensor 數(shù)據(jù)前冒黑,需要獲取一個(gè) SensorManager 對象。而在其構(gòu)造函數(shù)中勤哗,會先調(diào)用 nativeClassInit 和 nativeGetNextSensor 獲取系統(tǒng)支持的所有 Sensor 的參數(shù)(注抡爹,nativeClassInit 只會調(diào)用一次),包括名稱芒划、類型等參數(shù)冬竟。后續(xù)的相關(guān)接口,會用到這些參數(shù)民逼。
7.7 Android Sensor Framework的數(shù)據(jù)流程分析
當(dāng)上層調(diào)用 registerListener 接口時(shí)泵殴,相應(yīng)的 sensor 就會被 enable。SensorService 在調(diào)用 HAL 提供的 enable 接口前拼苍,會先調(diào)用 batch 接口笑诅,對 sensor 的采樣率、數(shù)據(jù)上報(bào)頻率等進(jìn)行配置疮鲫。另外吆你,如果 sensor 已經(jīng)被 enable 了,那么 SensorService 就只調(diào)用 batch 和 flush 接口俊犯。 SensorService 在 onFirstRef 時(shí)創(chuàng)建了一個(gè) Looper早处,該 Looper 的執(zhí)行線程會調(diào)用 poll 接口,并阻塞在 sensor 的數(shù)據(jù)管道瘫析,當(dāng) sensor 有數(shù)據(jù)返回時(shí),SensorService 會通過 SensorEventQueue 發(fā)送到上層默责,并最終分發(fā)到各個(gè) listener贬循。