Android Permission 정책이 계속해서 바뀌기 때문에 조금이라도 쉽게 권한 설정 할 수 있도록 모듈화 했다.
ps. 원래 권한 설정이 길고, 할게 많다
/* Utile.kt */
fun showSnackBar(view: View, message: String, navigation: () -> Unit) {
Snackbar.make(
view,
message,
Snackbar.LENGTH_INDEFINITE
).apply {
setAction(content.getString("확인")) {
navigation.invoke()
}
show()
}
}
/* Config.kt */
object Config {
// 어떤 권한 설정 요청인지 판단하기 위한 변수
const val REQUEST_CODE_BLUETOOTH = 111
const val REQUEST_CODE_ACCESS = 222
const val REQUEST_CODE_STORAGE = 333
}
}
/* SampleActivity.kt */
// 처음 권한 요청을 시작할 권한의 판단 변수
private var permissionCheckNow = REQUEST_CODE_BLUETOOTH
private fun accessPermission() { ... }
private fun storagePermission() { ... }
// 예시로 bluetoothPermission
private fun bluetoothPermission() {
with(Build.VERSION.SDK_INT) {
when {
// 권한마다 AOS 버전별로 추가로 선언 해야 하는 권한이 있다.
this >= Build.VERSION_CODES.S -> {
if (checkSelfPermission(BLUETOOTH_CONNECT) != PERMISSION_GRANTED ||
checkSelfPermission(BLUETOOTH_SCAN) != PERMISSION_GRANTED ||
checkSelfPermission(BLUETOOTH_ADVERTISE) != PERMISSION_GRANTED ||
) {
// onRequestPermissionsResult로 이동
ActivityCompat.requestPermission(
this@SampleActivity,
arrayOf(
BLUETOOTH_CONNECT,
BLUETOOTH_SCAN,
BLUETOOTH_ADVERTISE
),
REQUEST_CODE_BLUETOOTH
)
} else {
// 권한 설정 성공시
// 저자는 사용시 다른 권한 요청으로 넘어가게 했었음
// accessPermission()
}
}
this >= Build.VERSION_CODES.M -> {
if (checkSelfPermission(BLUETOOTH) != PERMISSION_GRANTED ||
checkSelfPermission(BLUETOOTH_ADMIN) != PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this@SplashActivity,
arrayOf(
BLUETOOTH,
BLUETOOTH_ADMIN
),
REQUEST_CODE_BLUETOOTH
)
} else {
// 권한 설정 성공시
// 저자는 사용시 다른 권한 요청으로 넘어가게 했었음
// accessPermission()
}
}
// this >= Build.VERSION_CODES.* 버전 별 permission 추가로 설정 가능
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
grantResults
.contains(PERMISSION_GRANTED)
.let {
if (it) {
// 권한 수락시
// 해당 권한 Accept -> 다른 권한 설정 or 다른 페이지로 이동
when (requestCode) {
REQUEST_CODE_BLUETOOTH -> {
permissionCheckNow = REQUEST_CODE_ACCESS
accessPermission()
}
/*
REQUEST_CODE_ACCESS -> {
permissionCheckNow = REQUEST_CODE_STORAGE
storagePermission()
}
REQUEST_CODE_STORAGE -> {
permissionCheckNow = REQUEST_CODE_BLUETOOTH
// Intent() 모든 권한 수락 시 다른 페이지로 이동
}
*/
}
} else permissions.all {
// 권한 거절시
// 1. 사용자가 권한 요청을 명시적으로 거부한 경우 true를 반환한다.
// 2. 사용자가 권한 요청을 처음 보거나, 다시 묻지 않음 선택한 경우, 권한을 허용한 경우 false를 반환한다.
// 이곳에는 2.의 두 번 거절, 다시 묻지 않음과 1.번만 들어온다. (처음 권한 요청, 권한 허용의 경우 위에서 걸러짐)
ActivityCompat.shouldShowRequestPermissionRationale(this@SplashActivity, it)
}.let {
// 권한 요청 재시도
if (it) {
// 두 번째에 권한 수락시
when (requestCode) {
REQUEST_CODE_BLUETOOTH -> bluetoothAndAccessPermission()
// REQUEST_CODE_ACCESS -> accessPermission()
// REQUEST_CODE_STORAGE -> storagePermission()
}
}
else {
// 다시 묻지 않음을 선택하거나, 두 번 거절한 경우
// device의 설정창으로 이동하는 모듈
// snackBar Module
showSnackBar(binding.root, getString(message)) {
startActivity(Intent().apply {
when (requestCode) {
// Android Developers Setting에서 원하는 것을 찾아서 써도 된다.
REQUEST_CODE_BLUETOOTH -> action =
ACTION_APPLICATION_DETAILS_SETTINGS
// REQUEST_CODE_ACCESS -> action =
// ACTION_APPLICATION_DETAILS_SETTINGS
// REQUEST_CODE_STORAGE -> action =
// ACTION_APPLICATION_DETAILS_SETTINGS
}
data = Uri.fromParts("package", packageName, null)
})
}
}
}
}
}
// device의 설정창에서 permission 수락하지 않고, 취소나 뒤로가기로 앱으로 돌아온 경우
// 권한이 거부 된 경우 수락할 때까지 반복
override fun onRestart() {
super.onRestart()
when(permissionCheckNow) {
REQUEST_CODE_BLUETOOTH -> bluetoothPermission()
REQUEST_CODE_ACCESS -> accessPermission()
REQUEST_CODE_STORAGE -> storagePermission()
}
}