728x90
반응형
SMALL
Android 12에서는 새로운 블루투스 권한이 도입 되어, 대응할 필요가 있게 되었습니다.
이에 아래 공식문서를 참조하여 대응하였습니다.
정리하자면, Android 12부터는 BLUETOOTH_SCAN, BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT 권한이 도입되었는데,
- BLUETOOTH_SCAN : 주변 블루투스 기기를 검색하는 경우
- BLUETOOTH_ADVERTISE: 현재 기기를 다른 블루투스 기기에서 검색할 수 있도록 하는 경우
- BLUETOOTH_CONNECT: 이미 페어링된 기기와 통신해야할 경우
에 추가되어야 하고,
API 별로 Scan, Connect에 필요한 런타임 퍼미션을 정리하자면 다음과 같습니다.
Scan
API | runtime permissions |
18~22 | 런타임 퍼미션 필요 없음 |
23~28 | 아래 둘중 하나 필요 - android.permission.ACCESS_COARSE_LOCATION - android.permission.ACCESS_FINE_LOCATION |
29~30 | - android.permission.ACCESS_FINE_LOCATION * 만약 백그라운드에서 스캔이 수행되어야 할 경우 필요 - android.permission.ACCESS_BACKGROUND_LOCATION |
31~ | - android.permission.BLUETOOTH_SCAN * 스캔시 유저의 위치를 포함해야 할 경우 필요 - android.permission.ACCESS_FINE_LOCATION |
Connect
API | runtime permissions |
18~30 | 런타임 퍼미션 필요 없음 |
31~ | - android.permission.BLUETOOTH_CONNECT |
위의 사항을 참고하여, 다음과 같이 권한을 작성하였습니다.
- AndroidManifest.xml
<!-- 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" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- MainActivity.kt
val PERMISSIONS = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION
)
val PERMISSIONS_S_ABOVE = arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.ACCESS_FINE_LOCATION
)
val REQUEST_ALL_PERMISSION = 2
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
if (!hasPermissions(this, PERMISSIONS_S_ABOVE)) {
requestPermissions(PERMISSIONS_S_ABOVE, REQUEST_ALL_PERMISSION)
}
}else{
if (!hasPermissions(this, PERMISSIONS)) {
requestPermissions(PERMISSIONS, REQUEST_ALL_PERMISSION)
}
}
...
...
private fun hasPermissions(context: Context, permissions: Array<String>): Boolean {
for (permission in permissions) {
if (ActivityCompat.checkSelfPermission(context, permission)
!= PackageManager.PERMISSION_GRANTED
) {
return false
}
}
return true
}
...
// Permission check
@RequiresApi(Build.VERSION_CODES.M)
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String?>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
REQUEST_ALL_PERMISSION -> {
// If request is cancelled, the result arrays are empty.
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permissions granted!", Toast.LENGTH_SHORT).show()
} else {
requestPermissions(permissions, REQUEST_ALL_PERMISSION)
Toast.makeText(this, "Permissions must be granted", Toast.LENGTH_SHORT).show()
}
}
}
}
공식문서를 보면, 스캔에 유저의 실제 위치를 파생 하지 않을경우, 할 경우 나누어 설명이 되어있으므로, 참고하면 좋겠습니다.
728x90
반응형
LIST