Bluetooth の権限

アプリで Bluetooth 機能を使用するには、複数の権限を宣言する必要があります。また、アプリが Bluetooth クラシックまたは Bluetooth Low Energy(BLE)をサポートする必要があるかどうかを指定する必要があります。アプリが Bluetooth クラシックまたは BLE を必要とせず、これらのテクノロジーを利用できる場合は、実行時に可用性を確認できます。

権限を宣言する

アプリで宣言する権限のセットは、アプリがターゲットとする SDK のバージョンによって異なります。

Android 12 以降をターゲットとする

注: Android 8.0(API レベル 26)以降の場合、コンパニオン デバイス マネージャー(CDM)を使用すると、このセクションで説明する権限よりも効率的にコンパニオン デバイスに接続できます。CDM システムは、アプリに代わってペア設定 UI を提供し、位置情報の利用許可を必要としません。

ペア設定と接続エクスペリエンスをより細かく制御する場合は、このセクションで説明する権限を使用します。

Bluetooth 権限ダイアログ
付近のデバイスの検出、アドバタイズ、接続を行う権限をアプリに付与するようユーザーに求めるシステム権限ダイアログ。

Android 12(API レベル 31)以降をターゲットとするアプリの場合は、アプリのマニフェスト ファイルで次の権限を宣言します。

  1. アプリが Bluetooth デバイス(BLE 周辺機器など)を探す場合は、BLUETOOTH_SCAN 権限を宣言します。
  2. アプリが現在のデバイスを他の Bluetooth デバイスから検出できるようにする場合は、BLUETOOTH_ADVERTISE 権限を宣言します。
  3. アプリがすでにペア設定されている Bluetooth デバイスと通信する場合は、BLUETOOTH_CONNECT 権限を宣言します。
  4. Bluetooth 関連の従来の権限宣言では、android:maxSdkVersion30 に設定します。このアプリ互換性ステップを実施すると、Android 12 以降を搭載したデバイスにインストールされたときに、必要な Bluetooth 権限のみをアプリが付与できるようになります。
  5. アプリが Bluetooth のスキャン結果を使用して物理的な位置情報を取得する場合は、ACCESS_FINE_LOCATION 権限を宣言します。それ以外の場合は、アプリが物理的な位置情報を取得しないことを強くアサートできます。

BLUETOOTH_ADVERTISEBLUETOOTH_CONNECTBLUETOOTH_SCAN の各権限は実行時の権限です。したがって、Bluetooth デバイスの検索、他のデバイスからのデバイスの検出、すでにペア設定されている Bluetooth デバイスとの通信を行うには、事前にアプリでユーザーの承認をリクエストする必要があります。アプリがこれらの権限の少なくとも 1 つをリクエストすると、図 1 に示すように、アプリに付近のデバイスへのアクセスを許可するよう求めるメッセージがユーザーに表示されます。

次のコード スニペットは、Android 12 以降をターゲットとするアプリで Bluetooth 関連の権限を宣言する方法を示しています。

<manifest>
    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH"
                     android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
                     android:maxSdkVersion="30" />

    <!-- Needed only if your app looks for Bluetooth devices.
         If your app doesn't use Bluetooth scan results to derive physical
         location information, you can
         <a href="#assert-never-for-location">strongly assert that your app
         doesn't derive physical location</a>. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <!-- Needed only if your app makes the device discoverable to Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Needed only if your app communicates with already-paired Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- Needed only if your app uses Bluetooth scan results to derive physical location. -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    ...
</manifest>

アプリが物理的な位置情報を取得しないことを強く表明する

アプリが Bluetooth スキャン結果を使用して物理的な位置情報を導出しない場合は、アプリが Bluetooth 権限を使用して物理的な位置情報を導出することは決してないという強力なアサーションを行うことができます。そのための手順は次のとおりです。

  1. android:usesPermissionFlags 属性を BLUETOOTH_SCAN 権限宣言に追加し、この属性の値を neverForLocation に設定します。

  2. アプリで位置情報が必要ない場合は、アプリのマニフェストから ACCESS_FINE_LOCATION 権限を削除します。

次のコード スニペットは、アプリのマニフェスト ファイルを更新する方法を示しています。

<manifest>
    <!-- Include "neverForLocation" only if you can strongly assert that
         your app never derives physical location from Bluetooth scan results. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
                     android:usesPermissionFlags="neverForLocation" />

    <!-- Not needed if you can strongly assert that your app never derives
         physical location from Bluetooth scan results and doesn't need location
         access for any other purpose. -->
    <strike><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /></strike>
    ...
</manifest>

Android 11 以前をターゲットとする

Android 11(API レベル 30)以前をターゲットとするアプリの場合は、アプリのマニフェスト ファイルで次の権限を宣言します。

  • BLUETOOTH は、接続のリクエスト、接続の受け入れ、データ転送など、Bluetooth クラシックまたは BLE 通信を行うために必要です。
  • Android 11 以前では、ユーザーの位置情報に関する情報を収集するために Bluetooth スキャンが使用される可能性があるため、ACCESS_FINE_LOCATION が必要です。

位置情報の利用許可は実行時の権限であるため、マニフェストで宣言するとともに、実行時にこれらの権限をリクエストする必要があります。

ローカルの Bluetooth デバイスを検出する

アプリがデバイスの検出を開始する、または Bluetooth 設定を操作できるようにするには、BLUETOOTH_ADMIN 権限を宣言する必要があります。ほとんどのアプリでは、ローカルの Bluetooth デバイスを検出する機能のみを目的としてこの権限が必要になります。この権限によって付与されるその他の機能は使用しないでください。ただし、アプリがユーザーのリクエストに応じて Bluetooth 設定を変更する「電源マネージャー」機能を使用している場合を除きます。アプリ マニフェスト ファイルで権限を宣言します。たとえば、以下の場合です。

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

アプリがサービスをサポートしており、Android 10(API レベル 29)または Android 11 で実行できる場合は、Bluetooth デバイスを検出するための ACCESS_BACKGROUND_LOCATION 権限も宣言する必要があります。この要件の詳細については、バックグラウンドで位置情報にアクセスするをご覧ください。

次のコード スニペットは、ACCESS_BACKGROUND_LOCATION 権限を宣言する方法を示しています。

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

アプリの権限の宣言について詳しくは、<uses-permission> のリファレンスをご覧ください。

Bluetooth 機能の使用を指定する

Bluetooth がアプリに不可欠な場合は、この要件を示すフラグをマニフェスト ファイルに追加できます。<uses-feature> 要素を使用すると、アプリで使用するハードウェアのタイプと、そのハードウェアが必須かどうかを指定できます。

次の例は、アプリに Bluetooth クラシックが必要であることを示す方法を示しています。

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

アプリが Bluetooth Low Energy を使用している場合は、以下を使用できます。

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

その機能がアプリに必要な場合、Google Play ストアは、その機能がないデバイスのユーザーにはアプリを非表示にします。このため、必須属性を true に設定できるのは、この機能がないとアプリが動作しない場合のみです。

実行時に機能の可用性を確認する

クラシック Bluetooth または BLE をサポートしていないデバイスでアプリを使用できるようにするには、アプリのマニフェストに <uses-feature> 要素を追加し、required="false" を設定する必要があります。その後、PackageManager.hasSystemFeature() を使用して、実行時に機能の可用性を判断できます。

Kotlin

// Check to see if the Bluetooth classic feature is available.
val bluetoothAvailable = packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)

// Check to see if the BLE feature is available.
val bluetoothLEAvailable = packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)

Java

// Use this check to determine whether Bluetooth classic is supported on the device.
// Then you can selectively disable BLE-related features.
boolean bluetoothAvailable = getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);

// Use this check to determine whether BLE is supported on the device. Then
// you can selectively disable BLE-related features.
boolean bluetoothLEAvailable = getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);