Android系統(tǒng)提供了對(duì)傳感器的支持障涯,如果手機(jī)設(shè)備的硬件提供了這些傳感器罐旗,Android應(yīng)用可以通過(guò)傳感器來(lái)獲取設(shè)備的外界條件,包括手機(jī)設(shè)備的運(yùn)行狀態(tài)唯蝶、當(dāng)前擺放方向九秀、外界的磁場(chǎng)、溫度和壓力等粘我。Android系統(tǒng)提供了驅(qū)動(dòng)程序去管理這些傳感器硬件鼓蜒,當(dāng)傳感器感知到外部環(huán)境發(fā)生改變時(shí),Android系統(tǒng)負(fù)責(zé)管理這些傳感器數(shù)據(jù)征字。
一. Android中11中常見(jiàn)的傳感器
- 加速度傳感器:SENSOR_TYPE_ACCELEROMETER
- 磁力傳感器:SENSOR_TYPE_FIELD
- 方向傳感器:SENSOR_TYPE_ORIENTATION
- 陀螺儀傳感器:SENSOR_TYPE_GYROSCOPE
- 光線感應(yīng)傳感器:SENSOR_TYPE_LIGHT
- 壓力傳感器:SENSOR_TYPE_PRESSURE
- 溫度傳感器:SENSOR_TYPE_TEMPERATURE
- 接近傳感器:SENSOR_TYPE_PROXIMITY
- 重力傳感器:SENSOR_TYPE_GRAVITY
- 線性加速度傳感器:SENSOR_TYPE_LINEAR_ACCELERATION
- 旋轉(zhuǎn)矢量傳感器:SENSOR_TYPE_ROTATION_VECTOR
二. 使用傳感器
使用傳感器的步驟分為5步:
- 獲取SensorManager對(duì)象
調(diào)用Context的getSystemService(Context.SENSOR_SERVICE)方法獲取SensorManager對(duì)象都弹,SensorManager對(duì)象代表系統(tǒng)的傳感器管理服務(wù)。 - 獲取Sensor對(duì)象
調(diào)用SensorManager的getDefaultSensor(int type)方法獲取指定類型的傳感器匙姜。 - 注冊(cè)Sensor對(duì)象
在Activity的onResume()方法中調(diào)用SensorManager的registerListener()方法為指定的傳感器注冊(cè)監(jiān)聽(tīng)器畅厢,程序通過(guò)實(shí)現(xiàn)監(jiān)聽(tīng)器即可獲取傳感器傳來(lái)的數(shù)據(jù)。 - 重寫(xiě)onAccuracyChanged搁料,onSensorChanged方法
當(dāng)傳感器的精度和數(shù)據(jù)發(fā)送變化時(shí)或详,在這兩個(gè)方法中做相應(yīng)的操作。 - 注銷Sensor對(duì)象
在Activity的onPause()方法中調(diào)用SensorManager的unregisterListener()方法注銷指定的傳感器監(jiān)聽(tīng)器郭计。
SensorManager提供的注冊(cè)傳感器的方法為registerListener(SensorEventListener listener, Sensor sensor, int rate)霸琴,該方法的三個(gè)參數(shù)說(shuō)明如下:
- listener:監(jiān)聽(tīng)傳感器事件的監(jiān)聽(tīng)器。該監(jiān)聽(tīng)器需要實(shí)現(xiàn)SensorEventListener接口昭伸。
- sensor:傳感器對(duì)象梧乘。
- rate:指定獲取傳感器數(shù)據(jù)的頻率。rate有以下幾個(gè)頻率值:
- SensorManager.SENSOR_DELAY_FASTEST:最快庐杨。延遲最小选调,只有特別依賴于傳感器數(shù)據(jù)的應(yīng)用推薦采用這種頻率,這種模式可能造成手機(jī)電量大量消耗灵份。
- SensorManager.SENSOR_DELAY_GAME:適合游戲的頻率仁堪。一般有實(shí)時(shí)性要求的應(yīng)用適合使用這種頻率。
- SensorManager.SENSOR_DELAY_NORMAL:正常頻率填渠。一般對(duì)實(shí)時(shí)性要求不是特別高的應(yīng)用適合使用這種頻率弦聂。
- SensorManager.SENSOR_DELAY_UI:適合普通用戶界面的頻率鸟辅。這種模式比較省電,而且系統(tǒng)開(kāi)銷也很小莺葫,但延遲較大匪凉。
三. 讀取傳感器數(shù)據(jù)
在onSensorChanged(SensorEvent event)方法中有一個(gè)參數(shù)event,通過(guò)event可以獲取傳感器的類型以及傳感器的數(shù)據(jù)捺檬。
- 獲取傳感器的類型:event.sensor.getType()
- 獲取傳感器的數(shù)據(jù):event.values[i]再层,i為0,1,2...,不同傳感器堡纬,event.values[i]對(duì)應(yīng)的數(shù)據(jù)不同聂受,下面以加速度傳感器為例,解釋values[i]的含義烤镐。
* <h4>{@link android.hardware.Sensor#TYPE_ACCELEROMETER
* Sensor.TYPE_ACCELEROMETER}:</h4> All values are in SI units (m/s^2)
* <ul>
* <li> values[0]: Acceleration minus Gx on the x-axis </li>
* <li> values[1]: Acceleration minus Gy on the y-axis </li>
* <li> values[2]: Acceleration minus Gz on the z-axis </li>
* </ul>
* <p>
* A sensor of this type measures the acceleration applied to the device
* (<b>Ad</b>). Conceptually, it does so by measuring forces applied to the
* sensor itself (<b>Fs</b>) using the relation:
* </p>
* <b><center>Ad = - ∑Fs / mass</center></b>
* <p>
* In particular, the force of gravity is always influencing the measured
* acceleration:
* </p>
* <b><center>Ad = -g - ∑F / mass</center></b>
* <p>
* For this reason, when the device is sitting on a table (and obviously not
* accelerating), the accelerometer reads a magnitude of <b>g</b> = 9.81
* m/s^2
* </p>
* <p>
* Similarly, when the device is in free-fall and therefore dangerously
* accelerating towards to ground at 9.81 m/s^2, its accelerometer reads a
* magnitude of 0 m/s^2.
* </p>
* <p>
* It should be apparent that in order to measure the real acceleration of
* the device, the contribution of the force of gravity must be eliminated.
* This can be achieved by applying a <i>high-pass</i> filter. Conversely, a
* <i>low-pass</i> filter can be used to isolate the force of gravity.
* </p>
* <pre class="prettyprint">
* public void onSensorChanged(SensorEvent event)
* {
* // alpha is calculated as t / (t + dT)
* // with t, the low-pass filter's time-constant
* // and dT, the event delivery rate
* final float alpha = 0.8;
* 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];
* linear_acceleration[0] = event.values[0] - gravity[0];
* linear_acceleration[1] = event.values[1] - gravity[1];
* linear_acceleration[2] = event.values[2] - gravity[2];
* }
* </pre>
* <p>
* <u>Examples</u>:
* <ul>
* <li>When the device lies flat on a table and is pushed on its left side
* toward the right, the x acceleration value is positive.</li>
* <li>When the device lies flat on a table, the acceleration value is
* +9.81, which correspond to the acceleration of the device (0 m/s^2) minus
* the force of gravity (-9.81 m/s^2).</li>
* <li>When the device lies flat on a table and is pushed toward the sky
* with an acceleration of A m/s^2, the acceleration value is equal to
* A+9.81 which correspond to the acceleration of the device (+A m/s^2)
* minus the force of gravity (-9.81 m/s^2).</li>
* </ul>
從加速度傳感器源代碼中可以看出饺饭,values[0]表示x軸上的加速度,values[1]表示y軸上的加速度职车,values[2]表示z軸上的加速度。
四. 針對(duì)是否有傳感器功能優(yōu)化
因?yàn)椴⒎撬惺謾C(jī)都支持所有傳感器鹊杖,不用系統(tǒng)引入的傳感器不同悴灵,所以在使用之前有必要判斷一下,骂蓖、從而提高性能积瞒。
判斷是否有傳感器有兩種方法:
- 運(yùn)行時(shí)檢測(cè)
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (sensor != null){
//傳感器存在
}else{
//傳感器不存在
}
- 使用Android Market過(guò)濾器來(lái)限定目標(biāo)設(shè)備必須帶有指定傳感器配置。
<use-feature
name = "android.hardware.sensor.orientation"
android:required = "true"/>
五. 方向傳感器小Demo
利用方向傳感器登下,界面中的圖片向手機(jī)旋轉(zhuǎn)的反方向旋轉(zhuǎn)茫孔。代碼如下:
public class MainActivity extends AppCompatActivity implements SensorEventListener{
private ImageView mIvSensor;
private Sensor mSensor;
private SensorManager mSensorManager;
private float mDegress = 0f;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIvSensor = (ImageView) findViewById(R.id.iv_sensor);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_UI); //rate suitable for the user interface
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION){
float degree = - event.values[0];
RotateAnimation rotateAnimation = new RotateAnimation(mDegress, degree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(100);
mIvSensor.startAnimation(rotateAnimation);
mDegress = degree;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//TODO:當(dāng)傳感器精度發(fā)生變化時(shí)
}
}
演示效果:
六. 注意
- 別忘記注銷。
- 不要阻塞onSensorChanged方法被芳。
- 避免使用過(guò)時(shí)的方法或傳感器類型缰贝。
- 在使用前先驗(yàn)證傳感器是否存在。
- 謹(jǐn)慎選擇傳感器延時(shí)畔濒。