回 Android手機程式設計人才培訓班 課程時間表

感測器

簡介

Android系統內建將近二十種感測器,利用這些感測器我們可以製作出各種有趣的應用程式和遊戲。

感測器類型有:

  1. TYPE_ACCELEROMETER:加速度感測器(Accelerometer)
  2. TYPE_AMBIENT_TEMPERATURE:溫度感測器(Temperature)
  3. TYPE_GAME_ROTATION_VECTOR:A constant describing an uncalibrated rotation vector sensor type.
  4. TYPE_GEOMAGNETIC_ROTATION_VECTOR:A constant describing a geo-magnetic rotation vector.
  5. TYPE_GRAVITY:重力感測器(Gravity)
  6. TYPE_GYROSCOPE:陀螺儀(Gyroscope)
  7. TYPE_GYROSCOPE_UNCALIBRATED:A constant describing an uncalibrated gyroscope sensor type.
  8. TYPE_HEART_RATE:A constant describing a heart rate monitor.
  9. TYPE_LIGHT:環境光照感測器(Light)
  10. TYPE_LINEAR_ACCELERATION:A constant describing a linear acceleration sensor type.
  11. TYPE_MAGNETIC_FIELD:磁力感測器(Magnetic Field)
  12. TYPE_MAGNETIC_FIELD_UNCALIBRATED:A constant describing an uncalibrated magnetic field sensor type.
  13. TYPE_ORIENTATION:方向感測器(Orientation)
  14. TYPE_PRESSURE:壓力感測器(Pressure)
  15. TYPE_PROXIMITY:距離感測器(Proximity)
  16. TYPE_RELATIVE_HUMIDITY:A constant describing a relative humidity sensor type.
  17. TYPE_ROTATION_VECTOR:A constant describing a rotation vector sensor type.
  18. TYPE_SIGNIFICANT_MOTION:A constant describing a significant motion trigger sensor.
  19. TYPE_STEP_COUNTER:A constant describing a step counter sensor.
  20. TYPE_STEP_DETECTOR:A constant describing a step detector sensor.
  21. TYPE_TEMPERATURE:溫度感測器。API Level 14以後請使用TYPE_AMBIENT_TEMPERATURE代替。

提醒:
  • 並非所有Android裝置都會支援全部感測器類型。
  • 模擬器中無法使用感測器。


取得Android裝置所有感測器資訊

java/res/layout/activity_main.xml中加入:
<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

        <TextView android:id="@+id/txtView"
            android:text="@string/hello_world" android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
</ScrollView>
java/src/{package}/MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    TextView txtView = (TextView)findViewById(R.id.txtView);

    // 從系統服務中獲得感測器管理器
    SensorManager sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);

    // 從感測器管理器中獲得全部的感測器列表
    List<Sensor> allSensors = sm.getSensorList(Sensor.TYPE_ALL);

    // 顯示有多少個感測器
    txtView.setText("該手機有" + allSensors.size() + "種感測器,分別為:\n");

    //
    // 顯示每個感測器的詳細資訊
    // 1. getType(): 感測器類型代碼
    // 2. getName(): 設備名稱
    // 3. getVersion(): 設備版號
    // 4. getVendor(): 供應商
    //
    for(Sensor s : allSensors)
    {
        String str = txtView.getText() + "\n\n感測器類型:";

        switch(s.getType())
        {
        case Sensor.TYPE_ACCELEROMETER: str += "TYPE_ACCELEROMETER(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_AMBIENT_TEMPERATURE: str += "TYPE_AMBIENT_TEMPERATURE(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_GAME_ROTATION_VECTOR: str += "TYPE_GAME_ROTATION_VECTOR(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR: str += "TYPE_GEOMAGNETIC_ROTATION_VECTOR(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_GRAVITY: str += "TYPE_GRAVITY(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_GYROSCOPE: str += "TYPE_GYROSCOPE(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_GYROSCOPE_UNCALIBRATED: str += "TYPE_GYROSCOPE_UNCALIBRATED(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_HEART_RATE: str += "TYPE_HEART_RATE(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_LIGHT: str += "TYPE_LIGHT(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_LINEAR_ACCELERATION: str += "TYPE_LINEAR_ACCELERATION(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_MAGNETIC_FIELD: str += "TYPE_MAGNETIC_FIELD(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED: str += "TYPE_MAGNETIC_FIELD_UNCALIBRATED(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_ORIENTATION: str += "TYPE_ORIENTATION(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_PRESSURE: str += "TYPE_PRESSURE(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_PROXIMITY: str += "TYPE_PROXIMITY(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_RELATIVE_HUMIDITY: str += "TYPE_RELATIVE_HUMIDITY(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_ROTATION_VECTOR: str += "TYPE_ROTATION_VECTOR(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_SIGNIFICANT_MOTION: str += "TYPE_SIGNIFICANT_MOTION(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_STEP_COUNTER: str += "TYPE_STEP_COUNTER(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_STEP_DETECTOR: str += "TYPE_STEP_DETECTOR(" + s.getType() + ")\n"; break;
        case Sensor.TYPE_TEMPERATURE: str += "TYPE_TEMPERATURE(" + s.getType() + ")\n"; break;
        default:
        str += "未知的類型(" + s.getType() + ")\n"; break;
        }

        str += "設備名稱:" + s.getName() + "\n" +
        "設備版本:" + s.getVersion() + "\n" +
        "供應商:" + s.getVendor() + "\n";

        txtView.setText(str);
    }
}
為避免資訊過長而超出螢幕範圍,XML版面設計中建議使用ScrollView標籤包圍TextView標籤。

方向感測器使用範例

  • Z軸(values[0]):方位角(azimuth)。
  • X軸(values[1]):投擲角(pitch)。
  • Y軸(values[2]):滾動角(roll)。


版面XML使用TextView:
<TextView android:id="@+id/txtInfo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
程式碼:
public class MainActivity extends ActionBarActivity
{
    TextView txtInfo;
    SensorManager sensorMgr;
    float[] accelerometer_values;
    float[] magnitude_values;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        txtInfo = (TextView)findViewById(R.id.txtInfo);

        // 取得SensorManager物件
        sensorMgr = (SensorManager)getSystemService(SENSOR_SERVICE);
    }

    // 感應器傾聽器
    SensorEventListener listener = new SensorEventListener() 
    {
        public void onSensorChanged(SensorEvent event) 
        {
            switch (event.sensor.getType()) 
            {
                case Sensor.TYPE_ACCELEROMETER:
                    accelerometer_values = (float[]) event.values.clone();
                    break;
                case Sensor.TYPE_MAGNETIC_FIELD:
                    magnitude_values = (float[]) event.values.clone();
                    break;
            }

            if(magnitude_values != null && accelerometer_values != null)
            {
                float[] R = new float[9];
                float[] values = new float[3];
                
                SensorManager.getRotationMatrix(R, null, accelerometer_values, magnitude_values);
                SensorManager.getOrientation(R, values);

                StringBuilder sensorInfo = new StringBuilder();

                for (int i = 0; i < values.length; i++)
                    sensorInfo.append("-values[" + i + "] = " + values[i] + "\n");
                
                txtInfo.setText(sensorInfo);
            }
        }

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

    // 
    @Override
    protected void onResume()
    {
        super.onResume();

        // 註冊感應器
        if(!(sensorMgr.registerListener(listener, sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI) &&
        sensorMgr.registerListener(listener, sensorMgr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI)))
        {
            Log.w("OrientationEx", "sensor not found!");
            sensorMgr.unregisterListener(listener);
        }
    }

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

        // 取消註冊感應器
        sensorMgr.unregisterListener(listener);
    }

}
執行畫面