前言
Android提供了對設備傳感器的支持,只要Android設備的硬件提供了這些傳感器,Android應用可以通過傳感器來獲取設備的外界條件,包括手機的運行狀態、當前擺放的方向等。Android系統還提供了驅動程序去管理這些傳感器硬件,可以通過監聽器的方式監聽傳感器硬件感知到的外部環境的變化。本篇博客主要講解如何簡單的使用Android下的傳感器,最后將以一個簡單的Demo演示。
開發傳感器應用步驟
開發一個對於傳感器支持的應用十分簡單,開發人員只要在傳感器管理器SensorManager中為所要監聽的傳感器指定一個監聽器即可,當外部環境發生變化的時候,Android系統會通過傳感器獲取外部環境的數據,然后將數據傳遞給監聽器的監聽回調方法。具體步驟如下:
Android中內置了很多系統級的服務,用於給開發人員使用,而傳感器也是通過傳感器服務,SensorManager來管理的。而在Android組件中獲取系統服務,使用方法Context.getSystemService(String)即可,它的參數均以static final的方式定義在Context中,而獲取SensorManager需要傳入Context.SENSOR_SERVICE。
1 manager=(SensorManager) getSystemService(SENSOR_SERVICE);
傳感器服務管理設備上所有的傳感器,所以需要指定待監聽的傳感器。獲取待監聽的傳感器,需要使用SensorManager.getDefaultSensor()方法,它的完整簽名如下:
Sensor getDefaultSensor(int type)
Android中的傳感器需要Sensor支持,getDefaultSensor()方法通過指定的type參數獲取到相對應的傳感器。type參數被以static final的方式定義在Sensor內部,方便開發人員可以直接使用。下面介紹幾個常用傳感器的type:
- Sensor.TYPE_ORIENTATION:方向傳感器。
- Sensor.TYPE_ACCELEROMETER:重力傳感器。
- Sensor.TYPE_LIGHT:光線傳感器。
- Sensor.TYPE_MAGNETIC_FIELD:磁場傳感器。
獲得SensorManager和Sensor對象之后,就可以為其Sensor注冊監聽器了。為傳感器注冊監聽器,使用SensorManager.registerListener()方法即可,它存在多個重載方法,但是有些方法已經過時了,下面提供一個常用的方法的簽名:
boolean registerListener(SensorEventListener listener,Sensor sensor,int rateUs)
上面方法參數的意義:listener:傳感器的監聽器、sensor:待監聽的傳感器、rateUs:傳感器的采樣率。
從registerListener()方法可以看出,它需要傳遞一個SensorEventListener對象,它就是傳感器的監聽器,其中包含兩個方法,需要開發人員去實現它:
- void onAccuracyChanged(Sensor sensor,int accuracy):當傳感器精度發生變化時回調。
- void onSensorChanged(SensorEvent event):當傳感器感應的值發生變化時回調。
對於上面兩個方法,傳感器的精度一般是不會發生改變的,所以我們一般主要的代碼量在onSensorChanged()中。
registerListener()方法還有一個rateUs的參數,它表示監聽傳感器改變的采樣率,就是從傳感器獲取值的頻率。它被定義以static final的形式定義在SensorManager中,方便我們直接使用,它定義了如下幾個選項:
- SensorManager.SENSOR_DELAY_FASTEST:最快,延遲最小。
- SensorManager.SENSOR_DELAY_GAME:適合游戲的頻率。
- SensorManager.SENSOR_DELAY_NORMAL:正常頻率。
- SensorManager.SENSOR_DELAY_UI:適合普通用戶界面UI變化的頻率。
Android為我們提供了這幾個采樣率的參數,方便我們使用。但對於選擇那種采樣率而言,並不是越快越好,要參照實際開發的應用的情況來說,采樣率越大,將越耗費資源,包括電量、CPU等,所以要根據實際情況選擇,畢竟再強大的應用,如果造成設備續航能力的降低,也是會被用戶所不喜的。
當使用完傳感器之后,需要為其注銷監聽器,因為傳感器的監聽器並不會因為應用的結束而自行釋放資源,需要開發人員在適當的時候主動注銷。注銷傳感器監聽器使用SensorManager.unregisterListener()方法即可,和監聽器的注冊方法一樣,它也具有多個重載的方法,但是有一些已經被棄用了,下面介紹一個常用的完整簽名:
void unregisterListener(SensorEventListener listener)
指南針Demo
上面已經講解了在應用中使用傳感器的步驟以及具體內容,下面通過一個簡單的Demo來演示一下如何使用傳感器。在Demo中監聽方向傳感器,使其角度的變化改變來操作方向,模擬一個指南針的效果。
重寫監聽器的onSensorChanged()方法,其中event獲取當當前監聽事件的參數,可以使用values[0]獲取到當前的方向傳感器感應到的角度。參照官方文檔,可以看出,它代表一個360°的角度,規則是: 0=North, 90=East, 180=South, 270=West。
下面直接貼代碼了,注釋比較全,就不再贅述了,會用到補間動畫的內容,對補間動畫不了解的朋友,可以看看另外一篇博客:Android--Tween補間動畫。還有一點需要注意的是就是傳感器的Demo需要在真機上測試,因為模擬器上不存在傳感器硬件。
1 package com.example.sensormanagerdemo; 2 3 import android.hardware.Sensor; 4 import android.hardware.SensorEvent; 5 import android.hardware.SensorEventListener; 6 import android.hardware.SensorManager; 7 import android.os.Bundle; 8 import android.view.animation.Animation; 9 import android.view.animation.RotateAnimation; 10 import android.widget.ImageView; 11 import android.app.Activity; 12 13 public class MainActivity extends Activity { 14 private ImageView iv_compass; 15 private SensorManager manager; 16 private float startDegree = 0f; 17 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_main); 22 23 iv_compass = (ImageView) findViewById(R.id.iv_compass); 24 // 獲得傳感器管理器 25 manager = (SensorManager) getSystemService(SENSOR_SERVICE); 26 27 } 28 29 @Override 30 protected void onResume() { 31 super.onResume(); 32 // 為方向傳感器注冊監聽器 33 manager.registerListener(listener, 34 manager.getDefaultSensor(Sensor.TYPE_ORIENTATION), 35 SensorManager.SENSOR_DELAY_UI); 36 37 } 38 39 private SensorEventListener listener = new SensorEventListener() { 40 41 @Override 42 public void onSensorChanged(SensorEvent event) { 43 if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) { 44 // 獲取當前傳感器獲取到的角度 45 float degree = -event.values[0]; 46 // 通過補間動畫旋轉角度 從上次的角度旋轉 47 RotateAnimation ra = new RotateAnimation(startDegree, degree, 48 Animation.RELATIVE_TO_SELF, 0.5f, 49 Animation.RELATIVE_TO_SELF, 0.5f); 50 ra.setDuration(200); 51 iv_compass.startAnimation(ra); 52 // 記錄當前旋轉后的角度 53 startDegree = degree; 54 } 55 } 56 57 @Override 58 public void onAccuracyChanged(Sensor sensor, int accuracy) { 59 60 } 61 }; 62 63 @Override 64 protected void onStop() { 65 // 為傳感器注銷監聽器 66 manager.unregisterListener(listener); 67 super.onStop(); 68 } 69 }
效果展示:

總結
本篇博客講解了Android下如何使用傳感器,只是簡單的介紹了一下,對於傳感器獲取到的數值,都在event.values數組中,但是不同傳感器獲取到的值不同,具體情況具體分析,這里就不再深入討論了。

