官术网_书友最值得收藏!

第6章 Android傳感器系統概覽

在Android系統中提供的主要傳感器有加速度、磁場、方向、陀螺儀、光線、壓力、溫度和接近等傳感器。傳感器系統會主動對上層報告傳感器精度和數據的變化,并且提供了設置傳感器精度的接口,這些接口可以在Java應用和Java框架中使用。本章將詳細講解在Android系統中使用傳感器技術開發智能設備應用程序的基本流程,為讀者步入本書后面知識的學習打下堅實的基礎。

6.1 Android設備的傳感器系統

本書在前面第5章中,已經詳細講解了Android傳感器系統的基本架構。本節將詳細講解調用傳感器API接口,在Android智能設備中開發應用程序的方法。

6.1.1 包含的傳感器

在安裝Android SDK后,依次打開安裝目錄中下面的幫助文件。

      android SDK/sdk/docs/reference/android/hardware/Sensor.html

在此文件中列出了Android傳感器系統所包含的所有傳感器類型,如圖6-1所示。

▲圖6-1 Android傳感器系統的類型

另外,也可以直接在線登錄http://developer.android.com/reference/android/hardware/Sensor.html來查看。由此可見,在當前最新(作者寫稿時最新)版本Android 4.4中一共提供了18種傳感器API接口。各個類型的具體說明如下所示。

(1)TYPE_ACCELEROMETER:加速度傳感器,單位是m/s2,測量應用于設備x、y、z軸上的加速度,又叫作G-sensor。

(2)TYPE_AMBIENT_TEMPERATURE:溫度傳感器,單位是℃,能夠測量并返回當前的溫度。

(3)TYPE_GRAVITY:重力傳感器,單位是m/s2,用于測量設備x、y、z軸上的重力,也叫作GV-sensor,地球上的數值是9.8 m/s2

(4)TYPE_GYROSCOPE:陀螺儀傳感器,單位是rad/s2,能夠測量設備x、y、z三軸的角加速度數據。

(5)TYPE_LIGHT:光線感應傳感器,單位是lx,能夠檢測周圍的光線強度,在手機系統中主要用于調節LCD亮度。

(6)TYPE_LINEAR_ACCELERATION:線性加速度傳感器,單位是m/s2,能夠獲取加速度傳感器去除重力的影響得到的數據。

(7)TYPE_MAGNETIC_FIELD:磁場傳感器,單位是μT(微特斯拉),能夠測量設備周圍3個物理軸(x, y, z)的磁場。

(8)TYPE_ORIENTATION:方向傳感器,用于測量設備圍繞3個物理軸(x, y, z)的旋轉角度,在新版本中已經使用SensorManager.getOrientation()替代。

(9)TYPE_PRESSURE:氣壓傳感器,單位是hPa(百帕斯卡),能夠返回當前環境下的壓強。

(10)TYPE_PROXIMITY:距離傳感器,單位是cm,能夠測量某個對象到屏幕的距離。可以在打電話時判斷人耳到電話屏幕距離,以關閉屏幕而達到省電功能。

(11)TYPE_RELATIVE_HUMIDITY:濕度傳感器,能夠測量周圍環境的相對濕度。

(12)TYPE_ROTATION_VECTOR:旋轉向量傳感器,旋轉矢量代表設備的方向,是一個將坐標軸和角度混合計算得到的數據。

(13)TYPE_TEMPERATURE:溫度傳感器,在新版本中被TYPE_AMBIENT_TEMPERATURE替換。

(14)TYPE_ALL:返回所有的傳感器類型。

(15)TYPE_GAME_ROTATION_VECTOR:除了不能使用地磁場之外,和TYPE_ROTATION_VECTOR的功能完全相同。

(16)TYPE_GYROSCOPE_UNCALIBRATED:提供了能夠讓應用調整傳感器的原始值,定義了一個描述未校準陀螺儀的傳感器類型。

(17)TYPE_MAGNETIC_FIELD_UNCALIBRATED:和TYPE_GYROSCOPE_UNCALIBRATED相似,也提供了能夠讓應用調整傳感器的原始值,定義了一個描述未校準陀螺儀的傳感器類型。

(18)TYPE_SIGNIFICANT_MOTION:運動觸發傳感器,應用程序不需要為這種傳感器觸發任何喚醒鎖。能夠檢測當前設備是否運動,并發送檢測結果。

6.1.2 檢測當前設備支持的傳感器

在接下來的實例中,將演示在Android設備中檢測當前設備支持傳感器類型的方法。本實例的功能是檢測當前設備支持的傳感器類型,具體實現流程如下所示。

布局文件main.xml的具體實現代碼如下所示。

      <linearlayout android:layout_height="fill_parent" android:layout_width="fill_parent"
      android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
      <textview android:layout_height="wrap_content"
       android:layout_width="fill_parent" android:text=""
       android:id="@+id/TextView01"
      >
      </textview>
      </linearlayout>

主程序文件MainActivity.java的具體實現代碼如下所示。

      public class MainActivity extends Activity {

    /** Called when the activity is first created. */
    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            //準備顯示信息的UI組建
            final TextView tx1 = (TextView) findViewById(R.id.TextView01);

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

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

            //顯示有多少個傳感器
          tx1.setText("經檢測該手機有" + allSensors.size() + "個傳感器,它們分別是:\n");

            //顯示每個傳感器的具體信息
            for (Sensor s : allSensors) {

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

                  switch (s.getType()) {
                  case Sensor.TYPE_ACCELEROMETER:
                        tx1.setText(tx1.getText().toString() + s.getType() + " 加速
                          度傳感器accelerometer" + tempString);
                          break;
                  case Sensor.TYPE_GYROSCOPE:
                        tx1.setText(tx1.getText().toString() + s.getType() + " 陀螺
                          儀傳感器gyroscope" + tempString);
                          break;
                  case Sensor.TYPE_LIGHT:
                        tx1.setText(tx1.getText().toString() + s.getType() + " 光線
                          感應傳感器light" + tempString);
                          break;
                  case Sensor.TYPE_MAGNETIC_FIELD:
                        tx1.setText(tx1.getText().toString() + s.getType() + " 電磁
                          場傳感器magnetic field" + tempString);
                          break;
                  case Sensor.TYPE_ORIENTATION:
                        tx1.setText(tx1.getText().toString() + s.getType() + " 方向
                          傳感器orientation" + tempString);
                          break;
                  case Sensor.TYPE_PRESSURE:
                        tx1.setText(tx1.getText().toString() + s.getType() + " 壓力
                          傳感器pressure" + tempString);
                          break;
                  case Sensor.TYPE_PROXIMITY:
                        tx1.setText(tx1.getText().toString() + s.getType() + " 距離
                          傳感器proximity" + tempString);
                          break;
                  case Sensor.TYPE_AMBIENT_TEMPERATURE :
                        tx1.setText(tx1.getText().toString() + s.getType() + " 溫度
                          傳感器temperature" + tempString);
                          break;
                  default:
                        tx1.setText(tx1.getText().toString() + s.getType() + " 未知
                          傳感器" + tempString);
                          break;
                  }
            }
    }
}

上述實例代碼需要在真機中運行,執行后將會列表顯示當前設備所支持的傳感器類型。如圖6-2所示。

▲圖6-2 執行效果

6.2 使用SensorSimulator

在進行和傳感器相關的開發工作時,使用SensorSimulator可以提高開發效率。SensorSimulator是一個開源免費的傳感器小型工具,通過該工具可以在模擬器中調試傳感器的應用。搭建SensorSimulator開發環境的基本流程如下所示。

(1)下載SensorSimulator,讀者可從http://code.google.com/p/openintents/wiki/SensorSimulator網站找到該工具的下載鏈接。這里下載的是sensorsimulator-1.1.1.zip版本,如圖6-3所示。

▲圖6-3 下載sensorsimulator-1.1.1.zip

(2)將下載好的SensorSimulator解壓到本地根目錄,例如C盤的根目錄。

(3)向模擬器安裝SensorSimulatorSettings-1.1.1.apk。首先在操作系統中依次選擇“開始”|“運行”,進入“運行”對話框。

(4)在“運行”對話框輸入“cmd”進入cmd命令行,之后通過cd命令將當前目錄導航到SensorSimulatorSettings-1.1.1.apk目錄下,然后輸入下列命令向模擬器安裝該apk。

        adb install SensorSimulatorSettings-1.1.1.apk

如圖6-4所示。在此需要注意的是,安裝apk時,一定要保證模擬器正在運行才可以,安裝成功后會輸出“Success”提示。

▲圖6-4 安裝apk

接下來開始配置應用程序,假設要在項目“jiaSCH”中使用SensorSimulator,則配置流程如下所示。

(1)在Eclipse中打開項目“jiaSCH”,然后為該項目添加JAR包,使其能夠使用SensorSimulator工具的類和方法。添加方法非常簡單,在Eclipse的Package Explorer中找到該項目的文件夾“jiaSCH”,然后右鍵單擊該文件夾并選擇“Properties”選項,彈出圖6-5所示的“Properties for jiaS”窗口。

▲圖6-5 “Properties for jiaS”窗口

(2)選擇左面的“Java Build Path”選項,然后單擊“Libraries”選項卡,如圖6-6所示。

▲圖6-6 “Libraries”選項卡

(3)單擊“Add External JARs”按鈕,在彈出的“JAR Selection”對話框中找到Sensorsimulator安裝目錄下的sensorsimulator-lib-1.1.1.jar,并將其添加到該項目中,如圖6-7所示。

▲圖6-7 添加需要的JAR包

(4)開始啟動sensorsimulator.jar,并對手機模擬器上的SensorSimulator進行必要的配置。首先在“C:\sensorsimulator-1.1.1\bin”目錄下找到sensorsimulator.jar并啟動,運行后的界面如圖6-8所示。

▲圖6-8 傳感器的模擬器

(5)接下來開始進行手機模擬器和SensorSimulator的連接配置工作,運行手機模擬器上安裝好的SensorSimulatorSettings.apk,如圖6-9所示。

▲圖6-9 運行手機模擬器上的SensorSimulatorSettings-1.1.1.apk

(6)在圖6-9中輸入SensorSimulator啟動時顯示的IP地址和端口號,單擊屏幕右上角的“Testing”按鈕后轉到測試連接界面。如圖6-10所示。

▲圖6-10 測試連接界面

(7)單擊屏幕上的“Connect”按鈕進入下一界面,如圖6-11所示。在此界面中可以選擇需要監聽的傳感器,如果能夠從傳感器中讀取到數據,說明SensorSimulator與手機模擬器連接成功,就可以測試自己開發的應用程序了。

▲圖6-11 連接界面

到此為止,使用Eclipse結合SensorSimulator配置傳感器應用程序的基本流程介紹完畢。

6.3 查看傳感器的相關信息

在接下來的實例中,將演示在Android智能設備中查看傳感器數據的方法。

本實例的功能是查看設備中傳感器的基本信息,本實例源碼來源于:

      https://github.com/gast-lib/gast-lib

讀者可以自行登錄下載。本實例的具體實現流程如下所示。

(1)編寫用戶交互界面SensorListActivity,實現了兩個用戶界面交互。其中主界面sensor_main.xml用于列表顯示系統中的傳感器,功能和前面的實例6-1類似。文件sensor_main.xml的主要實現代碼如下所示。

      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
          <fragment
              android:id="@+id/frag_sensor_select"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              class="root.gast.playground.sensor.SensorSelectorFragment" />

          <fragment
              android:id="@+id/frag_sensor_view"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              class="root.gast.playground.sensor.SensorDisplayFragment" />
      </LinearLayout>

文件SensorListActivity.java的具體實現代碼如下所示。

      public class SensorListActivity extends FragmentActivity
      {
          @Override
          protected void onCreate(Bundle savedInstanceState)
          {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.sensor_main);

              // wire up the fragments so selector
              // can call display
              SensorDisplayFragment sensorDisplay =
                    (SensorDisplayFragment) getSupportFragmentManager()
                            .findFragmentById(R.id.frag_sensor_view);
              SensorSelectorFragment sensorSelect =
                    (SensorSelectorFragment) getSupportFragmentManager()
                            .findFragmentById(R.id.frag_sensor_select);
              sensorSelect.setSensorDisplay(sensorDisplay);
          }
      }

通過上述代碼可知,傳感器類型列表顯示功能是通過調用文件SensorSelectorFragment.java實現的,具體實現代碼如下所示。

      public class SensorSelectorFragment extends ListFragment
      {
          private static final String TAG = "SensorSelectorFragment";

          private SensorDisplayFragment sensorDisplay;

          /**

          * connect with a display fragment to call later when user clicks a sensor
          * name, also setup the ListAdapter to show all the Sensors
          */
          public void setSensorDisplay(SensorDisplayFragment sensorDisplay)
          {
              this.sensorDisplay = sensorDisplay;

              SensorManager sensorManager =
                    (SensorManager) getActivity().getSystemService(
                            Activity.SENSOR_SERVICE);

              List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
              this.setListAdapter(new SensorListAdapter(getActivity()
                      .getApplicationContext(), android.R.layout.simple_list_item_1,
                      sensors));
          }

          /**
          * hide the list of sensors and show the sensor display fragment
          * add these changes to the backstack
          */
          private void showSensorFragment(Sensor sensor)
          {
              sensorDisplay.displaySensor(sensor);
              FragmentTransaction ft =
                      getActivity().getSupportFragmentManager().beginTransaction();
              ft.hide(this);
              ft.show(sensorDisplay);
              ft.addToBackStack("Showing sensor: " + sensor.getName());
              ft.commit();
          }

          /**
          * list view adapter to show sensor names and respond to clicks.
          */
          private class SensorListAdapter extends ArrayAdapter<Sensor>
          {
              public SensorListAdapter(Context context, int textViewResourceId,
                      List<Sensor> sensors)
              {
                  super(context, textViewResourceId, sensors);
              }

              /**
               * create a text view containing the sensor name
               */
              @Override
              public View getView(final int position, View convertView,
                      ViewGroup parent)
              {
                  final Sensor selectedSensor = getItem(position);
                  if (convertView == null)
                  {
                      convertView =
                            LayoutInflater.from(getContext()).inflate(
                                    android.R.layout.simple_list_item_1, null);
                  }

                  ((TextView) convertView).setText(selectedSensor.getName());

                  convertView.setOnClickListener(new View.OnClickListener()
                  {
                      @Override
                      public void onClick(View v)
                      {
                        if (BuildConfig.DEBUG)
                        {
                            Log.d(TAG,
                                    "display sensor! " + selectedSensor.getName());
                        }

                        showSensorFragment(selectedSensor);
                      }
                  });
                  return convertView;
              }
          }
      }

(2)再看第2個界面,當用戶在主界面選擇列表中的某一個傳感器時,會顯示這個傳感器的詳細信息。界面文件sensors_north_main.xml的主要實現代碼如下所示。

    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <RadioGroup android:id="@+id/sensorRateSelector"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_alignParentTop="true" >

              <RadioButton android:id="@+id/delayFastest"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="SENSOR_DELAY_FASTEST"
                  android:checked="false"/>

              <RadioButton android:id="@+id/delayGame"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="SENSOR_DELAY_GAME"
                  android:checked="false"/>

              <RadioButton android:id="@+id/delayNormal"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="SENSOR_DELAY_NORMAL"
                  android:checked="true"/>

              <RadioButton android:id="@+id/delayUi"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="SENSOR_DELAY_UI"
                  android:checked="false"/>
            </RadioGroup>

            <View android:id="@+id/seperator"
              style="@style/line_separator"
              android:layout_below="@id/sensorRateSelector" />

            <TextView android:id="@+id/nameLabel"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_below="@id/seperator"
              android:layout_alignParentLeft="true"
              android:text="Name:"
              android:layout_marginRight="5dip" />

            <TextView android:id="@+id/name"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_toRightOf="@id/nameLabel"
              android:layout_alignTop="@id/nameLabel"
              android:layout_alignBottom="@id/nameLabel" />

            <TextView android:id="@+id/typeLabel"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_alignLeft="@id/nameLabel"
              android:layout_below="@id/nameLabel"
              android:text="Type:"
              android:layout_marginRight="5dip" />

            <TextView android:id="@+id/type"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"

    android:layout_toRightOf="@id/typeLabel"
    android:layout_alignTop="@id/typeLabel"
    android:layout_alignBottom="@id/typeLabel"/>

<TextView android:id="@+id/maxRangeLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/nameLabel"
    android:layout_below="@id/typeLabel"
    android:text="Max Range:"
    android:layout_marginRight="5dip" />

<TextView android:id="@+id/maxRange"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/maxRangeLabel"
    android:layout_alignTop="@id/maxRangeLabel"
    android:layout_alignBottom="@id/maxRangeLabel"/>

<TextView android:id="@+id/minDelayLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/maxRangeLabel"
    android:layout_below="@id/maxRangeLabel"
    android:text="Min Delay:"
    android:layout_marginRight="5dip" />

<TextView android:id="@+id/minDelay"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/minDelayLabel"
    android:layout_alignTop="@id/minDelayLabel"
    android:layout_alignBottom="@id/minDelayLabel"/>

<TextView android:id="@+id/powerLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/minDelayLabel"
    android:layout_below="@id/minDelayLabel"
    android:text="Power:"
    android:layout_marginRight="5dip" />

<TextView android:id="@+id/power"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/powerLabel"
    android:layout_alignTop="@id/powerLabel"
    android:layout_alignBottom="@id/powerLabel"
    android:layout_marginRight="5dip"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/power"
    android:layout_alignTop="@id/power"
    android:layout_alignBottom="@id/power"
    android:text="mA"/>

<TextView android:id="@+id/resolutionLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/powerLabel"
    android:layout_below="@id/powerLabel"
    android:text="Resolution:"
    android:layout_marginRight="5dip" />

<TextView android:id="@+id/resolution"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"

    android:layout_toRightOf="@id/resolutionLabel"
    android:layout_alignTop="@id/resolutionLabel"
    android:layout_alignBottom="@id/resolutionLabel"/>

<TextView android:id="@+id/vendorLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/resolutionLabel"
    android:layout_below="@id/resolutionLabel"
    android:text="Vendor:"
    android:layout_marginRight="5dip" />

<TextView android:id="@+id/vendor"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/vendorLabel"
    android:layout_alignTop="@id/vendorLabel"
    android:layout_alignBottom="@id/vendorLabel"/>

<TextView android:id="@+id/versionLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/versionLabel"
    android:layout_alignLeft="@id/vendorLabel"
    android:layout_below="@id/vendorLabel"
    android:text="Version:"
    android:layout_marginRight="5dip" />

<TextView android:id="@+id/version"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/versionLabel"
    android:layout_alignTop="@id/versionLabel"
    android:layout_alignBottom="@id/versionLabel"/>

<TextView android:id="@+id/accuracyLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/versionLabel"
    android:layout_below="@id/versionLabel"
    android:text="Accuracy:"
    android:layout_marginRight="5dip" />

<TextView android:id="@+id/accuracy"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/accuracyLabel"
    android:layout_alignTop="@id/accuracyLabel"
    android:layout_alignBottom="@id/accuracyLabel"/>

<! -- timestamp -->
<TextView android:id="@+id/timestampLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/accuracyLabel"
    android:layout_below="@id/accuracyLabel"
    android:layout_marginRight="5dip"
    android:text="Timestamp:" />

<TextView android:id="@+id/timestamp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/timestampLabel"
    android:layout_alignTop="@id/timestampLabel"
    android:layout_alignBottom="@id/timestampLabel"
    android:layout_marginRight="5dip"
    android:visibility="gone" />

<TextView android:id="@+id/timestampUnits"

    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/timestamp"
    android:layout_alignTop="@id/timestamp"
    android:layout_alignBottom="@id/timestamp"
    android:visibility="gone"
    android:text="(ns)" />

<TextView android:id="@+id/dataLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/accuracyLabel"
    android:layout_below="@id/timestampLabel"
    android:layout_marginRight="5dip"
    android:visibility="gone"/>

<TextView android:id="@+id/dataUnits"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/dataLabel"
    android:layout_alignTop="@id/dataLabel"
    android:layout_alignBottom="@id/dataLabel"
    android:visibility="gone" />

<TextView android:id="@+id/singleValue"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/dataUnits"
    android:layout_alignTop="@id/dataUnits"
    android:layout_alignBottom="@id/dataUnits"
    android:visibility="gone" />

<! -- X axis -->
<TextView android:id="@+id/xAxisLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/dataLabel"
    android:layout_below="@id/dataLabel"
    android:layout_marginRight="5dip"
    android:visibility="gone"
    android:text="@string/xAxisLabel" />

<TextView android:id="@+id/xAxis"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/xAxisLabel"
    android:layout_alignTop="@id/xAxisLabel"
    android:layout_alignBottom="@id/xAxisLabel"
    android:layout_marginRight="5dip"
    android:visibility="gone" />

<! -- Y axis -->
<TextView android:id="@+id/yAxisLabel"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/xAxisLabel"
    android:layout_below="@id/xAxisLabel"
    android:layout_marginRight="5dip"
    android:visibility="gone"
    android:text="@string/yAxisLabel" />

<TextView android:id="@+id/yAxis"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/yAxisLabel"
    android:layout_alignTop="@id/yAxisLabel"
    android:layout_alignBottom="@id/yAxisLabel"
    android:layout_marginRight="5dip"
    android:visibility="gone" />

          <! -- Z axis -->
          <TextView android:id="@+id/zAxisLabel"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_alignLeft="@id/yAxisLabel"
              android:layout_below="@id/yAxisLabel"
              android:layout_marginRight="5dip"
              android:visibility="gone"
              android:text="@string/zAxisLabel" />

          <TextView android:id="@+id/zAxis"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_toRightOf="@id/zAxisLabel"
              android:layout_alignTop="@id/zAxisLabel"
              android:layout_alignBottom="@id/zAxisLabel"
              android:layout_marginRight="5dip"
              android:visibility="gone" />

          <! -- cos value (for rotation vector only) -->
          <TextView android:id="@+id/cosLabel"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_alignLeft="@id/zAxisLabel"
              android:layout_below="@id/zAxisLabel"
              android:layout_marginRight="5dip"
              android:visibility="gone"
              android:text="cos(\u0398/2):" />

          <TextView android:id="@+id/cos"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_toRightOf="@id/cosLabel"
              android:layout_alignTop="@id/cosLabel"
              android:layout_alignBottom="@id/cosLabel"
              android:layout_marginRight="5dip"
              android:visibility="gone" />
      </RelativeLayout>

某個傳感器的詳細信息功能是通過文件SensorDisplayFragment.java實現的,主要代碼如下所示。

  public class SensorDisplayFragment extends Fragment implements SensorEventListener
  {
      private static final String TAG = "SensorDisplayFragment";
      private static final String THETA = "\u0398";
      private static final String ACCELERATION_UNITS = "m/s\u00B2";

      private SensorManager sensorManager;
      private Sensor sensor;
      private TextView name;
      private TextView type;
      private TextView maxRange;
      private TextView minDelay;
      private TextView power;
      private TextView resolution;
      private TextView vendor;
      private TextView version;
      private TextView accuracy;
      private TextView timestampLabel;
      private TextView timestamp;
      private TextView timestampUnits;
      private TextView dataLabel;
      private TextView dataUnits;
      private TextView xAxis;
      private TextView xAxisLabel;
      private TextView yAxis;
      private TextView yAxisLabel;
      private TextView zAxis;
      private TextView zAxisLabel;

    private TextView singleValue;
    private TextView cosLabel;
    private TextView cos;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState)
    {
        View layout = inflater.inflate(R.layout.sensor_view, null);

        sensorManager =
              (SensorManager) getActivity().getSystemService(Context.SENSOR_SERVICE);

        name = (TextView) layout.findViewById(R.id.name);
        type = (TextView) layout.findViewById(R.id.type);
        maxRange = (TextView) layout.findViewById(R.id.maxRange);
        minDelay = (TextView) layout.findViewById(R.id.minDelay);
        power = (TextView) layout.findViewById(R.id.power);
        resolution = (TextView) layout.findViewById(R.id.resolution);
        vendor = (TextView) layout.findViewById(R.id.vendor);
        version = (TextView) layout.findViewById(R.id.version);
        accuracy = (TextView) layout.findViewById(R.id.accuracy);
        timestampLabel = (TextView) layout.findViewById(R.id.timestampLabel);
        timestamp = (TextView) layout.findViewById(R.id.timestamp);
        timestampUnits = (TextView) layout.findViewById(R.id.timestampUnits);
        dataLabel = (TextView) layout.findViewById(R.id.dataLabel);
        dataUnits = (TextView) layout.findViewById(R.id.dataUnits);
        xAxis = (TextView) layout.findViewById(R.id.xAxis);
        xAxisLabel = (TextView) layout.findViewById(R.id.xAxisLabel);
        yAxis = (TextView) layout.findViewById(R.id.yAxis);
        yAxisLabel = (TextView) layout.findViewById(R.id.yAxisLabel);
        zAxis = (TextView) layout.findViewById(R.id.zAxis);
        zAxisLabel = (TextView) layout.findViewById(R.id.zAxisLabel);
        singleValue = (TextView) layout.findViewById(R.id.singleValue);
        cosLabel = (TextView) layout.findViewById(R.id.cosLabel);
        cos = (TextView) layout.findViewById(R.id.cos);

        layout.findViewById(R.id.delayFastest).setOnClickListener(new
OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
              sensorManager.unregisterListener(SensorDisplayFragment.this);
              sensorManager.registerListener(SensorDisplayFragment.this,
                      sensor,
                      SensorManager.SENSOR_DELAY_FASTEST);
            }
        });

        layout.findViewById(R.id.delayGame).setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
              sensorManager.unregisterListener(SensorDisplayFragment.this);
              sensorManager.registerListener(SensorDisplayFragment.this,
                      sensor,
                      SensorManager.SENSOR_DELAY_GAME);
            }
        });

        layout.findViewById(R.id.delayNormal).setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
              sensorManager.unregisterListener(SensorDisplayFragment.this);
              sensorManager.registerListener(SensorDisplayFragment.this,

    sensor,
    SensorManager.SENSOR_DELAY_NORMAL);
}
});

layout.findViewById(R.id.delayUi).setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
sensorManager.unregisterListener(SensorDisplayFragment.this);
sensorManager.registerListener(SensorDisplayFragment.this,
    sensor,
    SensorManager.SENSOR_DELAY_UI);
}
});
return layout;
}

public void displaySensor(Sensor sensor)
{
if (BuildConfig.DEBUG)
{
Log.d(TAG, "display the sensor");
}

this.sensor = sensor;

name.setText(sensor.getName());
type.setText(String.valueOf(sensor.getType()));
maxRange.setText(String.valueOf(sensor.getMaximumRange()));
minDelay.setText(String.valueOf(sensor.getMinDelay()));
power.setText(String.valueOf(sensor.getPower()));
resolution.setText(String.valueOf(sensor.getResolution()));
vendor.setText(String.valueOf(sensor.getVendor()));
version.setText(String.valueOf(sensor.getVersion()));

sensorManager.registerListener(this,
sensor,
SensorManager.SENSOR_DELAY_NORMAL);
}

/**
*  @see  android.hardware.SensorEventListener#onAccuracyChanged(android.hardware.
Sensor, int)
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
switch(accuracy)
{
case SensorManager.SENSOR_STATUS_ACCURACY_HIGH:
this.accuracy.setText("SENSOR_STATUS_ACCURACY_HIGH");
break;
case SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM:
this.accuracy.setText("SENSOR_STATUS_ACCURACY_MEDIUM");
break;
case SensorManager.SENSOR_STATUS_ACCURACY_LOW:
this.accuracy.setText("SENSOR_STATUS_ACCURACY_LOW");
break;
case SensorManager.SENSOR_STATUS_UNRELIABLE:
this.accuracy.setText("SENSOR_STATUS_UNRELIABLE");
break;
}
}

/**
*   @see   android.hardware.SensorEventListener#onSensorChanged(android.hardware.

    SensorEvent)
        */
        @Override
        public void onSensorChanged(SensorEvent event)
        {
            onAccuracyChanged(event.sensor, event.accuracy);

            timestampLabel.setVisibility(View.VISIBLE);
            timestamp.setVisibility(View.VISIBLE);
            timestamp.setText(String.valueOf(event.timestamp));
            timestampUnits.setVisibility(View.VISIBLE);

            switch (event.sensor.getType())
            {
              case Sensor.TYPE_ACCELEROMETER:
                  showEventData("Acceleration - gravity on axis",
                          ACCELERATION_UNITS,
                          event.values[0],
                          event.values[1],
                          event.values[2]);
                  break;

              case Sensor.TYPE_MAGNETIC_FIELD:
                  showEventData("Abient Magnetic Field",
                          "uT",
                          event.values[0],
                          event.values[1],
                          event.values[2]);
                  break;
              case Sensor.TYPE_GYROSCOPE:
                  showEventData("Angular speed around axis",
                          "radians/sec",
                          event.values[0],
                          event.values[1],
                          event.values[2]);
                  break;
              case Sensor.TYPE_LIGHT:
                  showEventData("Ambient light",
                          "lux",
                          event.values[0]);
                  break;
              case Sensor.TYPE_PRESSURE:
                  showEventData("Atmospheric pressure",
                          "hPa",
                          event.values[0]);
                  break;
              case Sensor.TYPE_PROXIMITY:
                  showEventData("Distance",
                          "cm",
                          event.values[0]);
                  break;
              case Sensor.TYPE_GRAVITY:
                  showEventData("Gravity",
                          ACCELERATION_UNITS,
                          event.values[0],
                          event.values[1],
                          event.values[2]);
                  break;
              case Sensor.TYPE_LINEAR_ACCELERATION:
                  showEventData("Acceleration (not including gravity)",
                          ACCELERATION_UNITS,
                          event.values[0],
                          event.values[1],
                          event.values[2]);
                  break;
              case Sensor.TYPE_ROTATION_VECTOR:

                  showEventData("Rotation Vector",
                          null,

    event.values[0],
    event.values[1],
    event.values[2]);

xAxisLabel.setText("x*sin(" + THETA + "/2)");
yAxisLabel.setText("y*sin(" + THETA + "/2)");
zAxisLabel.setText("z*sin(" + THETA + "/2)");

if (event.values.length == 4)
{
cosLabel.setVisibility(View.VISIBLE);
cos.setVisibility(View.VISIBLE);
cos.setText(String.valueOf(event.values[3]));
}

break;
case Sensor.TYPE_ORIENTATION:
showEventData("Angle",
    "Degrees",
    event.values[0],
    event.values[1],
    event.values[2]);

xAxisLabel.setText(R.string.azimuthLabel);
yAxisLabel.setText(R.string.pitchLabel);
zAxisLabel.setText(R.string.rollLabel);

break;
case Sensor.TYPE_RELATIVE_HUMIDITY:
showEventData("Relatice ambient air humidity",
    "%",
    event.values[0]);
break;
case Sensor.TYPE_AMBIENT_TEMPERATURE:
showEventData("Ambien temperature",
    "degree Celcius",
    event.values[0]);
break;
}
}

private void showEventData(String label, String units, float x, float y, float z)
{
dataLabel.setVisibility(View.VISIBLE);
dataLabel.setText(label);

if (units == null)
{
dataUnits.setVisibility(View.GONE);
}
else
{
dataUnits.setVisibility(View.VISIBLE);
dataUnits.setText("(" + units + "):");
}

singleValue.setVisibility(View.GONE);

xAxisLabel.setVisibility(View.VISIBLE);
xAxisLabel.setText(R.string.xAxisLabel);
xAxis.setVisibility(View.VISIBLE);
xAxis.setText(String.valueOf(x));

yAxisLabel.setVisibility(View.VISIBLE);
yAxisLabel.setText(R.string.yAxisLabel);
yAxis.setVisibility(View.VISIBLE);
yAxis.setText(String.valueOf(y));

zAxisLabel.setVisibility(View.VISIBLE);

        zAxisLabel.setText(R.string.zAxisLabel);
        zAxis.setVisibility(View.VISIBLE);
        zAxis.setText(String.valueOf(z));
    }

    private void showEventData(String label, String units, float value)
    {
        dataLabel.setVisibility(View.VISIBLE);
        dataLabel.setText(label);

        dataUnits.setVisibility(View.VISIBLE);
        dataUnits.setText("(" + units + "):");

        singleValue.setVisibility(View.VISIBLE);
        singleValue.setText(String.valueOf(value));

        xAxisLabel.setVisibility(View.GONE);
        xAxis.setVisibility(View.GONE);

        yAxisLabel.setVisibility(View.GONE);
        yAxis.setVisibility(View.GONE);

        zAxisLabel.setVisibility(View.GONE);
        zAxis.setVisibility(View.GONE);
    }

    /**
    * @see android.support.v4.app.Fragment#onHiddenChanged(boolean)
    */
    @Override
    public void onHiddenChanged(boolean hidden)
    {
        super.onHiddenChanged(hidden);

        if (hidden)
        {
            if (BuildConfig.DEBUG)
            {
                Log.d(TAG, "Unregistering listener");
            }

            sensorManager.unregisterListener(this);
        }
    }

    /**
    * @see android.support.v4.app.Fragment#onPause()
    */
    @Override
    public void onPause()
    {
        super.onPause();

        if (BuildConfig.DEBUG)
        {
            Log.d(TAG, "onPause");
            Log.d(TAG, "Unregistering listener");
        }

        sensorManager.unregisterListener(this);
    }
}

到此為止,整個實例介紹完畢,執行后的效果如圖6-12所示。

▲圖6-12 執行效果

主站蜘蛛池模板: 濮阳县| 海门市| 泰兴市| 邵阳县| 乐平市| 安平县| 富源县| 都昌县| 吐鲁番市| 自贡市| 赣州市| 香格里拉县| 旬邑县| 莱西市| 栖霞市| 阿荣旗| 噶尔县| 古丈县| 福贡县| 青铜峡市| 禹城市| 梁平县| 且末县| 乌拉特后旗| 上犹县| 广宁县| 姚安县| 辽宁省| 长兴县| 白玉县| 靖边县| 琼海市| 达拉特旗| 昌乐县| 清流县| 会昌县| 宁远县| 文昌市| 杨浦区| 沈阳市| 囊谦县|