Android 12 の新しい Bluetooth 権限

Android 12 では、BLUETOOTH_SCANBLUETOOTH_ADVERTISEBLUETOOTH_CONNECT 権限が導入されています。これにより、アプリは位置情報の利用許可をリクエストせずに付近のデバイスをスキャンできます。これらの権限を宣言するには、アプリが Android 12 をターゲットとする必要があります。

ペア設定と接続の操作性を細かく制御する場合は、このページに記載されている権限を使用します。

新しい権限を宣言する

アプリが Bluetooth デバイスを操作する場合は、以下を行うことを強くおすすめします。

  1. Bluetooth Low Energy(BLE)周辺機器など、アプリが Bluetooth デバイスを探す場合は、アプリのマニフェストに BLUETOOTH_SCAN 権限を追加します。
  2. アプリが現在のデバイスを他の Bluetooth デバイスから検出可能にする場合は、アプリのマニフェストに BLUETOOTH_ADVERTISE 権限を追加します。
  3. アプリがすでにペア設定されている Bluetooth デバイスと通信する場合は、アプリのマニフェストに BLUETOOTH_CONNECT 権限を追加します。
  4. Bluetooth 関連の従来の権限宣言では、android:maxSdkVersion30 に設定します。アプリの互換性に関するこのステップでは、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.
         You must add an attribute to this permission, or declare the
         ACCESS_FINE_LOCATION permission, depending on the results when you
         check location usage in your app. -->
    <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" />
    ...
</manifest>
図 1. 付近のデバイスの検出、アドバタイズ、接続を行う権限をアプリに付与するよう求めるシステム権限ダイアログ。

ユーザー向けダイアログ

BLUETOOTH_SCANBLUETOOTH_ADVERTISEBLUETOOTH_CONNECT の各権限は実行時の権限です。そのため、Bluetooth デバイスを探す、デバイスを他のデバイスから検出可能にする、またはすでにペア設定されている Bluetooth デバイスと通信する前に、アプリで明示的にユーザーの承認をリクエストする必要があります。

アプリが新しい Bluetooth 権限の少なくとも 1 つをリクエストすると、図 1 に示すように、アプリが付近のデバイスにアクセスすることを許可するよう求めるプロンプトが表示されます。

スキャン結果の使用方法を検討する

デバイスの位置情報を取得するためにアプリで Bluetooth スキャン結果を使用するかどうかについては、慎重に検討してください。どのようにするかに応じて、次のいずれかのセクションの手順を行います。

アプリが物理的な位置情報を取得しない場合

アプリが物理的な位置情報を取得しない場合は、アプリが物理的な位置情報を取得するために Bluetooth 権限を使用することはないという旨を強く主張できます。手順は次のとおりです。

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

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

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

<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" />

    <!-- 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" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- 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. -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    ...
</manifest>

アプリが物理的な位置情報を取得する場合

アプリが物理的な位置情報を取得する場合は、次のコード スニペットに示すように、アプリのマニフェストで引き続き ACCESS_FINE_LOCATION 権限を宣言する必要があります。

<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" />

    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- Required if your app derives physical location from Bluetooth
         scan results. -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    ...
</manifest>