感應器總覽

大多數 Android 裝置都內建感應器,可測量動作、螢幕方向, 和各種環境條件這些感應器能夠提供高用量的原始資料 。如果您想監控 3D 裝置的移動或 或監控裝置附近的環境變化。舉例來說 遊戲可能會追蹤來自裝置重力感應器的讀數,藉此推斷複雜的使用者手勢 以及動作,例如傾斜、搖晃、旋轉或搖擺。同樣地,天氣應用程式可能會使用 裝置的溫度感應器和濕度感應器,用於計算並回報露點或旅遊 應用程式可能會使用地磁場感應器和加速計回報指南針 方針。

Android 平台支援以下三種感應器:

  • 動作感應器

    這些感應器會沿著三軸測量加速力和旋轉力,這個 類別包括加速計、重力感應器、陀螺儀和旋轉向量 感應器。

  • 環境感應器

    這些感應器會測量多種環境參數,例如環境氣溫 包括壓力、照明和濕度這個類別包括氣壓計、光量計 溫度計

  • 位置感應器

    這些感應器會測量裝置的實際位置,這個類別包括 螢幕方向感應器和磁力儀。

如要存取裝置上的感應器,並擷取原始感應器資料,請使用 Android 感應器架構感應器架構提供多種類別和介面,協助您執行更廣泛的 代表各式各樣的感應器工作舉例來說,您可以使用感應器架構執行以下操作:

  • 確認裝置可用的感應器。
  • 決定個別感應器的功能,例如最大範圍、製造商、功率 需求和解決方法
  • 取得原始感應器資料,並定義取得感應器資料的最低速率。
  • 註冊及取消註冊可監控感應器異動的感應器事件監聽器。

本主題將概略說明 Android 平台可用的感應器。 並介紹感應器架構。

感應器簡介

Android 感應器架構可讓你存取多種類型的感應器。其中一些感應器 有些則是以軟體為基礎硬體式感應器是實體元件 下載到手機或平板電腦裝置上。他們直接評估特定環境,藉此取得資料 ,例如加速度、地磁場強度或角度變化。軟體式 雖然感應器會模仿硬體感應器,但並非實體裝置。軟體式感應器 資料衍生自一或多個硬體式感應器,有時也稱為虛擬 感應器或合成感應器線性加速感應器和重力感應器是 軟體式感應器表 1 摘要列出 Android 支援的感應器 平台。

只有少數搭載 Android 系統的裝置搭載所有類型的感應器。例如大部分的手機裝置和 平板電腦具有加速計和磁力儀,但這些裝置擁有較少的裝置 氣壓計或溫度計此外,單一裝置可以有多個特定類型的感應器。適用對象 舉例來說,一部裝置可以有兩個重力感應器,每個感應器的重力範圍皆不同

表 1. Android 平台支援的感應器類型。

感應器 類型 說明 常見用途
TYPE_ACCELEROMETER 硬體 測量裝置套用至裝置的加速度 (以 m/s2 為單位) 這三個物理軸 (x、y 和 z),包括重力的力量 動作偵測 (搖動、傾斜等)。
TYPE_AMBIENT_TEMPERATURE 硬體 測量環境室溫,以攝氏度為單位。詳情請參閱下方的附註。 監測溫度。
TYPE_GRAVITY 軟體或硬體 測量套用至所有裝置的重力 (公尺/秒) 即三個實體軸 (x、y、z)。 動作偵測 (搖動、傾斜等)。
TYPE_GYROSCOPE 硬體 測量裝置的旋轉速率 物理軸 (x、y 和 z)。 旋轉偵測 (傾斜、轉動等)。
TYPE_LIGHT 硬體 測量 Lx 的環境光度 (照明)。 控制螢幕亮度。
TYPE_LINEAR_ACCELERATION 軟體或硬體 以 m/s2 為單位測量加速度 已套用至 這三個物理軸 (x、y 和 z),不含重力力。 沿著單一軸線監控加速。
TYPE_MAGNETIC_FIELD 硬體 測量全部三個物理軸 (x、y、z) 的環境磁場 μT。 建立指南針。
TYPE_ORIENTATION 軟體 測量裝置在三個物理軸 (x、y、z) 周圍的旋轉角度。 從 API 級別 3 開始,您可以取得 測量到的裝置使用重力感應器 以及地磁場感應器和 getRotationMatrix() 方法。 正在判斷裝置位置。
TYPE_PRESSURE 硬體 測量環境氣壓 (以 hPa 或 mbar 為單位)。 監測氣壓變化。
TYPE_PROXIMITY 硬體 測量物件與 (以公分為單位) 相對於裝置畫面的距離 裝置。這類感應器通常用於判斷手機是否 某人的耳朵 通話期間的手機位置。
TYPE_RELATIVE_HUMIDITY 硬體 測量相對環境濕度百分比 (百分比)。 監測露點、絕對濕度和相對濕度。
TYPE_ROTATION_VECTOR 軟體或硬體 提供裝置螢幕方向的三個元素,藉此測量裝置的方向 動作偵測和旋轉偵測。
TYPE_TEMPERATURE 硬體 測量裝置溫度,以攝氏度為單位。這部感應器 導入方式會因裝置而異 這個感應器已替換成「TYPE_AMBIENT_TEMPERATURE」感應器 API 級別 14 用於監測溫度。

感應器架構

如要存取這些感應器,並運用 Android 感應器架構取得原始感應器資料, 感應器架構是 android.hardware 套件的一部分,包含下列內容: 類別和介面:

SensorManager
你可以使用這個類別來建立感應器服務的例項。這個類別提供 存取及列出感應器、註冊及取消註冊感應器事件的各種方法 以及取得方向資訊。這個類別也提供多個感應器常數 包括回報感應器準確率、設定資料擷取率及校正感應器。
Sensor
你可以使用這個類別建立特定感應器的例項。這個類別提供多種 可讓您判斷感應器的能力
SensorEvent
系統會使用這個類別建立感應器事件物件,藉此提供 也就是感應器事件感應器事件物件包含下列資訊:原始感應器資料、 產生事件的感應器類型、資料準確度,以及 活動。
SensorEventListener
您可以使用這個介面建立兩種用來接收通知的回呼方法 (感應器 事件)。

在一般應用程式中,您會使用下列感應器相關 API 來執行兩項基本工作:

  • 找出感應器和感應器功能

    如果您的應用程式含有 需要特定感應器類型或功能才能運作的功能。舉例來說 找出裝置上的所有感應器,並停用任何應用程式功能 並仰賴不存在的感應器同樣地,您也可以找出所有感應器 方便您選擇具有最佳效能的感應器實作方式 應用程式。

  • 監控感應器事件

    但監控感應器事件是取得原始感應器資料的方式。每次發生感應器事件時 感應器偵測到正在測量的參數發生變化。「感應器事件」 包含四項資訊:觸發事件的感應器名稱、 事件的時間戳記、事件準確率,以及觸發的原始感應器資料 活動。

可用感應器

雖然感應器可用的感應器因裝置而異,但也可能因 Android 裝置而異。 版本。這是因為 Android 感應器在 發布新版本例如,Android 1.5 (API 級別 3) 導入了許多感應器, 未實作,且在 Android 2.3 (API 級別 9) 之前無法使用。同樣地 Android 2.3 (API 級別 9) 和 Android 4.0 (API 級別 14) 導入了數個感應器。兩條 感應器已淘汰,並由更優異的新版感應器取代。

表 2 摘要列出各平台每個感應器的可用性。只有四個 是因為這些平台涉及感應器異動搭載全新設計的感應器 列為已淘汰的後續平台仍可提供 感應器在裝置上,符合 Android 的前瞻相容性政策。

表 2. 各平台可用的感應器。

感應器 Android 4.0
(API 級別 14)
Android 2.3
(API 級別 9)
Android 2.2
(API 級別 8)
Android 1.5
(API 級別 3)
TYPE_ACCELEROMETER
TYPE_AMBIENT_TEMPERATURE 不適用 不適用 不適用
TYPE_GRAVITY 不適用 不適用
TYPE_GYROSCOPE 不適用1 不適用1
TYPE_LIGHT
TYPE_LINEAR_ACCELERATION 不適用 不適用
TYPE_MAGNETIC_FIELD
TYPE_ORIENTATION 2 2 2
TYPE_PRESSURE 不適用1 不適用1
TYPE_PROXIMITY
TYPE_RELATIVE_HUMIDITY 不適用 不適用 不適用
TYPE_ROTATION_VECTOR 不適用 不適用
TYPE_TEMPERATURE 2

1 已在 Android 1.5 (API 級別) 中新增這個感應器類型 3)、 但不適用於 Android 2.3 (API 級別 9) 版本。

2 這個感應器雖可以使用,但已問世 已淘汰。

識別感應器和感應器功能

Android 感應器架構提供數種方法,可讓您輕鬆判斷 執行階段,此功能會播放裝置上的感應器資料。API 也提供方法,可讓您判斷 例如感應器的最大範圍、解析度和功率 Google Cloud 就是最佳選擇

如要辨識裝置中的感應器,請先取得感應器的參照 課程中也會快速介紹 Memorystore 這是 Google Cloud 的全代管 Redis 服務方法是透過以下方式建立 SensorManager 類別的例項: 呼叫 getSystemService() 方法並傳遞 SENSOR_SERVICE 引數中。例如:

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

Java

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

接下來,你可以呼叫 getSensorList() 方法並使用 TYPE_ALL 常數。例如:

Kotlin

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

Java

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

如要列出指定類型的所有感應器,您可以使用另一個常數,而非 TYPE_ALL,例如 TYPE_GYROSCOPETYPE_LINEAR_ACCELERATION,或 TYPE_GRAVITY

您也可以使用 getDefaultSensor() 方法並傳入類型,判斷裝置上是否存在特定類型的感應器 特定感應器的常數。如果裝置有多個指定類型的感應器, 必須將感應器指派為預設感應器。如果指定的預設感應器不存在 方法呼叫會傳回空值,表示裝置沒有該類型 感應器。舉例來說,以下程式碼會檢查裝置上是否有磁力儀:

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) {
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){
    // Success! There's a magnetometer.
} else {
    // Failure! No magnetometer.
}

注意:Android 不需要裝置製造商製作任何產品 安裝在 Android 裝置上,因此能支援許多不同類型的感應器 感應器設定

除了列出裝置上的感應器之外,您也可以使用 Sensor 類別用來判斷個別功能的能力和屬性 感應器。如果您希望應用程式根據不同的感應器或 只有裝置才能支援感應器的功能例如,您可以使用 getResolution()getMaximumRange() 方法,以取得感應器的解析度和最大測量範圍。您也可以使用 getPower() 方法,用於取得感應器的電源需求。

如果您要針對應用程式最佳化 不同製造商的感應器或感應器的不同版本舉例來說 監控傾斜和搖動等使用者手勢,您可以建立一組資料篩選器 針對使用特定廠商重力感應器的新型裝置制定規則和最佳化作業 一組資料篩選規則,以及針對沒有重力感應器的裝置 只是加速計以下程式碼範例說明如何使用 getVendor()getVersion() 方法執行以下作業 而負責任的 AI 技術做法 有助於達成這項目標在本範例中,我們正在尋找將 Google LLC 列為供應商並 的版本號碼為 3。如果裝置上沒有該感應器,我們會嘗試使用 加速計。

Kotlin

private lateinit var sensorManager: SensorManager
private var mSensor: Sensor? = null

...

sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) {
    val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY)
    // Use the version 3 gravity sensor.
    mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 }
}
if (mSensor == null) {
    // Use the accelerometer.
    mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    } else {
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
        null
    }
}

Java

private SensorManager sensorManager;
private Sensor mSensor;

...

sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = null;

if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
    List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
    for(int i=0; i<gravSensors.size(); i++) {
        if ((gravSensors.get(i).getVendor().contains("Google LLC")) &&
           (gravSensors.get(i).getVersion() == 3)){
            // Use the version 3 gravity sensor.
            mSensor = gravSensors.get(i);
        }
    }
}
if (mSensor == null){
    // Use the accelerometer.
    if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
        mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    } else{
        // Sorry, there are no accelerometers on your device.
        // You can't play this game.
    }
}

另一個實用的方法是 getMinDelay() 方法 ,這會傳回感應器感測資料的最短時間間隔 (以微秒為單位)。任何感應器 這會為 getMinDelay() 傳回非零的值 是一種串流方式 感應器。串流感應器會定期感應資料,並在 Android 2.3 (API) 中推出 第 9 級)。如果呼叫 getMinDelay() 方法時感應器傳回 0,表示 感應器不是串流感應器,因為只有在 就能偵測出周遭動靜

getMinDelay() 方法非常實用 由您決定 感應器才能取得資料如果應用程式中的某些功能需要高資料 那麼你可以用這個方法判斷感應器 符合這些要求,並在應用程式內啟用或停用相關功能 。

注意:系統不會測量感應器的最大資料擷取率 也就是感應器架構將感應器資料傳送至應用程式的速度。 感應器架構會透過感應器事件回報資料,並有幾項因素會影響 應用程式接收感應器事件詳情請參閱「監控感應器事件」一文。

監控感應器事件

如要監控原始感應器資料,您必須實作兩種透過 SensorEventListener 介面:onAccuracyChanged()onSensorChanged()。Android 系統呼叫 這些方法發生的事件:

以下程式碼顯示如何使用 onSensorChanged() 方法監控 感應器。這個範例會顯示 TextView 中的原始感應器資料 是 在 main.xml 檔案中定義為 sensor_data

Kotlin

class SensorActivity : Activity(), SensorEventListener {
    private lateinit var sensorManager: SensorManager
    private var mLight: Sensor? = null

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
    }

    override fun onSensorChanged(event: SensorEvent) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        val lux = event.values[0]
        // Do something with this sensor value.
    }

    override fun onResume() {
        super.onResume()
        mLight?.also { light ->
            sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onPause() {
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

Java

public class SensorActivity extends Activity implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor mLight;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        // The light sensor returns a single value.
        // Many sensors return 3 values, one for each axis.
        float lux = event.values[0];
        // Do something with this sensor value.
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

在此範例中,叫用 registerListener() 方法時,會指定預設資料延遲時間 (SENSOR_DELAY_NORMAL)。資料 延遲時間 (或取樣率) 會決定感應器事件傳送到應用程式的時間間隔 透過 onSensorChanged() 回呼方法傳送。預設 資料延遲適合監控 螢幕方向通常會變更,且會延遲 200,000 微秒。您可以指定 資料延遲,例如 SENSOR_DELAY_GAME (20,000 微秒) 延遲時間)、SENSOR_DELAY_UI (延遲 60,000 微秒) 或 SENSOR_DELAY_FASTEST (0 微秒延遲時間)。從 Android 3.0 (API) 開始 等級 11) 也可以將延遲時間指定為絕對值 (以微秒為單位)。

您指定的延遲時間只是建議的延遲時間。Android 系統和其他應用程式 可能會改變這個延遲最佳做法是指定最大延遲時間 系統花費的時間通常比您指定的延遲時間還小 (也就是說,您應該選擇 但仍符合應用程式需求的最慢取樣率)。如果使用較長的延遲時間 處理器的負載較低 因此耗電量較低

沒有任何公開方法可判斷感應器架構傳送速率 感應器事件傳送至應用程式;不過,您可以使用與 感應器事件,以便計算多個事件的取樣率。您無需變更 設定完成後的取樣率 (延遲)。如果您因為某些原因而需要變更延遲 必須取消註冊感應器事件監聽器,再重新註冊。

另外請注意,本範例使用 onResume() 和 用於註冊及取消註冊感應器事件的 onPause() 回呼方法 接聽程式。最佳做法是一律停用不需要的感應器, 活動已暫停。如未執行這類動作,部分感應器會在幾小時內耗盡電池電力 有相當程度的電力,而且會快速消耗電池電力。系統 不會在螢幕關閉時自動停用感應器。

處理不同的感應器設定

Android 不會為裝置指定標準感應器設定, 也就是說,裝置製造商可在自家應用程式中加入任何感應器設定 Android 裝置。因此,裝置可能會納入多種 以因應各種設定 如果您的應用程式需要使用特定類型的感應器,請務必確認 才能順利執行應用程式

你可以透過以下兩種方式,確保裝置上有指定的感應器:

  • 在執行階段偵測感應器,並視情況啟用或停用應用程式功能。
  • 使用 Google Play 篩選器指定具有特定感應器設定的裝置。

我們會在以下章節中討論每個選項。

在執行階段偵測感應器

如果您的應用程式使用特定類型的感應器,但不需要,您可以使用 感應器架構,以便在執行階段偵測感應器,然後停用或啟用應用程式功能 。舉例來說,導航應用程式可能會使用溫度感應器 壓力感應器、GPS 感應器和地磁場感應器 (顯示溫度和氣溫) 壓力、位置和指南針方位。如果裝置沒有壓力感應器,您可以使用 感應器架構,以便在執行階段偵測壓力感應器,然後停用 部分顯示壓力的應用程式 UI 部分。舉例來說,以下程式碼會檢查 裝置上是否有壓力感應器:

Kotlin

private lateinit var sensorManager: SensorManager
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) {
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

Java

private SensorManager sensorManager;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){
    // Success! There's a pressure sensor.
} else {
    // Failure! No pressure sensor.
}

使用 Google Play 篩選器指定特定感應器設定

如果您是在 Google Play 發布應用程式,可以使用 資訊清單檔案中的 <uses-feature> 元素,藉此針對不支援的裝置篩選應用程式 請為您的應用程式 建立適當的感應器設定 <uses-feature> 元素包含多個硬體描述元,可讓您篩選 偵測應用程式是否含有特定感應器可列出的感應器包括: 加速計、氣壓計、指南針 (地磁場)、陀螺儀、光度和距離。 以下是資訊清單項目範例,可篩選沒有加速計的應用程式:

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

如果將此元素和描述元新增至應用程式的資訊清單,使用者就會看到 才能顯示在 Google Play 上。

只有在您的應用程式出現時,您才應該將描述元設為 android:required="true" 完全仰賴特定感應器如果您的應用程式使用感應器的某些功能, 在沒有感應器的情況下仍執行,您應在 <uses-feature> 中列出感應器 但將描述元設為 android:required="false"這可以確保 即使裝置沒有特定感應器,也可以安裝您的應用程式。這也是 專案管理的最佳做法,可協助您持續追蹤應用程式使用的功能。 請注意,如果應用程式使用特定感應器,但仍在沒有感應器的情況下執行, 則您應該在執行階段偵測感應器,並停用或啟用應用程式功能, 或適當。

感應器座標系統

一般來說,感應器架構會使用標準的 3 軸座標系統表示資料值。 對多數感應器來說,當裝置處於「裝置螢幕」時,座標系統是相對於裝置螢幕的定義 處於預設方向 (如圖 1 所示)。當裝置保持預設方向時, X 軸為水平,指向右側;Y 軸是垂直且指向上,Z 軸 指向螢幕外面。在這個系統中,畫面後方的座標 Z 的值為負數。下列感應器使用此座標系統:

圖 1. 感應器使用的座標系統 (相對於裝置) 也能使用 Google Cloud CLI 或 Compute Engine API

最需要瞭解這個座標系統的關鍵點是,軸不會 當裝置的螢幕方向變更時 (也就是感應器的座標系統) 進行切換 不會隨著裝置移動而改變這個行為與 OpenGL 座標系統

另一個值得注意的是,應用程式不得假設裝置的自然 (預設) 螢幕方向為直向。許多平板電腦裝置的自然方向為橫向。且 感應器座標系統始終取決於裝置的自然方向。

最後,如果您的應用程式與感應器資料相符,您就必須使用 判斷螢幕旋轉的 getRotation() 方法,然後使用 要對應的 remapCoordinateSystem() 方法 感應器座標與螢幕座標。即使資訊清單指定 。

注意:部分感應器和方法使用的座標系統 相對於裝置的參考框架。這些 感應器和方法會傳回資料,代表與 Google 地球。詳情請參閱 getOrientation() 方法、getRotationMatrix() 方法、方向 感應器旋轉向量 感應器

感應器頻率限制

為了保護使用者的相關機密資訊 (如果應用程式鎖定 Android 12 (API 級別 31) 以上版本,系統會對重新整理作業設下限制 特定動作感應器和位置感應器提供的資料速率。這項資料 包含裝置網路所記錄的值 加速計 陀螺儀地理磁場 感應器

重新整理頻率限制取決於您存取感應器資料的方式:

如果您的應用程式需要以更高的頻率收集動作感應器資料,您必須 宣告 HIGH_SAMPLING_RATE_SENSORS敬上 權限,如以下程式碼片段所示。否則,如果您的應用程式 在不宣告這項權限的情況下,以更高的頻率收集動作感應器資料。 發生 SecurityException

AndroidManifest.xml

<manifest ...>
    <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/>
    <application ...>
        ...
    </application>
</manifest>

存取和使用感應器的最佳做法

設計感應器時,請務必遵守下列規範: 本節這些指南是建議最佳做法,適用對象為所有使用感應器的使用者 存取感應器及取得感應器資料

只在前景收集感應器資料

在搭載 Android 9 (API 級別 28) 以上版本的裝置上,執行 背景具有下列限制:

  • 感應器如果採用 連續 加速計和陀螺儀等回報模式 事件。
  • 感應器如果採用 內容變動時單樣本 報表模式不會接收事件。

基於這些限制,最佳做法是偵測 應用程式於前景運作或 前景服務

取消註冊感應器事件監聽器

使用完感應器或感應器時,請務必取消註冊感應器的監聽器 活動暫停。如果已註冊感應器事件監聽器,並暫停其活動,感應器就會 會繼續取得資料並使用電池資源 (除非取消註冊感應器)。下列 程式碼顯示如何使用 onPause() 方法取消註冊事件監聽器:

Kotlin

private lateinit var sensorManager: SensorManager
...
override fun onPause() {
    super.onPause()
    sensorManager.unregisterListener(this)
}

Java

private SensorManager sensorManager;
...
@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

詳情請參閱 unregisterListener(SensorEventListener)

使用 Android Emulator 進行測試

Android Emulator 提供一組虛擬感應器控制項 測試加速計、環境溫度、磁力儀 例如鄰近區域和亮度等等

模擬器與執行下列項目的 Android 裝置連線: SdkControllerSensor 應用程式。請注意,此應用程式僅適用於搭載 Android 4.0 (API) 的裝置 第 14 級) 或更高等級。(如果裝置執行的是 Android 4.0,必須具有 已安裝修訂版本 2)。SdkControllerSensor 應用程式會監控 並將裝置上的感應器傳輸到模擬器模擬器 再依據從感應器接收到的新值轉換 。

您可以在 SdkControllerSensor 應用程式查看原始碼 下列位置:

$ your-android-sdk-directory/tools/apps/SdkController

如要在裝置和模擬器之間轉移資料,請按照下列步驟操作: 步驟:

  1. 確認 USB 裝置已啟用偵錯功能。
  2. 使用 USB 傳輸線將裝置連接至您開發的機器上。
  3. 在裝置上啟動 SdkControllerSensor 應用程式。
  4. 在應用程式中選取要模擬的感應器。
  5. 執行下列 adb 指令:

  6. $ adb forward tcp:1968 tcp:1968
    
  7. 啟動模擬器。現在您應該可以將轉換套用至 移動裝置來啟動模擬器

注意: 如果對 實體裝置無法轉換模擬器,請嘗試執行 再次執行步驟 5 的 adb 指令。

詳情請參閱 Android 模擬器指南

不要封鎖 onSensorChanged() 方法

感應器資料可能會頻繁變更,這表示系統可能會經常呼叫 onSensorChanged(SensorEvent) 方法。我們相信 應該盡量在 onSensorChanged(SensorEvent) 方法內執行,以免封鎖它。如果您的 應用程式要求您對資料進行篩選或減少感應器資料, 在 onSensorChanged(SensorEvent) 方法之外運作。

避免使用已淘汰的方法或感應器類型

許多方法和常數已淘汰。 尤其是 TYPE_ORIENTATION 已淘汰感應器類型。如要取得方向資料,請改用 getOrientation() 方法。同樣地, 已淘汰「TYPE_TEMPERATURE」感應器類型。應使用 請改為在裝置上使用 TYPE_AMBIENT_TEMPERATURE 感應器類型 搭載 Android 4.0 系統

使用感應器前,請先驗證感應器

嘗試從裝置擷取資料前,請務必先確認裝置上是否存在感應器。錯誤做法 會假設感應器確實存在,因為這是常用的感應器。裝置製造商是 不需要在裝置上提供任何特定感應器。

謹慎選擇感應器延遲時間

使用 registerListener() 方法註冊感應器時,請務必選擇適合 或用途感應器能以極高速率提供資料。允許系統傳送 不必要的額外資料會消耗系統資源和電池電力