Android系統編程入門系列之硬體交互——感測器

到目前為止,關於應用程式與用戶之間的相關內容便比較膚淺的大致介紹完畢。而在整個系統架構中,應用程式與用戶之間的交互,猶如參天大樹上的枝幹和樹葉,交互起來五彩繽紛,但使整個生態系統保持生命力的核心,在於樹根,也就是應用程式通過Android系統與設備上硬體的交互。

設備硬體

設備的硬體目前主要分為三大類,包括感測器系列硬體(重力感測器、加速度感測器、陀螺儀、位置感測器、光亮感測器等),互聯通訊系列硬體(SIM卡,無線WLAN,藍牙、NFC、USB等),多媒體系列硬體(麥克風、播放器、相機等)。

雖然設備硬體五花八門,但是在系統層都遵循各自的硬體協議封裝了一層,而在應用程式內部只需要使用系統層提供的相關介面即可。不管是對哪種硬體的訪問,首要步驟都是在應用程式的清單文件中,使用<uses-permission>標籤聲明要使用的相關許可權。
而對於某些設備非必需硬體,應用程式中可使用<uses-feature>標籤聲明對某些硬體的需求,以兼容應用程式在沒有該硬體的設備上運行。

注意,使用<uses-feature>標籤聲明的硬體需求,在應用程式安裝到設備時,並不會檢查該設備是否支援相關需求硬體,而只是在其他服務如官方Google Play中、或應用程式內部運行到相關硬體支援程式碼時,檢測相關聲明。

感測器系列硬體

許可權聲明

對於感測器系列硬體,需要聲明許可權名稱為Manifest.permission.BODY_SENSORS,另外,在Android10.0即API 31及以上的版本中,還可以使用Manifest.permission.HIGH_SAMPLING_RATE_SENSORS許可權以更快速的刷新獲取感測器的數據。

使用流程

與感測器系列硬體的交互,主要藉助android.hardware.SensorManager感測器管理類,該類的對象,可以在能獲取上下文環境Context對象的地方,調用其getSystemService(Context.SENSOR_SERVICE)獲取系統服務對象,將返回的結果類型強制轉換為SensorManager類型即可。

在得到SensorManager感測器管理類的對象後,可以調用其getSensorList(int type)方法,參數 type 可以指定為代表所有感測器類型的Sensor.TYPE_ALL=-1,也可以指定某一類具體的感測器,這些類型及數值都是在android.hardware.Sensor感測器類中定義的靜態常量。而該方法的返回結果,也是List<Sensor>感測器集合,裡邊包含了當前系統所在設備的所有可使用的感測器資訊。
而如果設備中有多個同一類型的感測器,可以調用getDefaultSensor(int type)方法,參數 type 同樣是指定的某一種感測器類型,返回該類型感測器所使用的默認一個Sensor感測器對象,如果系統硬體中沒有正常使用該類型的感測器,則會返回null。

對於通過感測器管理類對象找到的Sensor感測器對象,可以調用其getX()系列方法,獲取感測器的一些基本資訊,方法名中的X包括Id、Name、Version等。

在找到匹配的Sensor感測器對象後,就可以在合適的時機,開啟實時監測該感測器獲得的數據,以及在合適的時機,關閉對該感測器數據的監測活動。通常為了節省資源,在介面Activity的onResume()方法中開啟監測,並在對應的onPause()方法中關閉監測。

開啟監測是調用SensorManager對象的registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, int maxReportLatencyUs, Handler handler)方法。參數 listener 是android.hardware.SensorEventListener感測器事件監聽器介面所實現的對象,在感測器發出數據時會回調該對象所實現的方法;參數 sensor 則是上文所匹配的要檢測的Sensor感測器對象;參數 samplingPeriodUs 是用int類型標記的監測頻率,其值是SensorManager中定義的靜態常量,包括正常頻率SENSOR_DELAY_NORMAL=3, 稍微快一點以在介面更新時的頻率SENSOR_DELAY_UI=2, 再快一點以在遊戲更新時的頻率SENSOR_DELAY_GAME=1, 和最快的頻率SENSOR_DELAY_FASTEST=0;參數 maxReportLatencyUs 為可選參數,是int類型表示感測器更新數據後回調上文監聽介面對象的方法時的最大延時,單位是毫秒,且默認值為0;參數 handler 同樣為可選參數,感測器發出的數據在回調上文的監聽器介面對象後,也會交付到該Handler類型的對象中處理,默認值為null。

關閉監測是調用SensorManager對象的unregisterListener(SensorEventListener listener, Sensor sensor)方法。參數 listener 即在開啟監測方法中傳入的SensorEventListener監聽器介面對象;參數 sensor 是可選參數,為開啟監測方法中傳入的Sensor感測器對象,當該參數默認值為null時,則會對所有開啟參數 listener 監聽的感測器對象的監測活動都關閉。

在該SensorEventListener感測器事件監聽介面的實例化對象中,需要實現兩個方法,包括onAccuracyChanged(Sensor sensor, int accuracy),和onSensorChanged(SensorEvent event)方法。
其中,onAccuracyChanged(Sensor sensor, int accuracy)方法會在感測器的精確度發生變化時回調,其參數 sensor 為發生變化的Sensor感測器對象;參數 accuracy 是int類型的標記,由SensorManager定義的靜態常量,其值包括感測器數據不允許應用程式訪問的SENSOR_STATUS_NO_CONTACT=-1,感測器需要校準或無法正常訪問的SENSOR_STATUS_UNRELIABLE=0,低精確度需要校準的SENSOR_STATUS_ACCURACY_LOW=1。普通精確度可以檢測平均值的SENSOR_STATUS_ACCURACY_MEDIUM=2,高精確度非常精準的SENSOR_STATUS_ACCURACY_HIGH=3。
onSensorChanged(SensorEvent event)方法會在感測器更新數據時回調,其參數 event 是android.hardware.SensorEvent感測器事件類,該類型中包含了Sensor感測器以及更新的float[]數據等資訊,其中的數據數組長度及內容,則是根據感測器的不同類型所確定的。

應用場景

類似指南針類應用,計步器類應用,自動調節螢幕亮度等功能,都是依靠感測器系列硬體實現的。應用程式藉助感測器系列硬體,感知外界環境的動態變化,從而實時展示給用戶查看,而這個數據流向是單向的。