日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Android?如何獲取傳感器的數據方法詳解_Android

作者:??ByteSaid??? ? 更新時間: 2022-09-23 編程語言

1 傳感器簡介

傳感器 Sensor 是一種檢測裝置,能感受到被測量的信息,并能將感受到的信息,按一定規律變換成為電信號或其他所需形式的信息輸出,以滿足信息的傳輸、處理、存儲、顯示、記錄和控制等要求。 Android 提供了對設備傳感器的支持,只要 Android 設備的硬件提供了這些傳感器,Android 應用可以通過傳感器來獲取設備的外界條件,包括手機的運行狀態、當前擺放的方向等。Android 系統還提供了驅動程序去管理這些傳感器硬件,可以通過監聽器的方式監聽傳感器硬件感知到的外部環境的變化。

Android 平臺支持三大類傳感器:

類別 傳感器 說明
運動傳感器 TYPE_ACCELEROMETER 加速度傳感器,基于硬件
TYPE_GRAVITY 重力傳感器,基于硬件或軟件
TYPE_GYROSCOPE 陀螺儀傳感器,基于硬件
TYPE_ROTATION_VECTOR 旋轉矢量傳感器,基于硬件或軟件
TYPE_LINEAR_ACCELERATION 線性加速度傳感器,基于硬件或軟件
位置傳感器 TYPE_MAGNETIC_FIELD 磁力傳感器,基于硬件
TYPE_ORIENTATION 方向傳感器,基于軟件
TYPE_PROXIMITY 距離傳感器,基于硬件
環境傳感器 TYPE_LIGHT 光線感應傳感器,基于硬件
TYPE_PRESSURE 壓力傳感器,基于硬件
TYPE_TEMPERATURE 溫度傳感器,基于硬件

有些傳感器基于硬件,有些基于軟件?;谟布膫鞲衅魇莾戎迷谑謾C或平板設備中的物理組件。這類傳感器通過直接測量特定的環境屬性(如加速度、地磁場強度或角度變化)來采集數據。基于軟件的傳感器不是物理設備,它們只是模仿基于硬件的傳感器。基于軟件的傳感器從一個或多個基于硬件的傳感器獲取數據,有時被稱為虛擬傳感器或合成傳感器。比如線性加速度傳感器和重力傳感器就是基于軟件的傳感器。

傳感器棄用說明:

  • Android 2.2(API 級別 8)已棄用方向傳感器,Android 4.4W(API 級別 20)已棄用此傳感器類型 TYPE_ORIENTATION。替代方法見后面示例代碼。
  • 溫度傳感器已在 Android 4.0(API 級別 14)中棄用,不同設備具有不同的實現。

2 傳感器的使用

2.1 獲取傳感器服務

Android 中內置了很多系統級的服務,用于給開發人員使用,而傳感器也是通過傳感器服務 SensorManager 來管理的。而在 Android 組件中獲取系統服務,使用方法 Context.getSystemService(String) 即可,它的參數均以 static final 的方式定義在 Context 中,而獲取 SensorManager 需要傳入 Context.SENSOR_SERVICE。

SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

2.2 獲取待監聽的傳感器

傳感器服務管理設備上所有的傳感器,所以需要獲取待監聽的傳感器。 可以通過在 getSensorList() 方法中傳入 TYPE_ALL 來獲取設備上的所有傳感器:

List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);

也可以通過指定的 type 參數獲取到相對應的傳感器,如果設備上有多個特定類型的傳感器,則必須將其中一個指定為默認傳感器。如果沒有指定默認傳感器,則該方法調用會返回 null,這表示設備沒有該類型的傳感器。

Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

注意使用前先判斷傳感器是否存在。

運行時檢測。

if (sensor != null) {
    //傳感器存在
} else {
    //傳感器不存在
}

使用清單文件來限定目標設備必須帶有指定傳感器配置。

<uses-feature
    android:name="android.hardware.sensor.accelerometer"
    android:required="true" />

對于某一個傳感器,它的一些具體信息的獲取方法如下:

  • getMaximumRange() 最大取值范圍
  • getName() 設備名稱
  • getPower() 功率
  • getResolution() 精度
  • getType() 傳感器類型
  • getVentor() 設備供應商
  • getVersion() 設備版本號

2.3 注冊傳感器的監聽器

獲得 SensorManager 和 Sensor 對象之后,就可以為其 Sensor 注冊監聽器了。為傳感器注冊監聽器,使用 SensorManager.registerListener() 方法即可,它存在多個重載方法,但是有些方法已經過時了,下面提供一個常用的方法:

boolean registerListener(SensorEventListener listener,Sensor sensor,int rateUs)

上面方法參數的意義:listener:傳感器的監聽器、sensor:待監聽的傳感器、rateUs:傳感器的采樣率。 從 registerListener() 方法可以看出,它需要傳遞一個 SensorEventListener 對象,它就是傳感器的監聽器,其中包含兩個方法,需要開發人員去實現它:

  • void onSensorChanged(SensorEvent event):當傳感器感應的值發生變化時回調。
  • void onAccuracyChanged(Sensor sensor,int accuracy):當傳感器精度發生變化時回調。 對于上面兩個方法,傳感器的精度一般是不會發生改變的,所以我們一般主要的代碼量在 onSensorChanged()中。

在 onSensorChanged(SensorEvent event) 方法中有一個參數 event,通過 event 可以獲取傳感器的類型以及傳感器的數據。

  • 獲取傳感器的類型:event.sensor.getType()
  • 獲取傳感器的數據:event.values[i],i為0,1,2...,不同傳感器,event.values[i] 對應的數據不同。以加速度傳感器為例,values[0] 表示x軸上的加速度,values[1] 表示y軸上的加速度,values[2] 表示z軸上的加速度。

registerListener() 方法還有一個 rateUs 的參數,它表示監聽傳感器改變的采樣率,就是從傳感器獲取值的頻率。它被定義以 static final 的形式定義在 SensorManager 中,方便我們直接使用,它定義了如下幾個參數:

參數 延時 說明
SensorManager.SENSOR_DELAY_FASTEST 0ms 一般不是特別敏感的處理不推薦使用,該種模式可能造成手機電力大量消耗,由于傳遞的為原始數據,算法不處理好將會影響游戲邏輯和 UI 的性能。
SensorManager.SENSOR_DELAY_GAME 20ms 一般絕大多數的實時性較高的游戲都使用該級別。
SensorManager.SENSOR_DELAY_UI 60ms 適合普通用戶界面 UI 變化的頻率,相對節省電能和邏輯處理,一般游戲開發中不使用。
SensorManager.SENSOR_DELAY_NORMAL 200ms 對于一般的益智類或 EASY 級別的游戲可以使用,但過低的采樣率可能對一些賽車類游戲有跳幀現象。

Android 為我們提供了這幾個采樣率的參數,方便我們使用。但對于選擇那種采樣率而言,并不是越快越好,要參照實際開發的應用的情況來說,采樣率越大,將越耗費資源,包括電量、CPU 等,所以要根據實際情況選擇,畢竟再強大的應用,如果造成設備續航能力的降低,也是會被用戶所不喜的。

2.4 注銷傳感器的監聽器

當使用完傳感器之后,需要為其注銷監聽器,因為傳感器的監聽器并不會因為應用的結束而自行釋放資源,需要開發人員在適當的時候主動注銷。注銷傳感器監聽器使用 SensorManager.unregisterListener() 方法即可,和監聽器的注冊方法一樣,它也具有多個重載的方法,但是有一些已經被棄用了,下面介紹一個常用的:

void unregisterListener(SensorEventListener listener)

3 示例代碼

Java 代碼如下:

public class MainActivity extends AppCompatActivity {
    private final String TAG = "sensor-sample";
    private TextView mAccelerometerSensorTextView;
    private TextView mMagneticSensorTextView;
    private TextView mGyroscopeSensorTextView;
    private TextView mOrientationSensorTextView;
    private SensorManager mSensorManager;
    private MySensorEventListener mMySensorEventListener;
    private float[] mAccelerometerReading = new float[3];
    private float[] mMagneticFieldReading = new float[3];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAccelerometerSensorTextView = findViewById(R.id.accelerometer_sensor);
        mMagneticSensorTextView = findViewById(R.id.magnetic_sensor);
        mGyroscopeSensorTextView = findViewById(R.id.gyroscope_sensor);
        mOrientationSensorTextView = findViewById(R.id.orientation_sensor);

        this.mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        this.mMySensorEventListener = new MySensorEventListener();
    }
    @Override
    protected void onResume() {
        super.onResume();
        if (mSensorManager == null) {
            return;
        }
        Sensor accelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        if (accelerometerSensor != null) {
            //register accelerometer sensor listener
            mSensorManager.registerListener(mMySensorEventListener, accelerometerSensor, SensorManager.SENSOR_DELAY_UI);
        } else {
            Log.d(TAG, "Accelerometer sensors are not supported on current devices.");
        }
        Sensor magneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        if (magneticSensor != null) {
            //register magnetic sensor listener
            mSensorManager.registerListener(mMySensorEventListener, magneticSensor, SensorManager.SENSOR_DELAY_UI);
        } else {
            Log.d(TAG, "Magnetic sensors are not supported on current devices.");
        }
        Sensor gyroscopeSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        if (gyroscopeSensor != null) {
            //register gyroscope sensor listener
            mSensorManager.registerListener(mMySensorEventListener, gyroscopeSensor, SensorManager.SENSOR_DELAY_UI);
        } else {
            Log.d(TAG, "Gyroscope sensors are not supported on current devices.");
        }
    }
    @Override
    protected void onPause() {
        super.onPause();
        if (mSensorManager == null) {
            return;
        }
        //unregister all listener
        mSensorManager.unregisterListener(mMySensorEventListener);
    }

    /*
    This orientation sensor was deprecated in Android 2.2 (API level 8), and this sensor type was deprecated in Android 4.4W (API level 20).
    The sensor framework provides alternate methods for acquiring device orientation.
     */
    private void calculateOrientation() {
        final float[] rotationMatrix = new float[9];
        SensorManager.getRotationMatrix(rotationMatrix, null, mAccelerometerReading, mMagneticFieldReading);

        final float[] orientationAngles = new float[3];
        SensorManager.getOrientation(rotationMatrix, orientationAngles);
        Log.d(TAG, "orientation data[x:" + orientationAngles[0] + ", y:" + orientationAngles[1] + ", z:" + orientationAngles[2] + "]");
        mOrientationSensorTextView.setText("[x:" + orientationAngles[0] + ", y:" + orientationAngles[1] + ", z:" + orientationAngles[2] + "]");
    }
    private class MySensorEventListener implements SensorEventListener {
        @Override
        public void onSensorChanged(SensorEvent event) {
            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                mAccelerometerReading = event.values;
                Log.d(TAG, "accelerometer data[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");
                mAccelerometerSensorTextView.setText("[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");
            } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                mMagneticFieldReading = event.values;
                Log.d(TAG, "magnetic data[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");
                mMagneticSensorTextView.setText("[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");
            } else if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
                Log.d(TAG, "gyroscope data[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");
                mGyroscopeSensorTextView.setText("[x:" + event.values[0] + ", y:" + event.values[1] + ", z:" + event.values[2] + "]");
            }
            calculateOrientation();
        }
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            Log.d(TAG, "onAccuracyChanged:" + sensor.getType() + "->" + accuracy);
        }

    }
}

運行效果如下:

原文鏈接:https://juejin.cn/post/7120052450576302117

欄目分類
最近更新