センサーの概要

ほとんどの Android デバイスには、動き、向き、 さまざまな環境条件下で使用してください。これらのセンサーは、非常に高い精度で元データを 精度が高く、デバイスの 3 次元の動きや、 デバイスの周囲の環境の変化を監視したい場合などです。たとえばゲームでは、重力センサーでの読み取り値をトラッキングすることで、ユーザーの複雑な操作や動き(ティルト、シェイク、回転、スウィングなど)を推定できます。また、天気情報アプリで温度センサーと湿度センサーを使って露点温度を計算したり、旅行アプリで地磁気センサーと加速度計を使ってコンパスの方位磁針を表示したりできます。

Android プラットフォームは、大きく分けて次の 3 つのカテゴリのセンサーをサポートしています。

  • モーション センサー

    3 軸方向の加速力や回転力を測定するためのセンサーです。このカテゴリのセンサーには、加速度計、重力センサー、ジャイロスコープ、回転ベクトル センサーなどがあります。

  • 環境センサー

    周囲の気温など、さまざまな環境パラメータを測定するセンサーです 気圧、照明、湿度などですこのカテゴリには気圧計、光度計、 体温計。

  • 位置センサー

    デバイスの物理的な位置を測定するためのセンサーです。このカテゴリに含まれるもの 方向センサーや磁力計です

Android センサー フレームワークを使用することにより、そのデバイスで利用可能なセンサーから測定データを取得できます。このセンサー フレームワークには、さまざまなセンサー関連タスクに役立つクラスとインターフェースが複数用意されています。たとえば、このセンサー フレームワークを使用して次のことを行えます。

  • そのデバイスで使用できるセンサーを特定する。
  • 個々のセンサーの性能(最大測定範囲、メーカー、所要電力、解像度など)を特定する。
  • センサーから測定データを取得する。また、測定データを取得する際の最低速度を定義する。
  • センサーの変化をモニタリングするセンサー イベント リスナーの登録や登録解除を行う。

このトピックでは、Android プラットフォームで使用可能なセンサーの概要について説明します。 また、Android センサー フレームワークの概要についても説明します。

センサーの概要

Android センサー フレームワークでは、さまざまなタイプのセンサーを利用できます。センサーには、ハードウェアベースのものと、ソフトウェアベースのものがあります。ハードウェアベース センサーは、物理コンポーネントとして構築されている スマートフォンやタブレット デバイスに変換できます。特定の環境特性(加速度、地磁気強度、角度変化など)を直接測定することでデータを導出します。ソフトウェアベース センサーは、ハードウェアベース センサーを模したもので、物理的なデバイスではありません。1 つまたは複数のハードウェアベース センサーからデータを取得するもので、仮想センサーまたは合成センサーとも呼ばれます。ソフトウェアベース センサーの例としては、リニア加速度センサーや重力センサーが挙げられます。表 1 に、Android でサポートされているセンサーの概要を示します。 できます。

すべてのタイプのセンサーを備えた Android 搭載デバイスはまれにしかありません。たとえば、ほとんどのスマートフォン デバイスや タブレットには加速度計と磁力計が搭載されていますが、 気圧計や温度計を使ってみましょう。また、1 つのデバイスに同じタイプのセンサーが複数搭載されていることもあります。たとえば、1 つのデバイスに、測定範囲の異なる 2 つの重力センサーが搭載されている場合があります。

表 1. Android プラットフォームでサポートされているセンサータイプ

センサー 種類 説明 一般的な活用法
TYPE_ACCELEROMETER ハードウェア デバイスにかかる 3 本の物理軸(x、y、z)方向の加速力(重力も含む)を m/s2 単位で測定します。 動きの検出(シェイク、ティルトなど)。
TYPE_AMBIENT_TEMPERATURE ハードウェア 周囲の室温を摂氏(°C)単位で測定します。下記の注をご覧ください。 気温のモニタリング。
TYPE_GRAVITY ソフトウェアまたはハードウェア デバイスにかかる 3 本の物理軸(x、y、z)方向の重力を m/s2 単位で測定します。 動きの検出(シェイク、ティルトなど)。
TYPE_GYROSCOPE ハードウェア 3 つのデバイスの回転速度をそれぞれ rad/s 単位で測定します 物理軸 (x、y、z)です。 回転の検出(スピン、ターンなど)。
TYPE_LIGHT ハードウェア 周囲光レベル(照度)をルクス単位で測定します。 画面の明るさの制御。
TYPE_LINEAR_ACCELERATION ソフトウェアまたはハードウェア デバイスにかかる 3 本の物理軸(x、y、z)方向の加速力(重力を除く)を m/s2 単位で測定します。 1 軸方向の加速度のモニタリング。
TYPE_MAGNETIC_FIELD ハードウェア 地球の 3 つの物理軸(x、y、z)の周囲地磁気を測定 μT。 コンパスの作成。
TYPE_ORIENTATION ソフトウェア 3 つの物理軸(x、y、z)すべてに対するデバイスの回転角度を測定します。 API レベル 3 以降では、重力センサーと地磁気センサーを getRotationMatrix() メソッドと組み合わせることで、デバイスの勾配行列と回転行列を求めることができます。 デバイスの姿勢の特定。
TYPE_PRESSURE ハードウェア 周囲の気圧をヘクトパスカル(ミリバール)単位で測定します。 気圧変化のモニタリング。
TYPE_PROXIMITY ハードウェア 対象物のビュー画面に対する物体の近さを cm 単位で測定します できます。このセンサーは通常、ハンドセットが 向上します 通話中のスマートフォンの位置。
TYPE_RELATIVE_HUMIDITY ハードウェア 周囲の相対湿度を百分率(%)で測定します。 露点温度、絶対湿度、相対湿度のモニタリング。
TYPE_ROTATION_VECTOR ソフトウェアまたはハードウェア デバイスの回転ベクトルの 3 要素を使用してデバイスの向きを測定します。 動きの検出と回転の検出。
TYPE_TEMPERATURE ハードウェア デバイスの温度を摂氏(°C)単位で測定します。デバイスによって実装方法が異なります。このセンサーは、API レベル 14 で TYPE_AMBIENT_TEMPERATURE センサーに置き換えられました。 温度のモニタリング。

センサー フレームワーク

Android センサー フレームワークを使用することにより、上記のセンサーから測定データを取得できます。センサー フレームワークは android.hardware パッケージの一部であり、次のものが含まれています。 クラスとインターフェース:

SensorManager
このクラスを使用して、センサー サービスのインスタンスを作成できます。このクラスには、センサーの利用とリストアップ、センサー イベント リスナーの登録と登録解除、向き情報の取得のための、さまざまなメソッドが用意されています。このクラスには、いくつかのセンサー定数も用意されています。 センサーの精度の報告、データ取得率の設定、センサーの調整に使用されます。
Sensor
このクラスを使用して、特定のセンサーのインスタンスを作成できます。このクラスには、 センサーの機能を判断するためのメソッドも用意しています。
SensorEvent
システムはこのクラスを使用して、センサー イベント オブジェクトを作成します。このオブジェクトは、 トリガーされます。センサー イベント オブジェクトには、センサーの元データ、 イベントを生成したセンサーのタイプ、データの精度、イベントのタイムスタンプ
SensorEventListener
このインターフェースを使用して、センサー値やセンサー精度が変化したときに通知(センサー イベント)を受け取るための、2 つのコールバック メソッドを作成できます。

通常のアプリでは、上記のセンサー関連 API を使用して、次の 2 つの基本的なタスクを行います。

  • センサーとセンサー性能の特定

    特定のタイプや性能のセンサーに依存する機能を備えたアプリの場合、ランタイムにセンサーやセンサー性能を判別できると便利です。たとえば、デバイス上に存在するセンサーをすべて特定して、存在しないセンサーを必要とするアプリ機能は無効にできます。また、同じタイプのセンサーをすべて特定して、その中からアプリに最適なパフォーマンスをもたらすセンサーを選択することもできます。

  • センサー イベントのモニタリング

    センサーから測定データを取得するには、センサー イベントをモニタリングします。センサー イベントは毎回発生 センサーが測定中のパラメータの変化を検出したときセンサー イベントからは、イベントをトリガーしたセンサーの名前、イベントのタイムスタンプ、イベントの精度、イベントをトリガーした測定データ、の 4 つの情報を取得できます。

センサー対応状況

利用可能なセンサーは、デバイスによっても、Android のバージョンによっても異なります。これは、Android センサーが数回のプラットフォーム リリースにわたって導入されてきたためです。たとえば、Android 1.5(API レベル 3)で多くのセンサーが導入されましたが、 は実装されず、Android 2.3(API レベル 9)までは使用できませんでした。Android 2.3(API レベル 9)や Android 4.0(API レベル 14)で新たに導入されたセンサーもあります。2 本 センサーのサポートは終了し、より優れた新しいセンサーに置き換えられました。

表 2 に、プラットフォームごとのセンサー対応状況をまとめます。センサーが変更されたプラットフォームは 4 種類のため、ここにはそれらのみを示します。センサーは 非推奨と表示されていても、後続のプラットフォームで使用できます(ただし、 センサーが存在するデバイス)に関する記述が、Android の上位互換性ポリシーに準拠しています。

表 2. プラットフォームごとのセンサー対応状況

センサー Android 4.0
(API Level 14)
Android 2.3
(API Level 9)
Android 2.2
(API Level 8)
Android 1.5
(API Level 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 には、各センサーの性能(最大測定範囲、解像度、所要電力など)を判定するためのメソッドも用意されています。

デバイス上のセンサーを特定するには、まずセンサー サービスへの参照を取得する必要があります。そのためには、次の手順で SensorManager クラスのインスタンスを作成します。 getSystemService() メソッドを呼び出して、 SENSOR_SERVICE 引数内で指定します。例:

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

次に、 getSensorList() メソッドを使用し、TYPE_ALL 定数を使用します。例:

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

特定のタイプのセンサーをリストアップしたい場合は、定数 TYPE_ALL の代わりに別の定数(TYPE_GYROSCOPETYPE_LINEAR_ACCELERATIONTYPE_GRAVITY など)を使用します。

また、getDefaultSensor() メソッドを使用してタイプを渡すことで、デバイスに特定の種類のセンサーが存在するかどうかを判断することもできます。 定数を指定します。デバイスに特定のタイプのセンサーが複数ある場合は、 センサーはデフォルトのセンサーとして指定する必要があります。特定の環境にデフォルトのセンサーが存在しない場合 タイプのセンサーの場合、メソッド呼び出しは null を返します。つまり、デバイスにそのタイプのセンサーは搭載されていません。 センサー。たとえば、次のコードでは、デバイス上に磁力計があるかどうかを確認しています。

KotlinJava
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.
}
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() メソッドを使用すれば、センサーの所要電力を取得できます。

センサーのメーカーやバージョンに応じてアプリを最適化する場合に特に役立つパブリック メソッドが 2 つあります。たとえば、アプリケーションで 傾斜やシェイクなどのユーザー ジェスチャーをモニタリングする必要がある場合は、データ フィルタリング セットを 1 つ作成できます。 特定のベンダーの重力センサーを搭載した新しいデバイス向けのルールと最適化や、 重力センサーがなく重力センサーがなく、 加速度計のみが必要です次のコードサンプルは、getVendor() メソッドと getVersion() メソッドを使用して、以下を行う方法を示しています。 できます。このサンプルでは、ベンダーとして Google LLC とリストされている重力センサーを探します。 バージョン番号は 3 です。このセンサーがデバイス上にない場合は、加速度計を使用します。

KotlinJava
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
    }
}
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.
    }
}

もう 1 つの便利なメソッドは getMinDelay() メソッドです。 センサーがデータを検知するために使用できる最小時間間隔(マイクロ秒単位)を返します。getMinDelay() メソッドでゼロ以外の値が返されるセンサーを、ストリーミング センサーといいます。ストリーミング センサーは定期的にデータを検知する機能であり、Android 2.3(API)で導入されました。 レベル 9)。getMinDelay() メソッドを呼び出したときにセンサーがゼロを返した場合は、 センサーは、データに変化があったときにのみデータをレポートするため、ストリーミング センサーではありません。 パラメータを指定します。

この getMinDelay() メソッドが有用なのは、センサーによるデータ測定の最大速度がわかるからです。アプリの特定の機能で高速なデータ測定やストリーミング センサーが必要な場合、このメソッドを使用すればセンサーが要件を満たしているかどうかがわかり、その結果に応じて、該当のアプリ機能を有効にしたり無効にしたりできます。

注意: センサーの最大データ取得速度は、 センサー・フレームワークがセンサー・データをアプリケーションに配信する速度が必要です。センサー フレームワークからのデータ配信はセンサー イベントを介して行われますが、アプリ側でセンサー イベントを受信する速度には複数の要因が影響するためです。詳細については、センサー イベントのモニタリングをご覧ください。

センサー イベントのモニタリング

センサーの素データをモニタリングするには、 SensorEventListener インターフェース: onAccuracyChanged()onSensorChanged()。Android システムは これらのメソッドを使用する必要があります。

  • センサーの精度が変化する。

    この場合、システムは onAccuracyChanged() メソッドを呼び出し、 変更された Sensor オブジェクトへの参照と、 センサーの新たな精度です精度は、次の 4 つのステータス定数のいずれかで表されます。 SENSOR_STATUS_ACCURACY_LOW, SENSOR_STATUS_ACCURACY_MEDIUM, SENSOR_STATUS_ACCURACY_HIGH, または SENSOR_STATUS_UNRELIABLE

  • センサーから新しい値が報告された場合

    この場合、システムは onSensorChanged() メソッドを呼び出し、以下を提供します。 SensorEvent オブジェクト。SensorEvent オブジェクトには、データの精度、データを生成したセンサー、データが生成されたときのタイムスタンプ、センサーにより新たに記録されたデータといった、最新のセンサーデータに関する情報が含まれています。

次のコードは、onSensorChanged() メソッドを使用してデータをモニタリングする方法を示しています。 光センサーが反応しますこの例では、未加工のセンサーデータを TextView に表示します。 つまり main.xml ファイルで sensor_data として定義されています。

KotlinJava
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)
    }
}
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);
    }
}

この例では、デフォルトのデータ遅延(SENSOR_DELAY_NORMAL)を、registerListener() メソッドが呼び出されたときに指定しています。データ 遅延(サンプリング レート)は、センサー イベントがアプリケーションに送信される間隔を制御します。 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 搭載デバイスを任意のセンサー構成にできます。その結果、多様なセンサーを備えたさまざまな構成のデバイスが存在しえます。アプリで特定のタイプのセンサーを必要とする場合は、アプリを正常に動作させるために、そのセンサーがデバイスに存在することを確認する必要があります。

デバイスに特定のセンサーが存在することを確認するには、次の 2 つの方法があります。

  • ランタイムにセンサーを検出し、その結果に応じてアプリの機能を有効または無効にする。
  • Google Play フィルタを使用して、特定のセンサー構成のデバイスのみをターゲットにする。

それぞれの方法について、以下のセクションで説明します。

ランタイムにおけるセンサーの検出

アプリで特定のタイプのセンサーを使用しているものの必須ではない場合は、センサー フレームワークを使用してランタイムにセンサーを検出し、必要に応じてアプリの機能を有効または無効にします。たとえば、ナビゲーション アプリは温度センサーを使用して、 圧力センサー、GPS センサー、地磁気センサー(温度、気圧を表示) 気圧、位置、コンパス方位などですデバイスに圧力センサーがない場合は、センサー フレームワークを使用してランタイムにそのことを検出し、気圧を表示する UI の部分を無効にできます。たとえば、次のコードでは、デバイスに圧力センサーがあるかどうかを確認しています。

KotlinJava
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.
}
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. センサーで使用される座標系(デバイスを基準とする) API

この座標系を理解するうえで最も重要な点は、軸は デバイスの画面の向き(センサーの座標系)が変更されたときにスワップされます。 デバイスが移動しても変化しません。この動作は OpenGL の動作と同じです。 座標系です。

理解しておくべきもう一つのポイントは、アプリは、デバイスの正常な動作を前提としないことです。 (デフォルト)向きは縦向きです。多くのタブレット デバイスでは、自然な向きは横向きになっています。そして センサー座標系は、常にデバイスの自然な向きに基づいています。

最後に、アプリでセンサーデータを画面表示と一致させる場合は、getRotation() メソッドで画面の回転を判定し、その後 remapCoordinateSystem() メソッドでセンサーの座標を画面の座標にマッピングする必要があります。これは、マニフェストで 縦向きのみのディスプレイです。

注: 一部のセンサーやメソッドでは、 (デバイスの参照フレームではなく)世界の参照フレームを基準とします。このようなセンサーやメソッドからは、地球を基準にしたデバイスの動きや位置のデータが返されます。詳細については、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() メソッドを使用してリスナーの登録を解除する方法を示しています。

KotlinJava
private lateinit var sensorManager: SensorManager
...
override fun onPause() {
    super.onPause()
    sensorManager.unregisterListener(this)
}
private SensorManager sensorManager;
...
@Override
protected void onPause() {
    super.onPause();
    sensorManager.unregisterListener(this);
}

詳しくは unregisterListener(SensorEventListener) をご覧ください。

Android Emulator でテストする

Android Emulator には、仮想センサー コントロールのセットが用意されており、 加速度計、周囲温度、磁力計、 近接、光などを遮断します。

Android Emulator では、SdkControllerSensor アプリが実行されている Android デバイスとの接続が使用されます。なお、このアプリは Android 4.0(API レベル 14)以上のデバイスでのみ利用できます(Android 4.0 搭載デバイスの場合は、Revision 2 がインストールされている必要があります)。SdkControllerSensor アプリは、 エミュレータに送信します。Android Emulator は、デバイス上のセンサーから送られた最新の値に基づいて更新されます。

SdkControllerSensor アプリのソースコードは、次の場所で確認できます。

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

デバイスとエミュレータの間でデータを転送するには、次の手順を実施します。 手順:

  1. デバイス側で USB デバッグが有効になっていることを確認します。
  2. USB ケーブルを使用してデバイスを開発用マシンに接続します。
  3. デバイス側で SdkControllerSensor アプリを起動します。
  4. SdkControllerSensor アプリで、エミュレートするセンサーを選択します。
  5. 次の adb コマンドを実行します。

  6. $ adb forward tcp:1968 tcp:1968
    
  7. Android Emulator を起動します。ここまでで、作成したテーブルに エミュレータを使用できます。

注: エミュレータが変換されない場合は、次を実行してみてください。 adb コマンドを再度実行します。

詳細については、Android Emulator のガイドをご覧ください。

onSensorChanged() メソッドをブロックしない

センサーデータは高速に変化する可能性があります。つまり、システムによって onSensorChanged(SensorEvent) メソッドが頻繁に呼び出される可能性があります。ベストプラクティスとして onSensorChanged(SensorEvent) メソッド内で実行する処理をできる限り少なくして、ブロックされないようにします。アプリでセンサーデータのフィルタや換算が必要な場合は、onSensorChanged(SensorEvent) メソッドの外側でその処理を行います。

サポートが終了したメソッドやセンサータイプを使用しない

いくつかのメソッドや定数はサポートが終了しています。具体的には、TYPE_ORIENTATION センサータイプはサポートが終了しています。向きのデータを取得するには、代わりに getOrientation() メソッドを使用します。同様に TYPE_TEMPERATURE センサータイプのサポートが終了しました。Android 4.0 を搭載しているデバイスでは、代わりに TYPE_AMBIENT_TEMPERATURE センサータイプを使用します。

センサーを使用する前に確認する

センサーからデータを取得しようとする前に、必ずそのセンサーがデバイス上に存在することを確認します。すべきでないこと センサーが頻繁に使用されるという理由だけで、センサーが存在することを前提とします。デバイス メーカーは デバイスに特定のセンサーを用意する必要はありません。

センサーの遅延は慎重に選択する

registerListener() メソッドでセンサーを登録する場合は、 理解することが重要です。センサーからは、極めて高速にデータが提供される可能性があります。不要なデータまで配信されるようにすると、システム リソースや電池を無駄に消費することになります。