雖然 Android系統支持十餘種傳感器的類型,但是手機裏的傳感器設備卻是有限的,基本上不會有哪部手機能夠支持全部的傳感器功能.
先來看一下幾種常用的傳感器:
光照傳感器
光照傳感器還是會比較常用到的,系統就有個自動調整屏幕亮度的功能。它會檢測手機周圍環境的光照強度,然後對手機屏幕的亮度進行相應地調整,以此保證不管是在強光還是弱光下,手機屏幕都能夠看得清
來看下是如何使用的:
public class SensorActivity extends Activity {
/**
* 用於顯示光照強度
*/
private TextView sensor;
/**
* SensorManager是系統所有傳感器管理器
*/
private SensorManager sensormanager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sensor);
sensor = (TextView) findViewById(R.id.texts);
// 先通過getSystemService獲取SensorManager的實例
sensormanager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// 通過getDefaultSensor得到傳感器的類型返回一個sensor的實例,此時的傳感器sensor就代表光照傳感器
Sensor sensor = sensormanager.getDefaultSensor(Sensor.TYPE_LIGHT);
// 通過registerListener方法註冊
/**
* 第一個參數就是SensorEventListener的實例 第二個參數就是Sensor的實例,第三個參數表示傳感器輸出信息的更新速率
* 共有SENSOR_DELAY_UI、 SENSOR_DELAY_NORMAL、 SENSOR_DELAY_GAME 和
* SENSOR_DELAY_FASTEST 這四種值可選 這個更新速率是依次遞增的
*/
sensormanager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
/**
* 實現SensorEventListener接口實現對傳感器輸出的信號進行監聽
*/
private SensorEventListener listener = new SensorEventListener() {
/**
* 當傳感器數值發生變化的時候會調用此方法
*/
@Override
public void onSensorChanged(SensorEvent event) {
// values數組當中的下標值就是當前光照強度
// 所有傳感器的輸出信息都是方法event.values[]這個數組當中的
float evens = event.values[0];
sensor.setText("當前光照強度" + evens);
Log.i("運行到了嗎", "" + evens);
}
/**
* 當傳感器的精度發生變化的時候就調用這個方法
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (sensormanager != null) {
sensormanager.unregisterListener(listener);//釋放資源
}
}
}
運行成功之後可以看到打印出來的信息:
有少部分手機沒有光照傳感器的就沒有辦法獲取到這個值了。
加速度傳感器
Android中的加速度傳感器則是提供了一種機制,使得我們能夠在應用程序中獲取到手機當前的加速度信息, 合理利用這些信息就可以開發出一些比較好玩的功能。現在就實現一下像微信搖一搖那種功能.
每種傳感器的用法都差不多,加速度傳感器輸出的信息同樣也是存放在 SensorEvent的 values 數組中的,只不過此時的 values數組中會有三個值, 分別代表手機在 X軸、 Y軸和 Z 軸方向上的加速度信息。
X軸、Y軸、Z軸在空間座標系上的含義如圖 :
當手機豎立起來的時候這個加速度是作用在 Y軸上的,當手機橫立起來的時候,這個加速度是作用在 X軸上的。當手機平放的時候,這個加速度是作用在 Z 軸上的。由於重力加速度的存在,即使手機在靜止的情況下,某一個軸上的加速度也有可能達到9.8m/s2.
public class ShakeSensorActivity extends Activity{
private SensorManager manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sensor);
manager=(SensorManager) getSystemService(Context.SENSOR_SERVICE);
//獲取到加速度傳感器
Sensor sensor=manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
manager.registerListener(listener, sensor,SensorManager.SENSOR_DELAY_NORMAL);
}
private SensorEventListener listener=new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
//加速度可能會是負值所以要取它們的絕對值
float x=Math.abs(event.values[0]);
float y=Math.abs(event.values[1]);
float z=Math.abs(event.values[2]);
//因爲即使手機在靜止的情況下,某一個軸上的加速度也有可能達到9.8m/s2所以這裏要寫一個比9.8大的比較合適的值來判斷
if(x>30||y>30||z>30){
Toast.makeText(ShakeSensorActivity.this, "搖一搖", Toast.LENGTH_SHORT).show();
Log.i("ShakeSensorActivity","搖一搖");
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
protected void onDestroy() {
if(manager!=null){
manager.unregisterListener(listener);
}
};
}
運行成功後可以看到logcat輸出信息:
方向傳感器
獲取方向傳感器的實例:
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
但是Android已經廢棄了 Sensor.TYPE_ORIENTATION 這種傳感器類型.Android獲取手機旋轉的方向和角度是通過加速度傳感器和地磁傳感器共同計算得出的,這也是 Android目前推薦使用的方式。
製作簡易指南針:
public class MainActivity extends Activity {
private SensorManager sensorManager;
private ImageView compassImg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setViews();
//傳感器管理器
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//加速度傳感器
Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//地磁傳感器
Sensor magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(sensorEventListener, accelerometer, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(sensorEventListener, magnetic, SensorManager.SENSOR_DELAY_GAME);
}
private void setViews() {
compassImg = (ImageView) findViewById(R.id.compass_img);
}
@Override
protected void onDestroy() {
super.onDestroy();
if(sensorManager != null){
sensorManager.unregisterListener(sensorEventListener);
}
}
//傳感器變化監聽器
private SensorEventListener sensorEventListener = new SensorEventListener() {
float[] accelerometerValues = new float[3];
float[] magneticValues = new float[3];
private float lastRotateDegree;
@Override
public void onSensorChanged(SensorEvent event) {
//判斷當前是地磁還是加速度傳感器
if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
accelerometerValues = event.values.clone();
}else if(event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD){
magneticValues = event.values.clone();
}
float[] R = new float[9];
float[] values = new float[3];
SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues);
SensorManager.getOrientation(R, values);
//Log.i("TAG", "values[0] is "+ Math.toDegrees(values[0]));
//將計算出的旋轉角度取反,用於旋轉指南針的背景圖
float rotateDegree = -(float)Math.toDegrees(values[0]);
if(Math.abs(rotateDegree - lastRotateDegree) > 1){
//旋轉補間動畫
RotateAnimation rotateAnimation = new RotateAnimation(lastRotateDegree, rotateDegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setFillAfter(true);
compassImg.startAnimation(rotateAnimation);
lastRotateDegree = rotateDegree;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
}