標籤:
一般情況下,在android系統中擷取手機的方位資訊在api中有TYPE_ORIENTATION常量,可以像得到加速度感應器那樣得到方向感應器sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);然而我們這樣做的話在最新版的SDK中就會看到這麼一句話:“TYPE_ORIENTATION This constant is deprecated. use SensorManager.getOrientation() instead. ”即這種方式也到期,不建議使用!Google建議我們在應用程式中使用SensorManager.getOrientation()來獲得未經處理資料。
public static float[] getOrientation (float[] R, float[] values)
第一個參數是R[] 是一個旋轉矩陣,用來儲存磁場和加速度的資料,可以理解為這個函數的傳入值,通過它這個函數給你求出方位角。
第二個參數就是這個函數的輸出了,他有函數自動為我們填充,這就是我們想要的。
values[0] :方向角,但用(磁場+加速度)得到的資料範圍是(-180~180),也就是說,0表示正北,90表示正東,180/-180表示正南,-90表示正西。而直接通過方向感應器資料範圍是(0~359)360/0表示正北,90表示正東,180表示正南,270表示正西。
values[1] pitch 傾斜角 即由靜止狀態開始,前後翻轉,手機頂部往上抬起(0~-90),手機尾部往上抬起(0~90)
values[2] roll 旋轉角 即由靜止狀態開始,左右翻轉,手機左側抬起(0~90),手機右側抬起(0~-90)
現在問題是這個R[]怎麼擷取,其實他是通過函數getRotationMatrix得到的。
看看getRotationMatrix的定義:
public static boolean getRotationMatrix (float[] R, float[] I, float[] gravity, float[] geomagnetic)
解釋以下參數,第一個就是我們需要填充的R數組,大小是9
第二個是是一個轉換矩陣,將磁場資料轉換進實際的重力座標中 一般預設情況下可以設定為null
第三個是一個大小為3的數組,表示從加速度感應器擷取來的資料 在onSensorChanged中
第四個是一個大小為3的數組,表示從磁場感應器擷取來的資料 在onSensorChanged中
範例程式碼:
package com.example.testoritation;import android.app.Activity;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;import android.os.Bundle;import android.view.Menu;import android.widget.TextView;//實現感應器事件監聽:SensorEventListenerpublic class MainActivity extends Activity implements SensorEventListener{private SensorManager sensorManager;private Sensor acc_sensor;private Sensor mag_sensor;//加速度感應器資料float accValues[]=new float[3];//地磁感應器資料float magValues[]=new float[3];//旋轉矩陣,用來儲存磁場和加速度的資料float r[]=new float[9];//類比方向感應器的資料(未經處理資料為弧度)float values[]=new float[3];TextView show_change=null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);show_change=(TextView) findViewById(R.id.show_change);sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);acc_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);mag_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);//給感應器註冊監聽:sensorManager.registerListener(this, acc_sensor, SensorManager.SENSOR_DELAY_GAME);sensorManager.registerListener(this, mag_sensor,SensorManager.SENSOR_DELAY_GAME);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}//感應器狀態改變時的回調方法@Overridepublic void onSensorChanged(SensorEvent event) {if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){accValues=event.values;}else if(event.sensor.getType()==Sensor.TYPE_MAGNETIC_FIELD){magValues=event.values;}/**public static boolean getRotationMatrix (float[] R, float[] I, float[] gravity, float[] geomagnetic) * 填充旋轉數組r * r:要填充的旋轉數組 * I:將磁場資料轉換進實際的重力座標中 一般預設情況下可以設定為null * gravity:加速度感應器資料 * geomagnetic:地磁感應器資料 */SensorManager.getRotationMatrix(r, null, accValues, magValues);/** * public static float[] getOrientation (float[] R, float[] values) * R:旋轉數組 * values :類比方向感應器的資料 */SensorManager.getOrientation(r, values);//將弧度轉化為角度後輸出StringBuffer buff=new StringBuffer();for(float value:values){value=(float) Math.toDegrees(value);buff.append(value+" ");}show_change.setText(buff.toString());}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {}}
Android 感應器之方向感應器