天天看點

Android Api Demos登頂之路(七十三)Graphics-->Compass

/*
 * 這個demon需要重點關注的是傳感器的使用
 * 傳感器的使用步驟為:
 * 感應檢測功能:
 1、取得SensorManager
 Context.getSysteService(SENSER_SERVICE)方法來取得感應檢測的服務
 2、實作取得感應檢測Sensor狀态的監聽功能
 實作以下兩個SensorEventListener方法來監聽,并取得感應檢測Sensor狀态:
 //在感應檢測到Sensor的精密度有變化時被調用到。  
 public void onAccuracyChanged(Senso sensor,int accuracy);  
 //在感應檢測到Sensor的值有變化時會被調用到。  
 public void onSensorChanged(SensorEvent event);  
 3、實作取得感應檢測Sensor目标各類的值
 實作下列getSensorList()方法來取得感應檢測Sensor的值;
 List<Sensor> sensors = sm.getSensorList(Sensor.TYPE_TEMPERATURE);  
 4、注冊SensorListener
 sm.regesterListener(SensorEventListener listener, Sensor sensor, int rate);  
 第一個參數:監聽Sensor事件,第二個參數是Sensor目标種類的值,第三個參數是延遲時間的精度密度。延遲時間的精密度參數如下:
 參數5、取消注冊
 sm.unregisterListener(SensorEventListener listener) 
 */
public class MainActivity extends Activity {
    private SensorManager mSensorManager;
    private Sensor mSensor;
    // 定義一個數組,用于存儲傳感器中的各種資訊的值
    private float[] mValues=new float[];
    private SampleView mView;

    // 定義加速傳感器和磁場傳感器
    private Sensor mAccelerometer;
    private Sensor mMagnetic;

    // 定義兩個數組,用于存放加速傳感器和磁場傳感器中的資料
    private float[] accelers = new float[];
    private float[] magnetics = new float[];

    private int mMethodId=;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 示範第一種方法使用Sensor.TYPE_ORIENTATION,但我們看到這個常量已經過時了
        // 下面示範第二種方法,用官方推薦的方法
        // mehtod1();
        mehtod2();
    }

    /*
     * 方向傳感器是基于軟體的并且它的資料是通過加速度傳感器和磁場傳感器共同獲得
     * 官方推薦我們使用SensorManager.getOrientation()方法
     */
    private void mehtod2() {
        mMethodId=;
        // 1.擷取傳感器的管理者
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mAccelerometer = mSensorManager
                .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mMagnetic = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

        mView = new SampleView(this);
        setContentView(mView);
    }

    private void mehtod1() {
        // 1.擷取傳感器的管理者
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        // 2.擷取方位傳感器
        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        mView = new SampleView(this);
        setContentView(mView);
    }

    private SensorEventListener mListener = new SensorEventListener() {
        // sensor的值發生變化時被調用.SensorEvent對象包含了有關新的傳感器資料的資訊,
        // 包括:資料的精度、産生資料的傳感器、産生資料時的時間戳、以及傳感器記錄的新的資料。
        @Override
        public void onSensorChanged(SensorEvent event) {
            // 擷取到sensor資訊的值
            mValues = event.values;
            if (mView != null) {
                mView.invalidate();
            }
        }

        // sensor的精密度發生變化時被調用
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }
    };
    private class MyListener implements SensorEventListener {
        @Override
        public void onSensorChanged(SensorEvent event) {
            //擷取加速傳感器的磁場傳感器中的資料
            if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
                accelers=event.values;
            }
            if(event.sensor.getType()==Sensor.TYPE_MAGNETIC_FIELD){
                magnetics=event.values;
            }
            //System.out.println("accelers:"+accelers.length);
            //System.out.println("magnetics:"+magnetics.length);

            float[] R = new float[];
            // 填R矩陣.第一個參數表示要填充的基準矩陣。第二個參數将磁場資料轉換進實際的重力坐标系當中
            // 通常可以設定為null,第三個參數為加速傳感器中的資料(重力傳感器與加速傳感器使用同一套坐标系)
            // 第四個參數為磁場傳感器中的資料,是以我們需要擷取這兩個傳感器中的資料,在對傳感器的監聽接口中擷取
            SensorManager.getRotationMatrix(R, null, accelers, magnetics);
            /*
             * 該方法的作用就是基于旋轉矩陣計算裝置的方向,R就是用于計算裝置方向的基準矩陣。 它是一個4*4或者3*3的矩陣,用一維數組來表示。
             * 其實R是用來儲存磁場和加速度的資料的。那麼它的值是如何擷取的呢?
             * 官方推薦我們使用SensorManage.getRotationMatrix來填充
             */
            SensorManager.getOrientation(R, mValues);
            mValues[] = (float) Math.toDegrees(mValues[]);
            System.out.println("mValues:"+mValues[]);
            if(mView!=null){
                mView.invalidate();
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }
    };

    @Override
    protected void onResume() {
        super.onResume();
        if(mMethodId==){
            //System.out.println("In Method2");
            mSensorManager.registerListener(new MyListener(), mAccelerometer,
                    SensorManager.SENSOR_DELAY_GAME);
            mSensorManager.registerListener(new MyListener(), mMagnetic,
                    SensorManager.SENSOR_DELAY_GAME);
        }else{
        // 注冊傳感器的監聽,第二個參數為傳感器,第三個參數表示延遲時間的精密度
        mSensorManager.registerListener(mListener, mSensor,
                SensorManager.SENSOR_DELAY_GAME);
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if(mMethodId==){
            mSensorManager.unregisterListener(new MyListener());
        }
        // 取消對傳感器的監聽
        mSensorManager.unregisterListener(mListener);

    }

    private class SampleView extends View {
        private Paint mPaint;
        private Path mPath;

        public SampleView(Context context) {
            super(context);
            mPath = new Path();
            // 定義路徑,繪制批南針的指針輪廓
            mPath.moveTo(, -);
            mPath.lineTo(-, );
            mPath.lineTo(, );
            mPath.lineTo(, );
            mPath.close();
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawColor(Color.WHITE);
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setColor(Color.BLACK);
            mPaint.setStyle(Paint.Style.FILL);

            // 擷取畫布的寬和高
            int w = canvas.getWidth();
            int h = canvas.getHeight();
            int cx = w / ;
            int cy = h / ;
            // 将畫布移到螢幕的中心點
            canvas.translate(cx, cy);
            if (mValues != null) {
                // mValues[0]表示y軸與磁北之間的夾角,現在我們需要使指針旋轉一定的角度
                // 讓指針的頭部指向磁北方向
                canvas.rotate(-mValues[]);
            }
            // 繪制指針
            canvas.drawPath(mPath, mPaint);
        }
    }
}
           

繼續閱讀