권한(Permission)에 관한 포스팅을 해보겠습니다.
Permission
과거 Android App에선 권한이 필요할 시 App 설치 전 사용자에게 필요 권한 목록을 보여주고, 권한을 요구한 뒤 사용자의 응답에 따라 설치를 하거나, 설치를 제한하는 것이 일반적이었지만
Android 6.0 마시멜로 (SDK 23) 이상의 버전부터는 일반 권한의 경우 앱 설치 시점에서 권한에 대한 승인을 요청하고, 위험 권한의 경우 앱 실행 시점에서 권한이 필요할 시 사용자에게 해당 권한이 필요한 이유를 알리고, 권한에 대한 승인을 선택할 수 있도록 변경되었습니다.
분류 | 세부 | |
LOCATION | ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION |
|
CAMERA | CAMERA | |
MICROPHONE | RECORD_AUDIO | |
CONTACTS | READ_CONTACTS WRITE_CONTACTS GET_ACCOUNTS |
|
PHONE | READ_PHONE_STATE CALL_PHONE READ_CALL_LOG WRITE_CALL_LOG ADD_VOICEMAIL USE_SIP PROCESS_OUTGOING_CALLS |
|
CALENDAR | READ_CALENDAR WRITE_CALENDAR |
|
SMS | SEND_SMS READ_SMS RECEIVE_SMS RECEIVE_WAP_PUSH RECEIVE_MMS |
|
SENSORS | BODY_SENSORS | |
STORAGE | READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE |
이제 사용자에게 권한을 요청하는 방법에 대해 알아보겠습니다.
1. SDK 버전 확인
2. 해당 권한이 승인 여부 확인
3. 권한 승인 여부에 따라 분기 처리
우선 위 순서를 따르기전에 Manifest에 권한을 등록해야 합니다.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.CAMERA"/>
코드를 작성하는 것은 정해진 것이 없으니 문제가 되지 않는다면, 자신의 방식대로 작성하면 됩니다.
전체적인 순서는
1. 사용자 이벤트 발생
2. permissionCheck() 호출 ( 3. versionCheck() 호출, 4. checkSelfPermission() 호출, 5.requestPermissions() 호출 )
6. onRequestPermissionsResult() 응답
사용자의 이벤트 발생
findViewById<ImageButton>(R.id.Lifehelper_logo)
.setOnClickListener {
permissionCheck()
}
1. SDK 버전 확인 : versionCheck()
private fun versionCehck() : Boolean {
if (android.os.Build.VERSION.SDK_INT >= M) {
return true
}else{
return false
}
}
2. 권한 승인 여부 확인 : checkSelfPermission()
private fun checkSelfPermission(): Boolean {
Log.d(Constants.TAG, "${this::class.simpleName} 권한 체크를 시작합니다.")
PERMISSIONS.forEach {
if (ContextCompat.checkSelfPermission(
this@MainActivity, it) != PackageManager.PERMISSION_GRANTED) {
Log.d(Constants.TAG, "${this::class.simpleName} $it 권한 : 거절")
return false
}
}
return true
}
ContextCompat.checkSelfPermission()
메서드를 이용하면 권한 승인에 대한 여부를 확인할 수 있습니다.
권한이 있는 경우, PERMISSION_GRANRTED를 없는 경우 PERMISSION_DINIED를 반환합니다.
3. 권한 승인 여부에 따른 분기 처리 : permissionCheck()
private fun permissionCheck() {
if (versionCehck()){
if (checkSelfPermission()) {
Log.d(Constants.TAG, "${this::class.simpleName} " + "권한 : 승인 상태")
...
} else {
Log.d(Constants.TAG, "${this::class.simpleName} " + "권한 : 거절 상태")
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
PERMISSIONS.toString())) {
// 1. 사용자가 승인 거절을 누른 상태
Log.d(Constants.TAG, "${this::class.simpleName} " + "사용자가 승인 거절을 누른 경우")
requestPermissions()
} else {
// 2. 사용자가 승인 거절 + 다시 표시하지 않기를 누른 경우
// 3. 아직 승인 요청을 한 적이 없는 경우
Log.d(Constants.TAG, "${this::class.simpleName} " + "사용자가 승인 거절 + 다시 표시하지 않기를 누른 경우")
requestPermissions()
}
}
}
}
ActivityCompat.shouldShowRequestPermissionRationale()
: 사용자가 거부를 누른 경우 true를 반환합니다. 보통 이를 통해 조금 더 다양한 분기 처리를 하기위해 사용합니다.
4. 권한 요청과 응답 처리 : requestPermissions()
private fun requestPermissions() {
Log.d(Constants.TAG, "${this::class.simpleName} 권한 요청을 시작합니다.")
ActivityCompat.requestPermissions(
this,
PERMISSIONS,
Constants.REQUEST_CODE)
}
ActivityCompat.requestPermissions()
: 사용자에게 권한을 요청합니다.
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray )
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when(requestCode){
Constants.REQUEST_CODE -> {
grantResults.forEach {
if (it == PackageManager.PERMISSION_GRANTED){Log.d(Constants.TAG, "${this::class.simpleName} " +
"권한 체크 결과 : $it 승인")
}
else {
Log.d(Constants.TAG, "${this::class.simpleName} " +
"권한 체크 결과 : $it 거절")
CustomSnackBar.make(findViewById<ImageButton>(R.id.Lifehelper_logo), getString(R.string.request_permission)).show()
}
}
}
}
}
onRequestPermissionResult()
: 사용자 응답을 전달합니다. (override method)
'Android' 카테고리의 다른 글
Retrofit2 예제 (feat. HTTP, REST API, OkHttp) (0) | 2021.03.21 |
---|---|
RecyclerView : 리사이클러 (0) | 2021.03.15 |
Application Class란 (context 접근) (0) | 2021.03.09 |
Part.1 - Clean Architecture (0) | 2021.02.26 |
Localization(지역화) (0) | 2021.02.22 |