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. アプリが BLE 周辺機器などの Bluetooth デバイスを検索する場合は、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);