Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android官方文檔之Location and Sensors APIs(中)

Android官方文檔之Location and Sensors APIs(中)

編輯:關於Android編程

本文將介紹Android設備中的傳感器。


傳感器概述(Sensors Overview)


大部分Android設備內置了大量的傳感器,比較常見的有測量位移的、感應方向的、感應周圍環境變化的 等等。這些傳感器都能反饋高精度的原始數據、而且可以監測設備在三個方向上的位移和周圍環境的變化 等。比如,在一款天氣應用程序中可以使用溫度傳感器和濕度傳感器得到周圍環境的變化;在一款旅游應用程序中可以使用地磁傳感器和加速器設定指南針的方向。


Android設備提供三種類型的傳感器:

運動傳感器(Motion sensors):這類傳感器可以監測設備在三個坐標軸所在方向上的加速力和旋轉力( measure acceleration forces and rotational forces along three axes)。主要有:加速計(accelerometers)、重力傳感器(gravity sensors)、陀螺儀( gyroscopes)和旋轉向量傳感器( rotational vector sensors)等。

環境傳感器(Environmental sensors):這類傳感器可以監測設備所在的環境參數,如溫度、氣壓、亮度、濕度 等(measure various environmental parameters, such as ambient air temperature and pressure, illumination, and humidity)。主要有:氣壓計(barometers)、光度計(photometers)、溫度計(thermometers)等。

位置傳感器(Position sensors):這類傳感器可以監測設備所在物理位置。如方向傳感器和磁力儀(orientation sensors and magnetometers)。


使用Android中的API可以輕松獲取各類傳感器所檢測的原始數據。例如,您可以通過這些API做以下事:

當前設備中所包含的傳感器數量和類別;

每一個傳感器的參數。如可測量的最大值、生產商、所需功率、測量精確度 等( maximum range, manufacturer, power requirements, and resolution)。

從傳感器中獲取數據的間隔(頻率)。

當傳感器的狀態發生變化時,可以通過注冊監聽器的方式監聽。


傳感器介紹(Introduction to Sensors)


從底層驅動劃分,傳感器還可以分為硬件驅動型和軟件驅動型。硬件驅動的傳感器(Hardware-based sensors)是內嵌於Android設備中的實實在在的物理部件。這些物理部件通過自身可以檢測周圍的環境屬性,並輸出測量數據,如加速度、地磁場強、角度變化 等。盡管由軟驅動的傳感器(Software-based sensors)看起來與硬件驅動的傳感器高度相似,但前者並不是物理部件。軟件驅動的傳感器提供的數據通常是由若干個不同類型的硬件驅動的傳感器的輸出結果經過計算合成的,所以有時也將它們稱作虛擬傳感器或者合成傳感器( virtual sensors or synthetic sensors)。線性加速器和重力傳感器就屬於軟驅動傳感器。下面的表格對Android各類傳感器作了簡要介紹。


在一個設備中,同一種類型的傳感器,可能有多個。比方說,一個設備中含有兩個重力傳感器,每個傳感器用於測量不同的范圍。


傳感器(Sensor) 類型(Type) 描述(Description) 應用場景(Common Uses) 加速計TYPE_ACCELEROMETER 硬件驅動型 可以監測設備在三維坐標系的三個坐標軸所在方向的加速度,單位是 m/s^2,當然還可以監測重力加速度的大小(g)。 監測設備的運動方式,如搖一搖、傾斜 等。 溫度計TYPE_AMBIENT_TEMPERATURE 硬件驅動型 監測當前設備所處環境的溫度,單位是攝氏度(°C) 。 監測溫度變化 監測重力加速度 TYPE_GRAVITY 軟件驅動型、硬件驅動型 可以監測設備在三維坐標系的三個坐標軸所在方向的加速度,單位是 m/s^2 監測設備的運動方式,如搖一搖、傾斜 等。 陀螺儀TYPE_GYROSCOPE 硬件驅動型 監測設備在三個坐標軸所在方向的角速度,單位是rad/s 檢測設備的旋轉或翻轉(spin, turn) 光照傳感器TYPE_LIGHT 硬件驅動型 監測設備所處環境的光線強度,單位是勒克斯(lx) 控制屏幕的亮度 線性加速器TYPE_LINEAR_ACCELERATION 軟件驅動型、硬件驅動型 可以監測設備在三維坐標系的三個坐標軸所在方向的加速度,單位是 m/s^2,當然還可以監測重力加速度的大小(g)。 監測設備在某一方向上的加速度 測量磁場強度TYPE_MAGNETIC_FIELD 硬件驅動型 監測設備在三個坐標軸所在方向上的磁場強度,單位是微特斯拉(μT) 實現指南針功能 測量方向TYPE_ORIENTATION 軟件驅動型 監測設備與三個坐標平面之間的夾角;調用getRotationMatrix()方法可以獲取設備的旋轉矩陣。 測定設備的位置。 監測氣壓TYPE_PRESSURE 硬件驅動型 監測設備所處環境的氣壓,單位是百帕(hPa)或毫巴(mbar),其中1000hPa=1000hPa=1個大氣壓強 監測大氣壓強的變化。 測量距離TYPE_PROXIMITY 硬件驅動型 用於測量物體與設備屏幕的直線距離,通常用於監測打電話時,手機屏幕與用戶耳朵的距離 耳朵距離手機屏幕的距離 相對濕度TYPE_RELATIVE_HUMIDITY 硬件驅動型 測量空氣的相對濕度(%) 用於監測由於大氣中的濕空氣溫度下降,使所含的水蒸氣達到飽和狀態而開始凝結時的溫度(也稱露點);也用於監測絕對濕度、相對濕度 旋轉向量TYPE_ROTATION_VECTOR 軟件驅動型、硬件驅動型 監測設備在三個坐標軸方向上的旋轉向量 監測設備的運動和旋轉 測量溫度TYPE_TEMPERATURE 硬件驅動型 監測設備所處環境的溫度,單位是攝氏度(°C),在API 14及以上版本,該傳感器替換了舊的TYPE_AMBIENT_TEMPERATURE傳感器 監測溫度

傳感器框架(Sensor Framework)


您可以通過Android傳感器框架獲取這些傳感器實例以及返回的監測參數。這面介紹的這些類或是接口,都在android.hardware包中。


SensorManager:您可以通過這個類獲取傳感器服務的實例。該類提供了獲取不同種類傳感器實例的方式、綁定和解除綁定監聽傳感器的方式、以及獲取設備朝向參數的方式(This class provides various methods for accessing and listing sensors, registering and unregistering sensor event listeners, and acquiring orientation information)。該類還提供了若干靜態常量,用於控制傳感器的監測精度和返回數據的頻率,以及校准方式(This class also provides several sensor constants that are used to report sensor accuracy, set data acquisition rates, and calibrate sensors)。

Sensor:通過該類可以獲取指定的傳感器實例。 通過這個實例,您可以調用大量方法來操作傳感器。

SensorEvent:通過這個類,可以創建一個傳感器事件的實例,該實例包含了這些信息:傳感器的原始數據、生成的傳感器事件的類型、數據的精度、事件的時間戳( the raw sensor data, the type of sensor that generated the event, the accuracy of the data, and the timestamp for the event)。

SensorEventListener:這個回調接口包含兩個方法,當傳感器監測的參數或精度發生變化時,這兩個方法用於接收傳感器事件返回的通知。


一般在應用中使用以上API的典型方式為:

確定傳感器的類型以及傳感器的功能(Identifying sensors and sensor capabilities):如果在您的應用程序中,某個功能需要通過特定傳感器的特定功能來實現,那麼檢測設備中的傳感器並尋找合適的類型並使用其特定功能就顯得很有必要。

監測傳感器事件(Monitor sensor events):監測傳感器事件,即如何獲取傳感器的原始數據。當監測數據發生變化時,傳感器事件都會回傳最新的數據。這些數據包含四部分:觸發事件的傳感器的名字、事件的時間戳、事件的精確度、出發事件的原始數據( the name of the sensor that triggered the event, the timestamp for the event, the accuracy of the event, and the raw sensor data that triggered the event)。


傳感器的可用性(Sensor Availability)


不同的設備、不同的Android版本都具有不同的傳感器。下面的這些傳感器是在Android 4.0及以上版本中可用的傳感器(有些已被廢棄但仍然可用):

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(已被廢棄但仍然可用)。


確定傳感器的類型以及傳感器的功能(Identifying Sensors and Sensor Capabilities)


獲取SensorManager實例的方式如下:

private SensorManager mSensorManager;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

獲取當前設備中所有的傳感器列表的方式如下:

List deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);

若您需要獲取某一種特定類型的所有傳感器列表,那麼需要將TYPE_ALL常量替換為:

Sensor.TYPE_GYROSCOPE:這表示您需要獲取所有具備陀螺儀功能的傳感器列表;

Sensor.TYPE_LINEAR_ACCELERATION:這表示您需要獲取所有具備線性加速器功能的傳感器列表;

Sensor.TYPE_GRAVITY:這表示您需要獲取所有具備重力儀功能的傳感器列表;


您還可以調用getDefaultSensor()方法來判斷設備中是否具有指定類型的傳感器,若具有至少一個,那麼方法將不返回空,否則將返回空,方式如下:

private SensorManager mSensorManager;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
  // 設備中至少內置了一個磁力計
  }
else {
  // 設備中沒有內置磁力計
  }

除此之外,通過調用Sersor類中公有方法,您還可以為指定的傳感器設置參數以決定其屬性。比如,調用getResolution()和getMaximumRange()方法可以分別獲取傳感器的回傳原始數據的頻率和測量范圍。調用getPower()方法可以獲取傳感器工作的額定功率。


通過調用Sensor類的getVendor()和getVersion()方法,可以獲取設備中指定生產廠商和指定版本的傳感器。假如您需要監測用戶對設備的傾斜或搖動手勢( tilt and shake),那麼您需要使用重力儀,下面的例子演示了“在設備的所有重力儀中,獲取生產廠商為Google Inc.、版本為3的重力儀傳感器。如果設備中沒有滿足該條件的傳感器,那麼就是用加速器代替,若加速器也沒有,那麼監測用戶手勢的功能將無法實現。

private SensorManager mSensorManager;
private Sensor mSensor;

...

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = null;

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)){="" use="" the="" version="" 3="" gravity="" sensor.="" msensor="gravSensors.get(i);" }="" (msensor="=" null){="" accelerometer.="" (msensormanager.getdefaultsensor(sensor.type_accelerometer)="" !="null){" else{="" sorry,="" there="" are="" no="" accelerometers="" on="" your="" device.="" you="" can't="" play="" this="" game.="" }

還有一些實用方法:getMinDelay()返回一個整數,單位是微秒(microseconds),表示傳感器回傳原始數據的間隔,若返回的值不是0,表示這是一個流傳感器( streaming sensor),流傳感器說的是:不論傳感器回傳的原始監測數據有沒有變化,傳感器均按照這個間隔回傳數據。相反若getMinDelay()返回0,表示不是流傳感器,非流傳感器表示只有監測的數據發生變化時,傳感器才回傳數據。


監測傳感器事件(Monitoring Sensor Events)


為了監聽傳感器回傳的原始數據,您需要實現SensorEventListener接口中的兩個回調方法:onAccuracyChanged() 和 onSensorChanged()。當下列事件發生時,系統會回調這兩個方法:

當傳感器的精度發生變化時(A sensor’s accuracy changes):在這種情況下,onAccuracyChanged()被回調,並回傳一個Sensor類對象的引用,以調整傳感器的精度。精度分為四個等級:SENSOR_STATUS_ACCURACY_LOW、SENSOR_STATUS_ACCURACY_MEDIUM、SENSOR_STATUS_ACCURACY_HIGH、SENSOR_STATUS_UNRELIABLE。

傳感器回傳了新的原始數據時(A sensor reports a new value):這時,onSensorChanged()被回調。並回傳一個SensorEvent 類對象的引用,該對象包含了最新的原始數據,它包括:數據的精度、產生數據的傳感器、數據產生的時間戳、新的數據 等( the accuracy of the data, the sensor that generated the data, the timestamp at which the data was generated, and the new data that the sensor recorded)。


下面演示了監聽光照傳感器的原始數據,並將數據顯示在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) {
    // Do something here if sensor accuracy changes.
  }

  @Override
  public final void onSensorChanged(SensorEvent event) {
    // The light sensor returns a single value.
    // Many sensors return 3 values, one for each axis.
    float lux = event.values[0];
    // Do something with this sensor value.
  }

  @Override
  protected void onResume() {
    super.onResume();
    mSensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
  }

  @Override
  protected void onPause() {
    super.onPause();
    mSensorManager.unregisterListener(this);
  }
}

其中registerListener()方法的第三個參數表示指定傳感器回傳數據的頻率,SENSOR_DELAY_NORMAL表示回傳數據的頻率是200,000微秒( 0.2秒);其他的常量還有SENSOR_DELAY_GAME,表示間隔20,000微秒( 0.02秒);SENSOR_DELAY_UI,表示間隔60,000 微秒(0.06秒);SENSOR_DELAY_FASTEST,表示最快。


使用Google Play過濾不包含特定傳感器的設備(Using Google Play filters to target specific sensor configurations)


在Mainfest.xml中配置標簽,表示您的應用需要指定的傳感器才能運行,如果某台設備未攜帶您指定的傳感器,那麼您的應用將不會出現在該設備所登陸的Google Play應用商店中。比如:

標簽中配置了加速器,並將android:required屬性設為true,這表示您的應用將完全依賴於加速計傳感器才能運行,若設備中不包含加速計,那麼使用該設備登陸Google Play時,您將無法搜索到該應用;若將android:required屬性設為false,表示應用的部分功能需要使用加速計,但整個應用不依賴於加速計,在這種情況下,您依然能在商店中搜索到該應用,但需要使用加速計的那部分功能無法使用。


傳感器的坐標系(Sensor Coordinate System)


Android中傳感器的坐標系如下圖所示: 這裡寫圖片描述vc/yysfK+sbBtcSjrNKyvs3Kx8u1o6y0y8qxedbhysfK+s/ytcSjrLb4xr2w5bXnxNS1xMSsyM+3vc/yyse64cbBtcSjrLTLyrF51uHSssrHyvrWsc/yyc+1xKOotLnWsdPav+2x36OpoaM8L3A+PGhyPjxoMiBpZD0="使用傳感器的注意事項best-practices-for-accessing-and-using-sensors">使用傳感器的注意事項(Best Practices for Accessing and Using Sensors)


在不使用傳感時注銷傳感器的監聽(最好是在onPause()中),否則會耗盡電量(Unregister sensor listeners,If a sensor listener is registered and its activity is paused, the sensor will continue to acquire data and use battery resources unless you unregister the sensor):
private SensorManager mSensorManager;
  ...
@Override
protected void onPause() {
  super.onPause();
  mSensorManager.unregisterListener(this);
}

不要在模擬器上測試傳感器(Don’t test your code on the emulator);

不要在onSensorChanged()方法中做大量操作(Don’t block the onSensorChanged() method):onSensorChanged()方法需要以較高的頻率不斷回傳數據,所以不要阻塞該方法;

避免使用廢棄的方法和常量(Avoid using deprecated methods or sensor types):TYPE_ORIENTATION這種類型的傳感器已被廢棄,欲獲取方向,應調用getOrientation()方法;同樣,TYPE_TEMPERATURE常量已被廢棄,您應當使用TYPE_AMBIENT_TEMPERATURE常量替代。

在使用傳感器之前一定要核實(Verify sensors before you use them):任何傳感器都不是現成提供好的,需要您自己實例化;

謹慎設定傳感器數據的回傳頻率 (Choose sensor delays carefully):當頻率較高時,比較耗電。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved