블루투스 권한

앱에서 블루투스 기능을 사용하려면 여러 권한을 선언해야 합니다. 또한 앱에 기존 블루투스 또는 저전력 블루투스 (BLE) 지원이 필요한지 지정해야 합니다. 앱에 블루투스 기본 또는 BLE가 필요하지 않지만 이러한 기술의 이점을 누릴 수 있는 경우 런타임에 사용 가능 여부를 확인할 수 있습니다.

권한 선언

앱에서 선언하는 권한 집합은 앱의 타겟 SDK 버전에 따라 다릅니다.

Android 12 이상 타겟팅

참고: Android 8.0 (API 수준 26) 이상에서 부속 기기 관리도구 (CDM)는 이 섹션에서 설명하는 권한에 비해 호환 기기에 연결하는 더 간편한 방법을 제공합니다. CDM 시스템은 앱을 대신해 페어링 UI를 제공하고 위치 정보 액세스 권한이 필요하지 않습니다.

페어링 및 연결 환경을 더 세부적으로 제어하려면 이 섹션에 설명된 권한을 사용하세요.

블루투스 권한 대화상자
사용자에게 근처 기기를 검색하고 광고하며 연결하는 권한을 앱에 부여하라고 요청하는 시스템 권한 대화상자

앱이 Android 12 (API 수준 31) 이상을 타겟팅하는 경우 앱의 매니페스트 파일에서 다음 권한을 선언합니다.

  1. 앱이 BLE 주변기기와 같은 블루투스 기기를 검색하면 BLUETOOTH_SCAN 권한을 선언합니다.
  2. 앱이 현재 기기를 다른 블루투스 기기에서 검색할 수 있도록 하려는 경우 BLUETOOTH_ADVERTISE 권한을 선언합니다.
  3. 앱이 이미 페어링된 블루투스 기기와 통신한다면 BLUETOOTH_CONNECT 권한을 선언합니다.
  4. 기존 블루투스 관련 권한 선언의 경우 android:maxSdkVersion30으로 설정합니다. 이 앱 호환성 단계를 통해 시스템은 Android 12 이상을 실행하는 기기에 설치할 때 필요한 블루투스 권한만 앱에 부여할 수 있습니다.
  5. 앱이 블루투스 검색 결과를 사용하여 실제 위치를 파생하는 경우 ACCESS_FINE_LOCATION 권한을 선언합니다. 또는 앱이 실제 위치를 파생하지 않는다고 강력하게 어설션할 수 있습니다.

BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT, BLUETOOTH_SCAN 권한은 런타임 권한입니다. 따라서 블루투스 기기를 찾거나 기기를 다른 기기에서 검색할 수 있게 하거나 이미 페어링된 블루투스 기기와 통신하려면 앱에서 명시적으로 사용자 승인을 요청해야 합니다. 앱이 이러한 권한 중 하나 이상을 요청하면 시스템은 사용자에게 앱이 근처 기기에 액세스하도록 허용하라는 메시지를 표시합니다(그림 1 참고).

다음 코드 스니펫은 앱이 Android 12 이상을 타겟팅하는 경우 앱에서 블루투스 관련 권한을 선언하는 방법을 보여줍니다.

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

앱이 물리적 위치를 얻지 않는다고 강력하게 어설션합니다

앱이 블루투스 검색 결과를 사용하여 실제 위치를 파생하지 않으면 앱이 블루투스 권한을 사용하여 실제 위치를 파생하지 않는다는 강력한 어설션을 만들 수 있습니다. 그러려면 다음 단계를 완료하세요.

  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는 연결 요청, 연결 수락, 데이터 전송과 같은 블루투스 클래식 또는 BLE 통신을 실행하는 데 필요합니다.
  • Android 11 이하에서는 블루투스 스캔을 사용하여 사용자 위치 정보를 수집할 수 있으므로 ACCESS_FINE_LOCATION가 필요합니다.

위치 정보 액세스 권한은 런타임 권한이므로 매니페스트에서 선언하는 것과 함께 런타임 시 이러한 권한을 요청해야 합니다.

로컬 블루투스 기기 검색

앱에서 기기 검색을 시작하거나 블루투스 설정을 조작하려면 BLUETOOTH_ADMIN 권한을 선언해야 합니다. 대부분의 앱은 로컬 블루투스 기기를 검색하는 기능에만 이 권한이 필요합니다. 앱이 사용자 요청 시 블루투스 설정을 수정하는 '전원 관리자'가 아닌 이상 이 권한이 부여하는 다른 기능을 사용하지 마세요. 앱 매니페스트 파일에서 권한을 선언합니다. 예를 들면 다음과 같습니다.

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

앱이 서비스를 지원하고 Android 10 (API 수준 29) 또는 Android 11에서 실행할 수 있다면 블루투스 기기를 검색하기 위한 ACCESS_BACKGROUND_LOCATION 권한도 선언해야 합니다. 이 요구사항에 관한 자세한 내용은 백그라운드에서 위치 액세스를 참고하세요.

다음 코드 스니펫은 ACCESS_BACKGROUND_LOCATION 권한을 선언하는 방법을 보여줍니다.

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

앱 권한 선언에 관한 자세한 내용은 <uses-permission> 참조를 확인하세요.

블루투스 기능 사용 지정

블루투스가 앱의 핵심적인 부분인 경우 매니페스트 파일에 이 요구사항을 나타내는 플래그를 추가할 수 있습니다. <uses-feature> 요소를 사용하면 앱에서 사용하는 하드웨어 유형과 필수 여부를 지정할 수 있습니다.

이 예에서는 앱에 블루투스 클래식이 필요하다고 표시하는 방법을 보여줍니다.

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

앱에서 저전력 블루투스를 사용하는 경우 다음을 사용할 수 있습니다.

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

앱에 이 기능이 필요하다고 선언하면 Google Play 스토어에서는 이러한 기능이 없는 기기의 사용자에게 앱을 숨깁니다. 따라서 이 기능 없이는 앱이 작동할 수 없는 경우에만 필수 속성을 true로 설정해야 합니다.

런타임에 기능 사용 가능 여부 확인

기본 블루투스 또는 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);