Android传感器-开发指南
大部分Android平臺(tái)的設(shè)備都帶有多個(gè)傳感器,使你能監(jiān)視其方位和運(yùn)動(dòng)狀態(tài)的變化。很多設(shè)備還有其它類型的傳感器,讓你能感知周圍的環(huán)境條件,比如溫度、壓力、濕度和光線。你可以利用Android的傳感器框架訪問這些傳感器,并獲取原始的傳感器數(shù)據(jù)。
傳感器框架提供了豐富的類和接口,能幫助你完成很多與傳感器有關(guān)的工作。比如,你可以用傳感器框架來進(jìn)行:
- 確定設(shè)備上可用的傳感器
- 確定某個(gè)傳感器的性能,比如量程、制造商、能耗、分辨率等。
- 讀取傳感器的原始數(shù)據(jù)并指定最小讀取頻率
- 注冊及注銷監(jiān)聽傳感器變化的傳感器事件偵聽器
本文概述了Android平臺(tái)可用的傳感器,并簡要介紹了傳感器框架。
傳感器介紹
Android傳感器框架能讓你訪問很多類型的傳感器。有些是基于硬件的,有些則是基于軟件的。基于硬件的傳感器是內(nèi)置于手持或桌面設(shè)備中的物理部件。它們直接測量環(huán)境參數(shù)并發(fā)送數(shù)據(jù),比如加速度、地磁強(qiáng)度、角速度等。基于軟件的傳感器則沒有物理設(shè)備,雖然它們也是模仿硬件傳感器。基于軟件的傳感器數(shù)據(jù)是來自一個(gè)或多個(gè)硬件傳感器,有時(shí)也被稱為虛擬傳感器或合成傳感器。直線加速度傳感器和重力傳感器就是基于軟件的傳感器。表1中列出了Android平臺(tái)支持的全部傳感器。
能夠擁有全部類型傳感器的Android設(shè)備非常少見。比如,大部分手持設(shè)備和桌面設(shè)備都帶有加速度和磁力傳感器,但帶氣壓計(jì)和溫度計(jì)的設(shè)備就少得多了。而且,在一臺(tái)設(shè)備上某類傳感器的數(shù)量也可以有多個(gè)。比如,一臺(tái)設(shè)備可以帶有兩個(gè)重力傳感器,每個(gè)傳感器的量程各不相同。
表1.?Android框架支持的傳感器類型
| 傳感器 | 類型 | 說明 | 常見用途 |
| TYPE_ACCELEROMETER | 硬件 | 測量施于設(shè)備的物理三維方向上(x、y和z軸)的加速度,包括重力,單位為m/s2。 | 運(yùn)動(dòng)檢測(晃動(dòng)、傾斜等) |
| TYPE_AMBIENT_TEMPERATURE | 硬件 | 測量周圍環(huán)境的溫度,單位為攝氏度(°C)。參見下文。 | 監(jiān)測氣溫 |
| TYPE_GRAVITY | 軟件或硬件 | 測量施于設(shè)備的物理三維方向上(x、y和z軸)的重力加速度,單位為m/s2?。 | 運(yùn)動(dòng)檢測(晃動(dòng)、傾斜等) |
| TYPE_GYROSCOPE | 硬件 | 測量設(shè)備圍繞每個(gè)物理三維方向(x、y和z軸)的轉(zhuǎn)動(dòng)角速度,單位為rad/s 。 | 轉(zhuǎn)動(dòng)檢測(旋轉(zhuǎn)、轉(zhuǎn)動(dòng)等) |
| TYPE_LIGHT | 硬件 | 測量周圍環(huán)境的光照強(qiáng)度(照度),單位為lx。 | 控制屏幕亮度 |
| TYPE_LINEAR_ACCELERATION | 軟件或硬件 | 測量施于設(shè)備的物理三維方向上(x、y和z軸)的加速度,但不包括重力,單位為m/s2。 | 監(jiān)測某一維軸線上的加速度 |
| TYPE_MAGNETIC_FIELD | 硬件 | 測量周圍物理三維方向(x、y和z軸)的地球磁場,單位為μT。 | 創(chuàng)建指南針 |
| TYPE_ORIENTATION | 軟件 | 測量圍繞物理三維方向(x、y和z軸)的旋轉(zhuǎn)角度。自API level 3開始,利用重力傳感器和地磁傳感器,你可以用getRotationMatrix()?方法讀取傾角矩陣和旋轉(zhuǎn)矩陣。 | 檢測設(shè)備的方位 |
| TYPE_PRESSURE | 硬件 | 測量周圍大氣壓力,單位為hPa或mbar。 | 監(jiān)測氣壓的變化 |
| TYPE_PROXIMITY | 硬件 | 測量附近的物體與設(shè)備屏幕間的距離,單位為cm。此傳感器的典型應(yīng)用,是可以檢測手持設(shè)備是否被人拿起來并靠近耳朵。 | 通話時(shí)確定電話的位置 |
| TYPE_RELATIVE_HUMIDITY | 硬件 | 測量周圍環(huán)境的相對濕度,單位為百分比(%)。 | 監(jiān)測結(jié)露點(diǎn)、絕對濕度和相對濕度。 |
| TYPE_ROTATION_VECTOR | 軟件或硬件 | 根據(jù)設(shè)備旋轉(zhuǎn)向量的三個(gè)參數(shù)測量設(shè)備的方向。 | 運(yùn)動(dòng)檢測和轉(zhuǎn)動(dòng)檢測 |
| TYPE_TEMPERATURE | 硬件 | 測量設(shè)備的溫度,單位是攝氏度(°C)。這個(gè)傳感器的實(shí)現(xiàn)因設(shè)備的差異而各不相同,并自API Level 14開始由TYPE_AMBIENT_TEMPERATURE?代替。 | 監(jiān)測溫度 |
傳感器框架
通過使用Android傳感器框架,你可以訪問這些傳感器并讀取傳感器的原始數(shù)據(jù)。Android傳感器框架是android.hardware?包的一部分,包含了以下類和接口:
SensorManager
你可以用這個(gè)類來創(chuàng)建傳感器設(shè)備的一個(gè)實(shí)例。這個(gè)類提供了多個(gè)方法,用于訪問及獲取傳感器列表、注冊及注銷傳感器事件偵聽器、讀取方位信息等。該類還提供了眾多的傳感器常量,用于報(bào)告?zhèn)鞲衅骶取⒃O(shè)置數(shù)據(jù)采樣率和校準(zhǔn)傳感器。
Sensor
你可以用這個(gè)類來創(chuàng)建某個(gè)傳感器的實(shí)例。該類提供了很多方法,使你能確定傳感器的性能。
SensorEvent
系統(tǒng)用該類來創(chuàng)建一個(gè)傳感器事件對象,用于提供傳感器事件的相關(guān)信息。這些信息包括:傳感器原始數(shù)據(jù)、生成本事件的傳感器類型、數(shù)據(jù)的精度、事件的時(shí)間戳。
SensorEventListener
你可以用該類來創(chuàng)建兩個(gè)回調(diào)方法,用于傳感器數(shù)值改變時(shí)或傳感器精度變化時(shí)接收通知(傳感器事件)。
在典型的應(yīng)用中,你一般會(huì)用這些傳感器API完成兩個(gè)基本的任務(wù):
- 識(shí)別傳感器及其性能
如果你的應(yīng)用有部分功能依賴于某些傳感器,則在運(yùn)行時(shí)識(shí)別傳感器的類型和性能是非常有用的。比如,你也許需要識(shí)別出當(dāng)前設(shè)備上所有的傳感器,并把那些所需傳感器不可用的功能禁用掉。同理,你可能還想識(shí)別出所有的某類型傳感器,以便應(yīng)用程序能夠選用其中性能最佳的那個(gè)。
- 監(jiān)聽傳感器事件
監(jiān)聽傳感器事件是獲取傳感器原始數(shù)據(jù)的途徑。每當(dāng)傳感器檢測到其測量的參數(shù)發(fā)生變化時(shí),傳感器事件就會(huì)被觸發(fā)。傳感器事件會(huì)向你提供四塊信息:觸發(fā)事件的傳感器名稱、事件的時(shí)間戳、事件的精度、觸發(fā)事件的傳感器原始數(shù)據(jù)。
傳感器的可用性
傳感器的可用性不僅會(huì)因設(shè)備不同而各不相同,也會(huì)因Android的版本而不一樣。這是因?yàn)?/span>Android傳感器的引入跨越了多個(gè)版本。比如,很多傳感器是自Android 1.5 (API Level 3) 開始引入的,但其中有些并未實(shí)現(xiàn)而直至Android 2.3 (API Level 9) 才可用。同樣,一部分傳感器是自Android 2.3 (API Level 9) 和Android 4.0 (API Level 14) 才引入的。有兩個(gè)傳感器已過時(shí),被更新更好的傳感器所替代。
表 2 匯總了每個(gè)版本可用的傳感器。由于涉及傳感器變動(dòng)的版本只有四個(gè),這里只列出了這四個(gè)版本。標(biāo)明過時(shí)的傳感器在后續(xù)的版本中仍是可用的(當(dāng)然設(shè)備要提供此傳感器),這也符合Android向下兼容性原則。
表2.?各版本可用的傳感器
| 傳感器 | Android 4.0 | Android 2.3 | Android 2.2 | Android 1.5 |
| TYPE_ACCELEROMETER | 是 | 是 | 是 | 是 |
| TYPE_AMBIENT_TEMPERATURE | 是 | n/a | n/a | n/a |
| TYPE_GRAVITY | 是 | 是 | n/a | n/a |
| TYPE_GYROSCOPE | 是 | 是 | n/a1 | n/a1 |
| TYPE_LIGHT | 是 | 是 | 是 | 是 |
| TYPE_LINEAR_ACCELERATION | 是 | 是 | n/a | n/a |
| TYPE_MAGNETIC_FIELD | 是 | 是 | 是 | 是 |
| TYPE_ORIENTATION | 是2 | 是2 | 是2 | 是 |
| TYPE_PRESSURE | 是 | 是 | n/a1 | n/a1 |
| TYPE_PROXIMITY | 是 | 是 | 是 | 是 |
| TYPE_RELATIVE_HUMIDITY | 是 | n/a | n/a | n/a |
| TYPE_ROTATION_VECTOR | 是 | 是 | n/a | n/a |
| TYPE_TEMPERATURE | 是2 | 是 | 是 | 是 |
1?此傳感器類型自 Android 1.5 (API Level 3) 起引入,但直至 Android 2.3 (API Level 9) 才可用。
2?此傳感器可用,但已過時(shí)。
識(shí)別傳感器及其性能
Android的傳感器框架提供了眾多的方法,使你很容易就能在運(yùn)行時(shí)檢測出當(dāng)前設(shè)備可用的傳感器。API也提供了很多檢測每個(gè)傳感器性能的方法,比如量程、分辨率、能耗。
要識(shí)別設(shè)備上的傳感器,你首先需要獲取一個(gè)傳感器設(shè)備的引用。你可以通過調(diào)用?getSystemService()?,并傳入?SENSOR_SERVICE?參數(shù),來創(chuàng)建一個(gè)?SensorManager?。例如:
?private SensorManager mSensorManager; ... mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);然后,你可以用?TYPE_ALL?參數(shù)調(diào)用?getSensorList()?方法,以獲取一個(gè)包含設(shè)備上所有傳感器的列表。例如:
?List<Sensor> deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);如果你需要列出某指定類型的所有傳感器,你可以用其它常量來代替?TYPE_ALL?,比如?TYPE_GYROSCOPE?、TYPE_LINEAR_ACCELERATION?、?TYPE_GRAVITY?。
你還可以用某類型常量作為參數(shù)的?getDefaultSensor()?來檢測設(shè)備上是否存在該類型的傳感器。如果設(shè)備上給定類型的傳感器不止一個(gè),則其中一個(gè)傳感器必須指定為缺省傳感器。如果給定類型的缺省傳感器不存在,則該方法返回null,表示設(shè)備沒有該類型的傳感器。例如,以下代碼檢查設(shè)備上是否存在磁力計(jì):
?private SensorManager mSensorManager; ... mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){ ? // 成功!磁力計(jì)存在。 ? } else { ? // 失敗|沒有磁力計(jì)。 ? }注意:?Android并未要求制造商在其Android平臺(tái)的設(shè)備上安裝任何類型的傳感器,因此設(shè)備上可能會(huì)存在各種各樣的傳感器。
除了列出設(shè)備上的傳感器清單外,你還可以用?Sensor?類的公共方法來確定每個(gè)傳感器的性能和參數(shù)。如果你的應(yīng)用需要根據(jù)傳感器及其性能的差異作出不同的表現(xiàn),這就非常有用。比如,你可以用?getResolution()?和getMaximumRange()?方法來獲取傳感器的分辨率及最大量程。你還可以用?getPower()?方法來獲取傳感器的能耗。
如果你需要根據(jù)傳感器的制造商或版本來對應(yīng)用進(jìn)行優(yōu)化,有兩個(gè)公共方法特別有用。比如,如果你的應(yīng)用需要監(jiān)控傾斜或者晃動(dòng)之類的用戶手勢,則針對較新的帶某廠商重力傳感器的設(shè)備,你可以建立一套數(shù)據(jù)過濾規(guī)則和優(yōu)化措施,而針對沒有重力傳感器只有加速度計(jì)的設(shè)備你可以建立另一套數(shù)據(jù)過濾器和優(yōu)化措施。以下例程展示了如何用?getVendor()?和?getVersion()?來完成這類工作的。在此例中,我們將先查找Google公司出品的版本為3的重力傳感器。如果設(shè)備上不存在這類傳感器,我們再嘗試使用加速計(jì)。
?private SensorManager mSensorManager; private Sensor mSensor; ... mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); if (mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){ ? List<Sensor> gravSensors = mSensorManager.getSensorList(Sensor.TYPE_GRAVITY); ? for(int i=0; i<gravSensors.size(); i++) { ? ? if ((gravSensors.get(i).getVendor().contains("Google Inc.")) && ? ? ? ?(gravSensors.get(i).getVersion() == 3)){ ? ? ? // 使用版本3的重力傳感器 ? ? ? mSensor = gravSensors.get(i); ? ? } ? } } else{ ? // 使用加速計(jì) ? if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){ ? ? mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); ? } ? else{ ? ? // 抱歉,設(shè)備上不存在加速計(jì),你無法玩這個(gè)游戲。 ? } }其它較有用的是?getMinDelay()?方法,用于返回傳感器采集數(shù)據(jù)的最小時(shí)間間隔(微秒)。任何getMinDelay()?返回非零值的傳感器都是流式傳感器(streamingsensor)。流式傳感器以一定的時(shí)間間隔有規(guī)律地測量數(shù)據(jù),自Android 2.3 (API Level 9) 開始引入。如果調(diào)用?getMinDelay()?時(shí)返回零,這就表示該傳感器不是流式傳感器,只有所監(jiān)測的參數(shù)發(fā)生變化時(shí)它才會(huì)報(bào)送數(shù)據(jù)。
getMinDelay()?方法能讓你確定傳感器的最大采樣頻率,因此它是非常有用的。如果你的應(yīng)用中某項(xiàng)功能需要很高的數(shù)據(jù)采樣率或者要用到流式傳感器,你就可以用此方法先確認(rèn)傳感器是否符合要求,然后再據(jù)此來啟用或禁用相關(guān)的功能。
警告:?傳感器框架并不一定按照傳感器的最大數(shù)據(jù)采樣率來向你的應(yīng)用發(fā)送數(shù)據(jù)。傳感器框架是通過傳感器事件來報(bào)送數(shù)據(jù)的,而很多因素會(huì)影響到應(yīng)用程序?qū)鞲衅魇录慕邮疹l率。詳情請參閱?監(jiān)聽傳感器事件?。
監(jiān)聽傳感器事件
要監(jiān)控傳感器的原始數(shù)據(jù),你需要實(shí)現(xiàn)?SensorEventListener?接口的?onAccuracyChanged()?和onSensorChanged()?回調(diào)方法。只要發(fā)生以下事件,Android系統(tǒng)就會(huì)調(diào)用這兩個(gè)方法:
- 傳感器精度發(fā)生變化
在這種情況下,系統(tǒng)會(huì)調(diào)用?onAccuracyChanged()?方法,并傳給你一個(gè)發(fā)生變化的?Sensor?對象的引用和新的傳感器精度值。精度用以下四種狀態(tài)常量之一來表示:?SENSOR_STATUS_ACCURACY_LOW、SENSOR_STATUS_ACCURACY_MEDIUM、?SENSOR_STATUS_ACCURACY_HIGH、和SENSOR_STATUS_UNRELIABLE。
- 傳感器報(bào)送一個(gè)新數(shù)據(jù)
這種情況下,系統(tǒng)會(huì)調(diào)用?onSensorChanged()?方法,并傳給你一個(gè)?SensorEvent?對象。?SensorEvent對象中包含了新數(shù)據(jù)的相關(guān)信息,包括:數(shù)據(jù)精度、生成數(shù)據(jù)的傳感器、生成數(shù)據(jù)的時(shí)間戳、傳感器采到的新數(shù)據(jù)。
以下代碼展示了如何用?onSensorChanged()?方法來監(jiān)控光線傳感器傳回的數(shù)據(jù),并把原始數(shù)據(jù)顯示在一個(gè)由main.xml文件定義為sensor_data的?TextView?中。
?public class SensorActivity extends Activity implements SensorEventListener { ? private SensorManager mSensorManager; ? private Sensor mLight; ? @Override ? public final void onCreate(Bundle savedInstanceState) { ? ? super.onCreate(savedInstanceState); ? ? setContentView(R.layout.main); ? ? mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); ? ? mLight = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); ? } ? @Override ? public final void onAccuracyChanged(Sensor sensor, int accuracy) { ? ? // 如果傳感器精度發(fā)生變化,可以在這里完成些工作。 ? } ? @Override ? public final void onSensorChanged(SensorEvent event) { ? ? // 光線傳感器返回單個(gè)值。 ? ? // 很多傳感器會(huì)返回3個(gè)值,代表每個(gè)坐標(biāo)軸上的數(shù)值。 ? ? float lux = event.values[0]; ? ? // 利用此值完成一些工作 ? } ? @Override ? protected void onResume() { ? ? super.onResume(); ? ? mSensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL); ? } ? @Override ? protected void onPause() { ? ? super.onPause(); ? ? mSensorManager.unregisterListener(this); ? } }在此例中,調(diào)用?registerListener()?時(shí)指定了缺省的數(shù)據(jù)延時(shí) (SENSOR_DELAY_NORMAL)。數(shù)據(jù)延時(shí)(或采樣率)控制著由?onSensorChanged()?發(fā)送給應(yīng)用的傳感器事件的觸發(fā)間隔。缺省的數(shù)據(jù)延遲是200,000微秒,適于監(jiān)測典型的屏幕方向變動(dòng)。你可以把數(shù)據(jù)延時(shí)指定為其它值,比如?SENSOR_DELAY_GAME?(20,000微秒)、SENSOR_DELAY_UI?(60,000微秒)或?SENSOR_DELAY_FASTEST?(0微秒)。Android3.0 (API Level 11) 開始,你還可以直接指定延時(shí)值(微秒數(shù))。
你指定的延時(shí)只是一個(gè)建議值。Android系統(tǒng)和其它應(yīng)用可以修改這個(gè)值。最佳方案是,你應(yīng)該指定你能承受的最大延時(shí),因?yàn)橄到y(tǒng)一般會(huì)采用一個(gè)比設(shè)定稍小一點(diǎn)的值(也就是說,你應(yīng)該選擇應(yīng)用所需的最慢采樣率)。采用更大的延時(shí)能夠降低處理器的負(fù)載并減少耗電量。
傳感器框架發(fā)送傳感器事件的實(shí)際頻率,是沒有現(xiàn)成的公共方法來判斷的,不過,你可以根據(jù)多個(gè)傳感器事件的時(shí)間戳來計(jì)算出采樣率。一旦采樣率(延時(shí))設(shè)置完成,你就不應(yīng)該改變它。如果由于某種原因需要修改延時(shí),那你就必須注銷并重新注冊傳感器偵聽器。
還有一點(diǎn)非常重要,請注意上例中使用了?onResume()?和?onPause()?回調(diào)方法來注冊和注銷傳感器事件偵聽器。最佳方案就是,你應(yīng)該保證在不用時(shí)及時(shí)關(guān)閉傳感器,特別當(dāng)你的activity被暫停時(shí)。不然,因?yàn)槟承﹤鞲衅鞯哪芎暮艽?#xff0c;會(huì)快速消耗電池電量,可能會(huì)在幾個(gè)小時(shí)內(nèi)將電池耗盡。當(dāng)屏幕關(guān)閉時(shí),系統(tǒng)會(huì)自動(dòng)禁用所有傳感器。
處理各種傳感器配置
Android并沒有設(shè)定標(biāo)準(zhǔn)的傳感器配置,這意味著設(shè)備制造商可能會(huì)把所有要裝入設(shè)備的傳感器配置都放進(jìn)Android平臺(tái)的設(shè)備中。這樣,設(shè)備就可能包括了各種傳感器的大量配置信息。比如,MotorolaXoom帶有壓力傳感器,而SamsungNexus S就沒有。同理,Xoom 和 NexusS 都帶有陀螺儀,但是HTC Nexus One 卻沒有。如果你的應(yīng)用依賴于特定類型的傳感器,你不得不確認(rèn)設(shè)備是否提供了該傳感器,以保證你的應(yīng)用能成功運(yùn)行。你有兩種方式來確認(rèn)傳感器的存在:
- 在運(yùn)行時(shí)檢測傳感器并酌情啟用或禁用應(yīng)用程序的相應(yīng)功能
- 使用Android Market過濾器來限定目標(biāo)設(shè)備必須帶有特定傳感器
這兩種方式將在下節(jié)介紹。
在運(yùn)行時(shí)檢測傳感器
如果你的應(yīng)用程序用到了特定類型的傳感器,不過并不是必須使用它,那么你可以在運(yùn)行時(shí)利用傳感器框架來檢測它,并酌情啟用或禁用相應(yīng)功能。比如,一個(gè)導(dǎo)航應(yīng)用也許會(huì)用到溫度、壓力、GPS和地磁傳感器來顯示溫度、氣壓、位置和南北方位。如果設(shè)備不提供壓力傳感器,你可以在運(yùn)行時(shí)用傳感器框架來檢測壓力傳感器是否存在,然后在應(yīng)用界面上關(guān)閉氣壓的顯示。例如,以下就是檢測設(shè)備是否提供壓力傳感器的代碼:
?? private SensorManager mSensorManager; ? ... ? mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); ? if (mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){ ? // Success! There's a pressure sensor. ? } ? else { ? // 失敗!傳感器不存在。 ? }用Android Market 過濾器來限定目標(biāo)設(shè)備必須帶有指定的傳感器配置
如果你要在 Android Market 上發(fā)布應(yīng)用,你可以用manifest 文件中的?<uses-feature>?元素把不提供所需傳感器的設(shè)備過濾掉。manifest 文件中的<uses-feature>元素有很多硬件描述符,利用它們你可以根據(jù)傳感器存在與否來對應(yīng)用進(jìn)行過濾。可列出的傳感器包括:加速計(jì)、氣壓計(jì)、羅盤(地磁)、陀螺儀、光線和鄰近距離。以下是濾除無加速計(jì)的manifest 樣例:
?<uses-feature android:name="android.hardware.sensor.accelerometer" ? ? ? ? ? ? ? android:required="true" />如果你把這個(gè)元素和描述符加入你的 manifest 中,則只有設(shè)備上帶有加速計(jì)的用戶才能在Android Market 上看到你的應(yīng)用。
僅當(dāng)應(yīng)用程序完全依賴于某指定傳感器時(shí),你才能把描述符設(shè)置?android:required="true"。如果你的應(yīng)用中只有某些功能用到了傳感器,而沒有傳感器的話仍然能正常運(yùn)行,那么你可以把傳感器列在?<uses-feature>中,但應(yīng)設(shè)置?android:required="false"?。這樣可以確保沒有此傳感器的設(shè)備也能安裝你的應(yīng)用。這也是項(xiàng)目管理實(shí)踐中的最佳方案,有助于你時(shí)刻了解應(yīng)用所需要的硬件特性。請記住,如果你的應(yīng)用用到了某個(gè)傳感器,但沒有此傳感器也能運(yùn)行,那你就必須在運(yùn)行時(shí)檢測傳感器,并酌情禁用或啟用相應(yīng)功能。
傳感器的坐標(biāo)系
通常,傳感器框架使用標(biāo)準(zhǔn)的三維坐標(biāo)系來表示數(shù)據(jù)。對大多數(shù)傳感器而言,該坐標(biāo)系是以設(shè)備保持默認(rèn)方向時(shí)的屏幕為參照物來定義的(參見圖1)。當(dāng)設(shè)備保持默認(rèn)方向時(shí),X軸表示從左到右的水平方向,Y軸表示自下而上的垂直方向,Z軸表示相對屏幕表面由內(nèi)而外的方向。在這一坐標(biāo)系中,屏幕背后的坐標(biāo)用Z軸的負(fù)值表示。以下傳感器會(huì)用到該坐標(biāo)系:
圖1.?傳感器API使用的坐標(biāo)系(相對設(shè)備而言)
- 加速度傳感器
- 重力傳感器
- 陀螺儀
- 線性加速度傳感器
- 地磁傳感器
要理解這個(gè)坐標(biāo)系,最重要的一點(diǎn)就是,屏幕方向變化時(shí)坐標(biāo)軸并不移動(dòng)——也就是說,設(shè)備移動(dòng)時(shí)傳感器的坐標(biāo)系永不改變。這與 OpenGL坐標(biāo)系類似。
理解坐標(biāo)系的另一個(gè)要點(diǎn),你的應(yīng)用不得假定設(shè)備的初始(默認(rèn))方向是豎直的。很多桌面設(shè)備的初始方向是橫向放置的。傳感器的坐標(biāo)系總是以設(shè)備的初始方向?yàn)榛鶞?zhǔn)的。
最后,如果你的應(yīng)用需要把傳感器數(shù)據(jù)與屏幕顯示關(guān)聯(lián),則你要用?getRotation()?方法來確定屏幕的轉(zhuǎn)動(dòng)方向,然后用remapCoordinateSystem()?方法把傳感器坐標(biāo)映射為屏幕坐標(biāo)。即使你的manifest文件已經(jīng)指定為僅支持縱向顯示,你仍需要這么做。
關(guān)于傳感器坐標(biāo)系的更多信息,包括如何處理屏幕旋轉(zhuǎn)的相關(guān)信息,請參閱?One Screen Turn Deserves Another
注意:?某些傳感器和方法的坐標(biāo)系使用了地球參照系(而非設(shè)備參照系)。這些傳感器和方法返回的數(shù)據(jù)表示了相對大地坐標(biāo)而言的設(shè)備運(yùn)動(dòng)和地理位置。詳情請參閱getOrientation()?方法、?getRotationMatrix()?方法、方向傳感器?和旋轉(zhuǎn)矢量傳感器。
訪問和使用傳感器的最佳實(shí)現(xiàn)方案
當(dāng)你設(shè)計(jì)傳感器相關(guān)的代碼時(shí),請確保遵守本節(jié)所列出的規(guī)范。這些規(guī)范作為最佳實(shí)現(xiàn)方案進(jìn)行推薦,適用于需要使用傳感器框架來訪問傳感器和讀取傳感器數(shù)據(jù)的任何人員。
注銷傳感器偵聽器
當(dāng)不再使用傳感器或相關(guān)activity暫停時(shí),確保及時(shí)注銷傳感器偵聽器。如果傳感器偵聽器已注冊而相關(guān)activity被暫停,傳感器仍會(huì)繼續(xù)測量數(shù)據(jù)并消耗電池資源,除非你注銷了傳感器。以下代碼展示了如何利用onPause()?方法來注銷偵聽器:
?private SensorManager mSensorManager; ? ... @Override protected void onPause() { ? super.onPause(); ? mSensorManager.unregisterListener(this); }詳情請參閱unregisterListener(SensorEventListener)。
不要在模擬器上測試你的代碼
目前無法在模擬器上測試傳感器相關(guān)的代碼,因?yàn)槟M器不能模擬傳感器。你必須在物理設(shè)備上測試傳感器相關(guān)代碼。不過,你可以利用傳感器的模擬器來模擬傳感器的輸出。
不要阻塞onSensorChanged() 方法
傳感器數(shù)據(jù)以很高的頻率在發(fā)生變化,這意味著系統(tǒng)可能會(huì)非常頻繁地調(diào)用?onSensorChanged(SensorEvent)方法。最佳實(shí)現(xiàn)方案是,在?onSensorChanged(SensorEvent)?方法中你應(yīng)該盡可能少干些事情,以防止阻塞。如果你的應(yīng)用需要對傳感器數(shù)據(jù)進(jìn)行過濾或剔除操作,則應(yīng)該在?onSensorChanged(SensorEvent)?方法之外進(jìn)行。
避免使用過時(shí)的方法或傳感器類型
有幾個(gè)方法和常量已經(jīng)過時(shí)了。特別是?TYPE_ORIENTATION?傳感器類型已經(jīng)過時(shí)。要獲取方位數(shù)據(jù),你應(yīng)該換用?getOrientation()?方法。同樣,?TYPE_TEMPERATURE?傳感器類型也已過時(shí)。在Android 4.0 的設(shè)備上,你應(yīng)該用?TYPE_AMBIENT_TEMPERATURE?傳感器類型來代替。
在使用前先驗(yàn)證傳感器
在試圖讀取數(shù)據(jù)前,請確保先驗(yàn)證一下傳感器是否存在。不要因?yàn)閭鞲衅骱艹S?#xff0c;就簡單地假定它會(huì)存在。制造商并不需要在他們的設(shè)備上提供任何傳感器。
謹(jǐn)慎選擇傳感器延時(shí)
當(dāng)利用?registerListener()?方法注冊傳感器時(shí),請確保為你的應(yīng)用或使用場景選擇了合適的發(fā)送頻率。傳感器能夠以很高的頻率發(fā)送數(shù)據(jù)。?請保證系統(tǒng)有能力發(fā)送其它數(shù)據(jù),不要無謂浪費(fèi)系統(tǒng)資源和消耗電池電量。
參考:http://developer.android.com/guide/topics/sensors/sensors_overview.html
總結(jié)
以上是生活随笔為你收集整理的Android传感器-开发指南的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android中11种常见传感器的使用方
- 下一篇: android sina oauth2.