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

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

編輯:關於Android編程

本文將介紹運動傳感器(Motion Sensors)、位置傳感器(Position Sensors)、環境傳感器(Environment Sensors)。
如需訪問官方原文,您可以點擊這些鏈接:

《Motion Sensors》

《Position Sensors》

《Environment Sensors》


運動傳感器(Motion Sensors)


Android中提供了大量運動傳感器,其中有兩個是硬件驅動型的:加速計(accelerometer) 和 陀螺儀(gyroscope);有三個是軟件和硬件聯合驅動型的: 重力儀(gravity)、 線性加速器(linear acceleration)、旋轉向量傳感器(rotation vector sensors)。軟件驅動型的傳感器具有更高的靈活性,因為它可以從不同的硬件驅動型的傳感器獲取數據並進行組合計算(The availability of the software-based sensors is more variable because they often rely on one or more hardware sensors to derive their data)。


運動傳感器可以監測設備的傾斜、搖動、旋轉 和 搖擺 等( tilt, shake, rotation, or swing)。這些運動通常來自用戶的動作,如在游戲中操縱一輛汽車或一個小球;當然運動傳感器也可以監測設備相對於周圍環境的變化,如設備在汽車中 等。對於第一種情況,傳感器監測的是設備自身的相對運動,而後者監測的則是相對於地面的相對運動。為了監測位置,運動傳感器還可以與其他傳感器配合使用,如地磁傳感器。


所有傳感器都會將監測的數據封裝在SensorEvent類中的多維數組中。比如,加速器監測的加速力(F=m*a^2)可以分解為三維坐標系的三個方向,即三組值。這些數據會被存儲在float型的數組中。下表列出了Android中運動傳感器的回傳值的存儲形式:

運動傳感器類型(Sensor) 回傳的數據(Sensor event data) 描述(Description) 單位(Units of measure) 加速器TYPE_ACCELEROMETER SensorEvent.values[0] SensorEvent.values[1] SensorEvent.values[2] 分別表示:x方向的加速度(包含重力加速度)、y方向的加速度(包含重力加速度)、z方向的加速度(包含重力加速度) m/s^2 重力儀TYPE_GRAVITY SensorEvent.values[0] SensorEvent.values[1] SensorEvent.values[2] 分別表示:x方向的加速度、y方向的加速度、z方向的加速度 m/s^2 陀螺儀TYPE_GYROSCOPE SensorEvent.values[0] SensorEvent.values[1] SensorEvent.values[2] 分別表示:x方向的轉動速率、 y方向的轉動速率、z方向的轉動速率 rad/s 無標定陀螺儀TYPE_GYROSCOPE_UNCALIBRATED SensorEvent.values[0] SensorEvent.values[1] SensorEvent.values[2] SensorEvent.values[3] SensorEvent.values[4] SensorEvent.values[5] 分別表示:x方向的轉動速率(無溫漂補償)、y方向的轉動速率(無溫漂補償)、z方向的轉動速率(無溫漂補償)、x方向的飄移估計值、y方向的飄移估計值、z方向的飄移估計值 rad/s 線性加速器TYPE_LINEAR_ACCELERATION SensorEvent.values[0] SensorEvent.values[1] SensorEvent.values[2] SensorEvent.values[0] SensorEvent.values[1] SensorEvent.values[2] 分別表示:x方向的加速度(包含重力加速度)、y方向的加速度(包含重力加速度)、z方向的加速度(包含重力加速度) 旋轉向量TYPE_ROTATION_VECTOR SensorEvent.values[0] SensorEvent.values[1] SensorEvent.values[2] SensorEvent.values[3] 分別表示:x方向的旋轉向量矢量和(x * sin(θ/2))、y方向的旋轉向量矢量和(y * sin(θ/2))、z方向的旋轉向量矢量和(z * sin(θ/2)) 無單位 計步器TYPE_STEP_COUNTER SensorEvent.values[0] 從最近一次開機到當前為止的用戶的步數 單位:步數

旋轉向量傳感器和重力傳感器最為常用( rotation vector sensor and the gravity sensor),其中前者可以監測手勢、監測角度變化 等。該傳感器可以替代加速器、地磁儀或方向傳感器。

Android傳感器開源項目(Android Open Source Project Sensors)

Android傳感器開源項目(Android Open Source Project Sensors,簡稱AOSP)提供了三種軟件驅動型的傳感器。分別是:重力傳感器、線性加速器 和 旋轉向量傳感器。這些傳感器支持Android 4.0及以上版本,並提供了更高的穩定性。


使用加速器(Using the Accelerometer)


獲取加速器實例的方式如下:

private SensorManager mSensorManager;
private Sensor mSensor;
  ...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

設備受到的加速度與其受力的關系如下:

Ad = - ∑Fs / mass

考慮到設備還受到重力影響:

Ad = -g - ∑F / mass

當設備靜止時,上述公式的g = 9.81 m/s2,當設備自由下落時, g = 0 m/s2。所以為了測量實際的加速度,必須排除g的影響。這可以通過一個高通濾波器實現(achieved by applying a high-pass filter)。相反,使用低通濾波器可以過濾其他因素而只剩重力加速度g。

具體方式如下:

public void onSensorChanged(SensorEvent event){
  // In this example, alpha is calculated as t / (t + dT),
  // where t is the low-pass filter's time-constant and
  // dT is the event delivery rate.

  final float alpha = 0.8;

  // Isolate the force of gravity with the low-pass filter.
  gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
  gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
  gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];

  // Remove the gravity contribution with the high-pass filter.
  linear_acceleration[0] = event.values[0] - gravity[0];
  linear_acceleration[1] = event.values[1] - gravity[1];
  linear_acceleration[2] = event.values[2] - gravity[2];
}

當設備放在水平桌面時:

從左向右移動設備,則x方向的加速度為正值;

從底部向頂部移動設備,則y方向的加速度為正值;

從下向上以加速度A的大小拋出設備時,則z方向的加速度為A+9.81,那麼設備的相對加速度為A - 9.81。(排除重力加速度的影響)

設備靜止時垂直地面方向的相對加速度為-9.81 m/s2。(排除重力加速度的影響)


使用重力傳感器(Using the Gravity Sensor)


獲取重力傳感器實例的方式如下:

private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);

使用陀螺儀(Using the Gyroscope)


陀螺儀實例的獲取方式如下:

private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

對於陀螺儀,從x,y,z軸的負方向向正方向看去,順時針轉動為正值,反之為負值。


使用方式如下:

// Create a constant to convert nanoseconds to seconds.
private static final float NS2S = 1.0f / 1000000000.0f;
private final float[] deltaRotationVector = new float[4]();
private float timestamp;

public void onSensorChanged(SensorEvent event) {
  // This timestep's delta rotation to be multiplied by the current rotation
  // after computing it from the gyro sample data.
  if (timestamp != 0) {
    final float dT = (event.timestamp - timestamp) * NS2S;
    // Axis of the rotation sample, not normalized yet.
    float axisX = event.values[0];
    float axisY = event.values[1];
    float axisZ = event.values[2];

    // Calculate the angular speed of the sample
    float omegaMagnitude = sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);

    // Normalize the rotation vector if it's big enough to get the axis
    // (that is, EPSILON should represent your maximum allowable margin of error)
    if (omegaMagnitude > EPSILON) {
      axisX /= omegaMagnitude;
      axisY /= omegaMagnitude;
      axisZ /= omegaMagnitude;
    }

    // Integrate around this axis with the angular speed by the timestep
    // in order to get a delta rotation from this sample over the timestep
    // We will convert this axis-angle representation of the delta rotation
    // into a quaternion before turning it into the rotation matrix.
    float thetaOverTwo = omegaMagnitude * dT / 2.0f;
    float sinThetaOverTwo = sin(thetaOverTwo);
    float cosThetaOverTwo = cos(thetaOverTwo);
    deltaRotationVector[0] = sinThetaOverTwo * axisX;
    deltaRotationVector[1] = sinThetaOverTwo * axisY;
    deltaRotationVector[2] = sinThetaOverTwo * axisZ;
    deltaRotationVector[3] = cosThetaOverTwo;
  }
  timestamp = event.timestamp;
  float[] deltaRotationMatrix = new float[9];
  SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector);
    // User code should concatenate the delta rotation we computed with the current rotation
    // in order to get the updated rotation.
    // rotationCurrent = rotationCurrent * deltaRotationMatrix;
   }
}

位置傳感器(Position Sensors)


Android中提供了兩類位置傳感器用於確定當前設備的位置:加速器和地磁儀(the geomagnetic field sensor and the accelerometer)。Android還提供了用於監測設備與周圍物體距離的傳感器(如手機貼近耳朵時點滅屏幕),即接近度傳感器(proximity sensor)。磁力儀和接近度傳感器都是硬件驅動型的,下表列舉了各種位置傳感器回傳值所代表的意義:


位置傳感器(Sensor) 回傳值(Sensor event data) 描述(Description) 單位(Units of measure) 游戲類型的旋轉向量傳感器TYPE_GAME_ROTATION_VECTOR SensorEvent.values[0] SensorEvent.values[1] SensorEvent.values[2] 分別表示:x方向的轉動向量(x * sin(θ/2))、y方向的轉動向量(y * sin(θ/2))、z方向的轉動向量(z * sin(θ/2)) 無單位 地磁類型的旋轉向量傳感器TYPE_GEOMAGNETIC_ROTATION_VECTOR 同上 同上 同上 磁力儀TYPE_MAGNETIC_FIELD 同上 分別表示:x方向受到的磁場強度、y方向受到的磁場強度、z方向受到的磁場強度 μT 微特斯拉 無標定的磁力儀TYPE_MAGNETIC_FIELD_UNCALIBRATED SensorEvent.values[0] SensorEvent.values[1] SensorEvent.values[2] SensorEvent.values[3] SensorEvent.values[4] SensorEvent.values[5] 分別表示:x方向受到的磁場強度(無硬鐵校准)、y方向受到的磁場強度(無硬鐵校准)、z方向受到的磁場強度(無硬鐵校准)、沿x軸鐵偏差校准、沿y軸鐵偏差校准、沿z軸鐵偏差校准 同上 接近度傳感器TYPE_PROXIMITY SensorEvent.values[0] 與物體的距離 厘米 cm

計算設備的方向(Computing the Device’s Orientation)

下面的代碼演示了如何檢測設備的朝向:

private SensorManager mSensorManager;
...
// Rotation matrix based on current readings from accelerometer and magnetometer.
final float[] rotationMatrix = new float[9];
mSensorManager.getRotationMatrix(rotationMatrix, null,
  accelerometerReading, magnetometerReading);

// Express the updated rotation matrix as three orientation angles.
final float[] orientationAngles = new float[3];
mSensorManager.getOrientation(rotationMatrix, orientationAngles);

獲得的結果如下:

方位角(Azimuth ):與z軸負方向的夾角。即手機的羅盤方向與北極點的夾角( This is the angle between the device’s current compass direction and magnetic north. If the top edge of the device faces magnetic north)。如果設備的頂部朝向正北,則該角度為0;若朝向正南,角度為180;朝向正東,為90度;正西為270度

傾斜角(Pitch ):與x軸正方向的夾角。即手機屏幕的平行線與地面的平行線的夾角( This is the angle between a plane parallel to the device’s screen and a plane parallel to the ground)。若將設備水平拿在手上,並將設備尾部朝向自己,這時若將設備旋轉:頭部慢慢朝向地面,此時該角度將成為正值,即0到90度(If you hold the device parallel to the ground with the bottom edge closest to you and tilt the top edge of the device toward the ground, the pitch angle becomes positive)。相反,若將頭部慢慢朝向天空,此時將變為負值,即0到-90度。該角度的范圍是-180到+180度。

滾動角(Roll ):與y軸正方向的夾角。即手機屏幕的垂線與地面垂線的夾角(This is the angle between a plane perpendicular to the device’s screen and a plane perpendicular to the ground)。若將設備水平拿在手上,並將設備尾部朝向自己,這時若將設備旋轉:左側慢慢朝向地面,此時該角度將成為正值,即0到90度。若是右側慢慢朝向地面,此時該角度將成為負值,即0到-90度。該角度的變化為-90度到+90度。


與其他傳感器不同,獲取方向傳感器使用的是getRotationMatrix()方法與getOrientation()方法。示例如下:

public class SensorActivity extends Activity implements SensorEventListener {

  private SensorManager mSensorManager;
  private final float[] mAccelerometerReading = new float[3];
  private final float[] mMagnetometerReading = new float[3];

  private final float[] mRotationMatrix = new float[9];
  private final float[] mOrientationAngles = new float[3];

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
  }

  @Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // Do something here if sensor accuracy changes.
    // You must implement this callback in your code.
  }

  @Override
  protected void onResume() {
    super.onResume();

    // Get updates from the accelerometer and magnetometer at a constant rate.
    // To make batch operations more efficient and reduce power consumption,
    // provide support for delaying updates to the application.
    //
    // In this example, the sensor reporting delay is small enough such that
    // the application receives an update before the system checks the sensor
    // readings again.
    mSensorManager.registerListener(this, Sensor.TYPE_ACCELEROMETER,
      SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
    mSensorManager.registerListener(this, Sensor.TYPE_MAGNETIC_FIELD,
      SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
  }

  @Override
  protected void onPause() {
    super.onPause();

    // Don't receive any more updates from either sensor.
    mSensorManager.unregisterListener(this);
  }

  // Get readings from accelerometer and magnetometer. To simplify calculations,
  // consider storing these readings as unit vectors.
  @Override
  public void onSensorChanged(SensorEvent event) {
    if (event.sensor == Sensor.TYPE_ACCELEROMETER) {
      System.arraycopy(event.values, 0, mAccelerometerReading,
        0, mAccelerometerReading.length);
    }
    else if (event.sensor == Sensor.TYPE_MAGNETIC_FIELD) {
      System.arraycopy(event.values, 0, mMagnetometerReading,
        0, mMagnetometerReading.length);
    }
  }

  // Compute the three orientation angles based on the most recent readings from
  // the device's accelerometer and magnetometer.
  public void updateOrientationAngles() {
    // Update rotation matrix, which is needed to update orientation angles.
    mSensorManager.getRotationMatrix(mRotationMatrix, null,
      mAccelerometerReading, mMagnetometerReading);

    // "mRotationMatrix" now has up-to-date information.

    mSensorManager.getOrientation(mRotationMatrix, mOrientationAngles);

    // "mOrientationAngles" now has up-to-date information.
  }
}

使用接近度傳感器(Using the Proximity Sensor)

獲取接近度傳感器實例的方式如下:

private SensorManager mSensorManager;
private Sensor mSensor;
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

該傳感器通常用於監測用戶打電話時,耳朵距離設備的距離。大部分接近度傳感器會返回距離的絕對值,單位是cm,而少數傳感器僅會返回代表距離物體遠近的boolean值。下面的例子演示了如何應用該傳感器:

public class SensorActivity extends Activity implements SensorEventListener {
  private SensorManager mSensorManager;
  private Sensor mProximity;

  @Override
  public final void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Get an instance of the sensor service, and use that to get an instance of
    // a particular sensor.
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
  }

  @Override
  public final void onAccuracyChanged(Sensor sensor, int accuracy) {
    // Do something here if sensor accuracy changes.
  }

  @Override
  public final void onSensorChanged(SensorEvent event) {
    float distance = event.values[0];
    // Do something with this sensor data.
  }

  @Override
  protected void onResume() {
    // Register a listener for the sensor.
    super.onResume();
    mSensorManager.registerListener(this, mProximity, SensorManager.SENSOR_DELAY_NORMAL);
  }

  @Override
  protected void onPause() {
    // Be sure to unregister the sensor when the activity pauses.
    super.onPause();
    mSensorManager.unregisterListener(this);
  }
}

環境傳感器(Environment Sensors)


通過環境傳感器,您可以獲取設備所處環境的濕度、溫度、光照強度、大氣壓力等等。

與其他傳感器不同的是,環境傳感器並不返回一組數據,而且沒有低通和高通濾波器,如下表所示:

傳感器(Sensor) 回傳數據(Sensor event data) 單位(Units of measure) 描述(Data description) 溫度傳感器TYPE_AMBIENT_TEMPERATURE event.values[0] °C 溫度 光強傳感器TYPE_LIGHT event.values[0] 勒克斯lx 光強 壓力傳感器TYPE_PRESSURE event.values[0] 百帕 或 毫巴(hPa or mbar) 大氣壓強 相對濕度傳感器TYPE_RELATIVE_HUMIDITY event.values[0] % 相對濕度

使用光線、壓力和溫度傳感器(Using the Light, Pressure, and Temperature Sensors)

示例如下:

public class SensorActivity extends Activity implements SensorEventListener {
  private SensorManager mSensorManager;
  private Sensor mPressure;

  @Override
  public final void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Get an instance of the sensor service, and use that to get an instance of
    // a particular sensor.
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mPressure = mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
  }

  @Override
  public final void onAccuracyChanged(Sensor sensor, int accuracy) {
    // Do something here if sensor accuracy changes.
  }

  @Override
  public final void onSensorChanged(SensorEvent event) {
    float millibars_of_pressure = event.values[0];
    // Do something with this sensor data.
  }

  @Override
  protected void onResume() {
    // Register a listener for the sensor.
    super.onResume();
    mSensorManager.registerListener(this, mPressure, SensorManager.SENSOR_DELAY_NORMAL);
  }

  @Override
  protected void onPause() {
    // Be sure to unregister the sensor when the activity pauses.
    super.onPause();
    mSensorManager.unregisterListener(this);
  }
}

使用濕度傳感器(Using the Humidity Sensor)

使用濕度傳感器與光照傳感器 等環境傳感器的方式一致。若您的設備上同時包含了濕度傳感器與溫度傳感器,那麼可以利用這兩個傳感器返回的值計算露點(Dew point)和絕對濕度( absolute humidity):

露點(Dew point):露點,也稱冷凝點,表示水蒸氣冷凝成液態水所需要的溫度。露點的計算公式如下:
這裡寫圖片描述

其中:

td表示露點溫度,單位是攝氏度;

t表示當前溫度,單位是攝氏度;<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxjb2RlPjxjb2RlPjxjb2RlPlJIse3Kvs/gttTKqrbIo6zWtc6qsNm31rHI0M7KvaOoJaOpo7s8L2NvZGU+PC9jb2RlPjwvY29kZT48L3A+DQo8cD48Y29kZT48Y29kZT48Y29kZT5tID0gMTcuNjKjuzwvY29kZT48L2NvZGU+PC9jb2RlPjwvcD4NCjxwPjxjb2RlPjxjb2RlPjxjb2RlPlRuID0gMjQzLjEyo7s8L2NvZGU+PC9jb2RlPjwvY29kZT48L3A+DQo8aHIgLz4NCjxjb2RlPjxjb2RlPjxjb2RlPr74ttTKqrbIo6hBYnNvbHV0ZSBodW1pZGl0eaOpo7qx7cq+serXvNe0zKzPwig3NjBtbUhnKcO/waK3vcPXyqq/1cb41tDL+bqsy67V9Mb7tcTW2MG/oaO++LbUyqq2yLXEvMbL47mryr3I58/Co7o8YnIgLz4NCjxpbWcgYWx0PQ=="這裡寫圖片描述" src="/uploadfile/Collfiles/20160823/201608230913451106.jpg" title="" />

其中:

dv表示絕對濕度,單位是g/m^3,克/立方米。

t表示當前環境溫度;

RH表示相對濕度,值為百分比形式(%);

m = 17.62

Tn = 243.12 攝氏度

A = 6.112 hPa

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