Android12(API 31) Bluetooth 관련 대응

Heathcliff·2022년 8월 16일

Android 12 Bluetooth 퍼미션 관련 변경점

안드로이드 개발자 사이트에서 Android12 Bluetooth 관련 변경점들이 추가되었다. 자세한 내용은 아래의 링크를 참조하자.

https://developer.android.com/about/versions/12/features/bluetooth-permissions?hl=ko#user-facing-dialog

요약하자면 Android12 이상의 기기 및 targetSDKversion 31 이상의 앱에서는 블르투스 기능을 사용하기 위해 아래의 세가지 런타임 퍼미션을 승인 받아야 한다.

  • BLUETOOTH_SCAN
  • BLUETOOTH_ADVERTISE
  • BLUETOOTH_CONNECT

BLUETOOTH_SCAN은 앱이 블루투스 주변기기를 스캔하는 경우 필요한 권한이다.
BLUETOOTH_ADVERTISE은 현재 기기를 다른 기기가 스캔하여 찾을 수 있도록 Advertising 하는 경우 필요한 권한이다.
BLUETOOTH_CONNECT은 블루투스 기기화 연결하여 통신할 경우 필요한 권한이다.


메니페스트에 Permission 선언


<!-- API 31(S) 이상 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
	android:usesPermissionFlags="neverForLocation"
	tools:targetApi="s" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    
<!-- 31미만 23(M) 이상 -->
<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.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

여기서 주목할 점은 31미만 버전에서 위치 관련 ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION가 필요한 이유는 해당 권한이 허용되자 않으면 Bluetooth Scan을 할 수 없기 때문이다.

그리고 BLUETOOTH_SCAN 퍼미션에 android:usesPermissionFlags="neverForLocation" 속성을 넣었는데 이 속성이 없으면 실제로 기기가 스캔이 되지 않고 위치권한을 추가적으로 받아야 스캔이 되는것을 확인했다.

그밖의 BLUETOOTH/BLUETOOTH_ADMIN 퍼미션은 BluetoothManager 등 블루투스 관련 기능을 위한 권한이다.


런타임 퍼미션 요청 코드

// 위치 관련 퍼미션
private val PERMISSIONS_LOCATION = arrayOf(
	Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION)

// 블루투스 관련 펴미션
@RequiresApi(Build.VERSION_CODES.S)
private val PERMISSIONS_BLUETOOTH = arrayOf(
	Manifest.permission.BLUETOOTH_CONNECT,
    Manifest.permission.BLUETOOTH_ADVERTISE,
    Manifest.permission.BLUETOOTH_SCAN)

// Activity Result Launcher
private lateinit var activityResultLauncherLocationPermissions: ActivityResultLauncher<Array<String>>   // 위치 관련 퍼미션
private lateinit var activityResultLauncherBluetoothPermissions: ActivityResultLauncher<Array<String>>  // 블루투스 관련 퍼미션

// Activity Result Launcher 초기화
private fun initActivityResultLauncher() {

	// 위치 정보 퍼미션
    activityResultLauncherLocationPermissions = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result: MutableMap<String,Boolean> ->

		val deniedList: List<String> = result.filter {
        	!it.value
		}.map {
			it.key
		}

		// 퍼미션 허용 여부
        if (deniedList.isEmpty()) {

			checkEnableBluetooth()

		} else {

			showPopupPermissionsDenied()
		}
	}

	// 블루투스 퍼미션
	activityResultLauncherBluetoothPermissions = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result: MutableMap<String,Boolean> ->

		val deniedList: List<String> = result.filter {
    		!it.value
		}.map {
			it.key
		}

		// 퍼미션 허용 여부
		if (deniedList.isEmpty()) {

			checkEnableBluetooth()

		} else {

			showPopupPermissionsDenied()
		}
	}
}

/**
* 권한 체크
*/
private fun checkPermission() {

	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {

		activityResultLauncherBluetoothPermissions.launch(PERMISSIONS_BLUETOOTH)

	} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

		activityResultLauncherLocationPermissions.launch(PERMISSIONS_LOCATION)

	} else {

		checkEnableBluetooth()
    }
}

위 내용은 블루투스 관련 퍼미션들을 정의하고 SDK 버전에 따라서 다른 권한을 요청하는 코드이다.

API 31 이상에서는 BLUETOOTH 관련 권한들을 요청하고
31미만인 경우에는 위치관련 권한을 요청한다.

android.permission.BLUETOOTH_ADMIN
android.permission.BLUETOOTH
Androidmanifest에 정의한 위 두 퍼미션은 런타임 퍼미션이 아니므로 따로 권한요청을 할 필요가 없다.

profile
Android Developer

0개의 댓글