Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android開發筆記之高級主題—傳感器的簡單介紹

android開發筆記之高級主題—傳感器的簡單介紹

編輯:關於Android編程

今天我們開始進入講解android中的一些高級主題的用法,比如傳感器、GPS、NFC、語音和人臉識別等。

這次來對傳感器的一個簡單介紹:

Android平台支持三大類的傳感器

位移傳感器

這些傳感器測量沿三個軸線測量加速度和旋轉。這類包含加速度,重力傳感器,陀螺儀,和矢量傳感器。

環境傳感器

這些傳感器測量各種環境參數,例如周圍的空氣溫度和壓力,光線,和濕度。這類包含氣壓,光線,和溫度傳感器。

位置傳感器

這些傳感器測量設備的物理位置。這類包含方向和磁力傳感器。

這些傳感器的一些是基於硬件的,一些是基於軟件的。基於硬件的傳感器是內嵌到手機或者平板中的物理元件,它們通過直接測量指定的環境屬性來得到它們的數據,例如加速度,磁場強度,或者角度變化。基於軟件的傳感器不是物理設備,盡管它們模仿基於硬件的傳感器。基於軟件的 傳感器從一個或更多基於硬件的傳感器獲取它們的數據,並且有時候被稱為虛擬傳感器或者合成傳感器。線性加速度傳感器和重力傳感器是基於軟件傳感器的例子。

很少Android設備有所有類型的傳感器。例如,大部分手機和平板有一個加速計和磁場計,但是很少的設備擁有氣壓或者溫度傳感器。並且,一個設備可以擁有一個類型不止一個的傳感器。例如,設備能有兩個重力傳感器,每個有不同的范圍。

這裡寫圖片描述

需要指出的是,傳感器的坐標系統與屏幕坐標系統不同,傳感器坐標系統的X軸沿屏幕向右;Y軸則沿屏幕向上,Z軸在垂直屏幕向上。

這裡寫圖片描述

我們依次看看幾種傳感器:

這裡寫圖片描述

1 加速度傳感器<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPrzTy9m2yLSruNDG99PWvdBHLXNlbnNvcqOst7W72HihonmhonrI/dbhtcS808vZtsjK/da1oaM8L3A+DQo8cD64w8r91rWw/LqstdjQxNL9waa1xNOwz+yjrLWlzrvKx20vc14yoaM8L3A+DQo8cD69q8rWu/rGvbfF1NrXwMPmyc+jrHjW4cSsyM/OqjCjrHnW4cSsyM8wo6x61uHErMjPOS44MaGjPC9wPg0KPHA+vavK1rv6s6/PwrfF1NrXwMPmyc+jrHrW4c6qLTkuODGhozwvcD4NCjxwPr2ryta7+s/y1/PH49Cxo6x41uHOqtX91rWhozwvcD4NCjxwPr2ryta7+s/y09LH49Cxo6x41uHOqri61rWhozwvcD4NCjxwPr2ryta7+s/yyc/H49Cxo6x51uHOqri61rWhozwvcD4NCjxwPr2ryta7+s/yz8LH49Cxo6x51uHOqtX91rWhozwvcD4NCjxwPjIgtMXBprSruNDG9zwvcD4NCjxwPrTFwaa0q7jQxve88rPGzqpNLXNlbnNvcqOst7W72HihonmhonrI/dbhtcS7t76ztMWzocr9vt2hozwvcD4NCjxwPrjDyv3WtbXEtaXOu8rHzqLM2Mu5wK2jqG1pY3JvLVRlc2xho6mjrNPDdVSx7cq+oaM8L3A+DQo8cD61pc670rK/ydLUyse438u5o6hHYXVzc6Opo6wxVGVzbGE9MTAwMDBHYXVzc6GjPC9wPg0KPHA+07K8/snP0ruw48O709C2wMGitcS0xcGmtKu40Mb3o6y0xcGmyv2+3dPJtefX08Lexcy0q7jQxvfM4bmpo6hFLWNvbXBhc3OjqaGjPC9wPg0KPHA+tefX08Lexcy0q7jQxvfNrMqxzOG5qc/CzsS1xLe9z/K0q7jQxvfK/b7doaM8L3A+DQo8cD4zILe9z/K0q7jQxvc8L3A+DQo8cD63vc/ytKu40Mb3vPKzxs6qTy1zZW5zb3KjrLe1u9jI/dbhtcS9x7bIyv2+3aOst73P8sr9vt21xLWlzrvKx73HtsihozwvcD4NCjxwPs6qwcu1w7W9vqvIt7XEvce2yMr9vt2jrEUtY29tcGFzc9Do0qq78cihRy1zZW5zb3K1xMr9vt2jrDwvcD4NCjxwPr6tuf28xsvjyfqy+k8tc2Vuc29yyv2+3aOst/HU8ta7xNy78cihy67Gvbe9z/K1xL3HtsihozwvcD4NCjxwPre9z/K0q7jQxvfM4bmpyP249sr9vt2jrLfWsfDOqmF6aW11dGihonBpdGNous1yb2xsoaM8L3A+DQo8cD5hemltdXRoo7q3vc67o6zS1HrW4c6q1uGjrLe1u9jLrsa9yrG0xbGxvKu6zVnW4bXEvNC9x6Ost7bOp86qMCZkZWc71sEzNjAmZGVnO6GjPC9wPg0KPHA+MCZkZWc7PbGxo6w5MCZkZWc7Pbaro6wxODAmZGVnOz3Ez6OsMjcwJmRlZzs9zvehozwvcD4NCjxwPnBpdGNoo7p41uG6zcuuxr3D5rXEvNC9x6Ost7bOp86qLTE4MCZkZWc71sExODAmZGVnO6GjPC9wPg0KPHA+tbF61uHP8nnW4deqtq/KsaOsvce2yM6q1f3WtaGjPC9wPg0KPHA+cm9sbKO6edbhus3Lrsa9w+a1xLzQvcejrNPJ09rA+sq31K3S8qOst7bOp86qLTkwJmRlZzvWwTkwJmRlZzuhozwvcD4NCjxwPrWxeNbhz/J61uHSxravyrGjrL3HtsjOqtX91rWhozwvcD4NCjxwPjQgzdPC3dLHtKu40Mb3PC9wPg0KPHA+zdPC3dLHtKu40Mb3vdDX9kd5cm8tc2Vuc29yo6y3tbvYeKGieaGiesj91uG1xL3HvNPL2bbIyv2+3aGjPC9wPg0KPHA+vce808vZtsi1xLWlzrvKx3JhZGlhbnMvc2Vjb25koaM8L3A+DQo8cD64+b7dTmV4dXMgU8rWu/rKtbLio7o8L3A+DQo8cD7Lrsa9xObKsdXr0P3XqqOsWtbhzqrV/aGjPC9wPg0KPHA+y67GvcTmyrHV69D916qjrHrW4c6quLqhozwvcD4NCjxwPs/y1/PQ/deqo6x51uHOqri6oaM8L3A+DQo8cD7P8tPS0P3XqqOsedbhzqrV/aGjPC9wPg0KPHA+z/LJz9D916qjrHjW4c6quLqhozwvcD4NCjxwPs/yz8LQ/deqo6x41uHOqtX9oaM8L3A+DQo8cD41ILniz9+40NOmtKu40Mb3PC9wPg0KPHA+ueLP37jQ06a0q7jQxve87LLiyrXKsbXEueLP38e/tsijrLnix7+1pc67ysdsdXijrMbkzu/A7dLi0uXKx9XVyeS1vbWlzrvD5rv9yc+1xLnizajBv6GjPC9wPg0KPHA+ueLP37jQ06a0q7jQxvfW99Kq08PT2kFuZHJvaWTPtc2ztcRMQ0TX1LavwcG2yLmmxNyhozwvcD4NCjxwPr/J0tS4+b7dssnR+bW9tcS54se/yv3Wtcq1yrG199X7TENEtcTBwbbIoaM8L3A+DQo8cD42ING5waa0q7jQxvc8L3A+DQo8cD7RucGmtKu40Mb3t7W72LWxx7C1xNG5x7+jrLWlzrvKx7DZxcHLub+oaGVjdG9wYXNjYWyjqGhQYaOpoaM8L3A+DQo8cD43IM7Ctsi0q7jQxvc8L3A+DQo8cD7OwrbItKu40Mb3t7W72LWxx7C1xM7CtsihozwvcD4NCjxwPjggvuDA67SruNDG9zwvcD4NCjxwPr7gwOu0q7jQxve87LLizu/M5dPryta7+rXEvuDA66OstaXOu8rHwOXD16GjPC9wPg0KPHA+0rvQqb7gwOu0q7jQxvfWu8Tct7W72NS2us29/MG9uPbXtMyso6w8L3A+DQo8cD7S8rTLo6y+4MDrtKu40Mb3vavX7rTzvuDA67e1u9jUtte0zKyjrNCh09rX7rTzvuDA67e1u9i9/Ne0zKyhozwvcD4NCjxwPr7gwOu0q7jQxve/ydPD09q908z9tee7sMqx19S2r7nYsdVMQ0TGwcS70tS92sqhtefBv6GjPC9wPg0KPHA+0rvQqdC+xqy8r7PJwcu+4MDrtKu40Mb3us254s/ftKu40Mb3wb3V37mmxNyhozwvcD4NCjxwPs/Cw+bI/bj2tKu40Mb31/a49rHIvc+jujwvcD4NCjxwPjxzdHJvbmc+1tjBprSruNDG9zwvc3Ryb25nPjwvcD4NCjxwcmUgY2xhc3M9"brush:java;"> 重力傳感器簡稱GV-sensor,輸出重力數據。 在地球上,重力數值為9.8,單位是m/s^2。 坐標系統與加速度傳感器相同。 當設備復位時,重力傳感器的輸出與加速度傳感器相同。

線性加速度傳感器

線性加速度傳感器簡稱LA-sensor。

線性加速度傳感器是加速度傳感器減去重力影響獲取的數據。

單位是m/s^2,坐標系統與加速度傳感器相同。

加速度傳感器、重力傳感器和線性加速度傳感器的計算公式如下:

加速度 = 重力 + 線性加速度

旋轉矢量傳感器

旋轉矢量傳感器簡稱RV-sensor。

旋轉矢量代表設備的方向,是一個將坐標軸和角度混合計算得到的數據。

RV-sensor輸出三個數據:

x*sin(theta/2)

y*sin(theta/2)

z*sin(theta/2)

sin(theta/2)是RV的數量級。

RV的方向與軸旋轉的方向相同。

RV的三個數值,與cos(theta/2)組成一個四元組。

RV的數據沒有單位,使用的坐標系與加速度相同。

傳感器框架:

你能訪問這些傳感器,是通過使用Android傳感器框架獲取原始數據。Android傳感器框架式android.hardware包的一部分,包含下面的類和接口:

SensorManager

你能使用這個類來創建一個傳感器服務的實例。這個類提供了各種方法類訪問和列舉傳感器,注冊和注銷傳感器事件監聽,並獲取相應的信息。這個類也提供了幾個傳感器的常量,用戶報告傳感器的精確度,設置數據獲取速率,和校准傳感器。

Sensor

你能使用這個類來創建一個指定傳感器的實例。這個類提供了各種方法讓你確定傳感器的功能。

SensorEvent

它提供了關於傳感器事件的信息。一個傳感器事件包含以下信息:原始傳感器數據,這類傳感器產生的事件,數據的准確性,和事件的時間戳。

SensorEventListener

你能使用這個接口來創建兩個回調方法,當傳感器的值改變或者當傳感器的精度改變的時候,它接受通知(傳感器事件)。

傳感器的值改變
在這種情況下系統調用onSensorChanged()方法,向你提供了一個SensorEvent對象,一個SensorEvent對象包含關於新的傳感器數據的信息,包括:數據的精度,傳感器產生的數據,數據產生的時間戳,和傳感器記錄的新的數據。

傳感器精度的變化
在 這種情況下系統調用onAccuracyChanged()方法,向你提供改變了新的傳感器精度的Sensor對象引用。精度通過四個狀態常量代 表:SENSOR_STATUS_ACCURACY_LOW,SENSOR_STATUS_ACCURACY_MEDIUM,SENSOR_STATUS_ACCURACY_HIGH, 或者SENSOR_STATUS_UNRELIABLE。

使用傳感器的步驟如下:

①調用Context的getSystemService(Context.SENSOR_SERVICE)方法獲取SensorManager對象。

②調用SensorManager的getDefaultSensor(int type)方法來獲取指定類型的傳感器。

從傳感器管理器中獲取其中某個或者某些傳感器的方法有如下三種:

第一種:獲取某種傳感器的默認傳感器

   Sensor defaultGyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);

第二種:獲取某種傳感器的列表

   List pressureSensors = sensorManager.getSensorList(Sensor.TYPE_PRESSURE);

第三種:獲取所有傳感器的列表,我們這個例子就用的第三種

   List allSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);

③一般在Activity的onResume()方法中調用SensorManager的registerListener()為指定傳感器注冊監聽器即可。程序可以通過實現監聽器即可獲取傳感器傳回來的數據。

SersorManager提供的注冊傳感器的方法為registerListener(SensorListener listener, Sensor sensor, int rate)該方法中三個參數說明如下:

listener:監聽傳感器事件的監聽器

sensor:傳感器對象

rate:指定獲取傳感器數據的頻率

rate可以獲取傳感器數據的頻率,支持如下幾個頻率值:

    SENSOR_DELAY_FASTEST:最快,延遲最小。

    SENSOR_DELAY_GAME:適合游戲的頻率。

    SENSOR_DELAY_NORMAL:正常頻率

    SENSOR_DELAY_UI:適合普通用戶界面的頻率。

那就來舉個例子來測試下:

這個例子就是顯示下手機上支持的傳感器及傳感器的一些信息並測試幾個常用傳感器

效果:

這裡寫圖片描述

核心代碼:

activity_main.xml



    

    

    

    

    

    

    

    

    

    

    

MainActivity.java

public class MainActivity extends Activity implements SensorEventListener{

    private TextView tv;
    private TextView tv_direction;
    private TextView tv_xianxing;
    private TextView tv_jiasudu;
    private TextView tv_guangqiang;
    private TextView tv_juli;
    private SensorManager sensorManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //1.獲取SensorManager服務
        sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        tv = (TextView) findViewById(R.id.tv);
        tv_direction = (TextView) findViewById(R.id.tv_direction);
        tv_xianxing = (TextView) findViewById(R.id.tv_xianxing);
        tv_jiasudu = (TextView) findViewById(R.id.tv_jiasudu);
        tv_guangqiang = (TextView) findViewById(R.id.tv_guangqiang);
        tv_juli = (TextView) findViewById(R.id.tv_juli);
        //獲取手機上支持的傳感器
        List list = sensorManager.getSensorList(Sensor.TYPE_ALL);
        tv.append("手機上有" + list.size() + "個傳感器" + "\n");
        for (Sensor sensor : list) {
            String msg = "名字:" + sensor.getName() + ",版本:" + sensor.getVersion()
                    +",供應商:" + sensor.getVendor() + ",類型:" + sensor.getType();
            tv.append(msg + "\n");
        }
    }
    @Override
    protected void onResume() {
        //23.獲得相應傳感器並注冊監聽器
        //第三個參數表示精度
        sensorManager.registerListener(this,
                sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
                sensorManager.SENSOR_DELAY_UI);
        sensorManager.registerListener(this,
                sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION),
                sensorManager.SENSOR_DELAY_UI);
        sensorManager.registerListener(this,
                sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                sensorManager.SENSOR_DELAY_UI);
        sensorManager.registerListener(this,
                sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
                sensorManager.SENSOR_DELAY_UI);
        sensorManager.registerListener(this,
                sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
                sensorManager.SENSOR_DELAY_UI);
        super.onResume();
    }
    @Override
    protected void onStop() {
        //4.解除綁定
        sensorManager.unregisterListener(this);
        super.onStop();
    }
    @Override
    public void onSensorChanged(SensorEvent event) {
        //傳感器數據變化,在該方法中我們可以獲取傳感器變化的值
        switch (event.sensor.getType()) {
        case Sensor.TYPE_ORIENTATION:
            float z = event.values[0];
            float x = event.values[1];
            float y = event.values[2];
            tv_direction.setText("z軸的方向:" + z + "\n"
                    + "x軸的方向:" + x + "\n"
                    + "y軸的方向:" + y + "\n");
            break;
        case Sensor.TYPE_LINEAR_ACCELERATION:
            float x1 = event.values[0];
            float y1 = event.values[1];
            float z1 = event.values[2];
            tv_xianxing.setText("x軸的加速度:" + x1 + "\n"
                    + "y軸的加速度:" + y1 + "\n"
                    + "z軸的加速度:" + z1 + "\n");
            break;
        case Sensor.TYPE_ACCELEROMETER:
            float x2 = event.values[0];
            float y2 = event.values[1];
            float z2 = event.values[2];
            tv_jiasudu.setText("x軸的加速度:" + x2 + "\n"
                    + "y軸的加速度:" + y2 + "\n"
                    + "z軸的加速度:" + z2 + "\n");
            break;
        case Sensor.TYPE_LIGHT:
            float light = event.values[0];
            tv_guangqiang.setText("光強:" + light);
            break;
        case Sensor.TYPE_PROXIMITY:
            float distanse = event.values[0];
            tv_juli.setText("距離傳感器:" + distanse);
            break;
        default:
            break;
        }
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        //傳感器精度的變化
    }
}

這個傳感器的介紹就這些,大家應該都看得懂。趕緊拿出自己的手機來試試吧。

訪問和使用傳感器的總結:

①注銷傳感器監聽器

當你完成使用傳感器的事情或者當傳感器activity pause的時候,確保注銷傳感器監聽器。如果一個傳感器的監聽器被注冊並且它的activity被pause,這個傳感器將繼續獲取數據並且使用電池資源,除非你注銷這個傳感器。

mSensorManager.unregisterListener(this);

②不要在模擬器上測試你的代碼

你目前不能再模擬器上測試你的傳感器代碼,因為模擬器不能模擬傳感器。你必須在一個物理設備上測試你的傳感器代碼。

③不要阻塞onSensorChanged()方法

傳感器數據可以高速的變化,這意味著系統可能經常調用onSensorChanged(SensorEvent)方法。作為一項最佳的實踐,你應該竟可能少 的在onSensorChanged(SensorEvent)方法中做事情,所以你沒有阻塞它。如果你的應用程序要求你做任何數據過濾或者減少傳感器數 據,你應該在onSensorChanged(SensorEvent)方法外執行這個工作。

④避免使用過時的方法或者傳感器類型

幾個方法和常量已經被棄用。尤其,TYPE_ORIENTATION傳感器類型已經被棄用。為了獲取方向數據你應該使用getOrientation()方 法替代。同樣,TYPE_TEMPERATURE傳感器類型已經被棄用。你應該在運行Andorid4.0的設備上使用TYPE_AMBIENT_TEMPERATURE傳感器類型替代。 

⑤在你使用它們之前驗證傳感器

在你嘗試從它獲取數據之前,總是驗證在一個傳感器在設備上是否存在。不要因為它是一個常用的傳感器而簡單假設傳感器存在。設備廠商沒有被要求在它們的設備上提供任何指定的傳感器。

⑥仔細選擇傳感器延遲

當你使用registerListener()方法中注冊一個傳感器的時候,確保你選擇一個適合你的應用程序或者用例的分發率。傳感器能非常高速提供數據。允許系統發送額外的你不需要浪費系統資源並使用電池的數據。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved