2012/12/02

Android Sensor取得手機移動方向

這個程式是透過Android Sensor的TYPE_ACCELEROMETER來取得到手機加速度,取得加速度根手機移動方向有何關係呢?

因為物體在位移時會對某個空間產生速度,透過速度的大小可以去抓取手機的方向,那怎麼知道手機的左、右、上和下的數值在X以及Y軸要怎麼表示?

透過300次資料比對後,畫出這張示意圖。手機垂直時,XY軸數值就如下方所表示的,水平的我還沒有去測試過,不過我想應該一樣的。




物體加速度時會產生所謂的反作用力,反作用力出現時,我們可以透過時間長短去抵銷,或是透過移動範圍去解決反作用力這令人頭痛的問題。



package com.example.getangle;

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.view.WindowManager;
import android.widget.TextView;

public class MainActivity extends Activity implements SensorEventListener {
    SensorManager manager;
    Sensor sensor;
    static float[] values = new float[3];
    static float[] init = new float[] { 0.0f, 0.0f, 0.0f };
    static float x, y, z;
    TextView textView;
    long lastUpdateTime = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        manager = (SensorManager) getSystemService(SENSOR_SERVICE);
        sensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        textView = (TextView) findViewById(R.id.text);
    }

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

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    public void onAccuracyChanged(Sensor arg0, int arg1) {
    }

    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
            if (init[0] == 0 && init[1] == 0 && init[2] == 0) {
                init[0] = event.values[0];
                init[1] = event.values[1];
                init[2] = event.values[2];
            }
            values = event.values;
            x = init[0] - values[0];
            y = init[1] - values[1];
            z = init[2] - values[2];
        }
        long currentUpdateTime = System.currentTimeMillis(); // 取得目前系統時間
        long timeInterval = currentUpdateTime - lastUpdateTime; // 時間秒數=目前系統時間-值變化的時間
        if (timeInterval < 300) // 判斷目前時間是否小於300毫秒
            lastUpdateTime = currentUpdateTime; // 值變化時間=當前時間
        else {
            if (x < -5) {
                textView.setText("左邊");
            } else if (x > 5) {
                textView.setText("右邊");
            } else if (x > -5 && x < 5) {
                if (y > 5) {
                    textView.setText("上");
                } else if (y < -5) {
                    textView.setText("下");
                }
            } else {
                textView.setText("");
            }
        }

        // y+
        // x+ -
        // -

    }

    private final void register() {
        manager.registerListener(this, sensor,
                SensorManager.SENSOR_DELAY_NORMAL);
    }

    private final void unRegister() {
        manager.unregisterListener(this);
        x = 0;
        y = 0;
        z = 0;
    }
}



圖片來源:
http://www.sogi.com.tw/product/productinfo.aspx?pno=8172