권한 처리 방법 정리
예시 화면
|
권한 처리 과정 |
권한 처리를 위하여 AndroidManifest.xml 에 작성할 부분과 코드 상 작성할 부분을 구분하여 정리
권한 요청은 두 가지 방법
- requestPermission() 함수를 이용하는 방식
- ActivityResultApi 를 사용하는 방식
전체 샘플 코드
- Github
- 주요코드 위치: android/PermissionSample/app/src/main/java/com/example/permissionsample/CheckPermission.kt
목차
- AndroidManifest.xml 에 필요 권한 작성
- uses-permission 설명
- uses-feature 설명
- [코드] 권한 확인하기
- [코드] 권한 요청하기 (2가지 방식)
- requestPermissions() & onRequestPermissionsResult() 방식
- ActivityResultApi 방식
1. AndroidManifest.xml 에 필요 권한 작성
예제) Camera 와 audio 녹음 권한 필요시
<!-- A camera with burst capability is required to use this application -->
<uses-feature android:name="android.hardware.camera.any" />
<!-- Permission declarations -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
안드로이드 권한 목록
1.1. uses-permission 설명
설명
앱이 필요로 하는 권한들 선언
예제) AndroidManifest.xml
<!-- Permission declarations -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
1.2. uses-feature 설명
설명
마켓플레이스 (Google Play 스토어) 에 필터링 적용
예제) AndroidManifest.xml
<!-- A camera with burst capability is required to use this application -->
<uses-feature android:name="android.hardware.camera.any" />
2. [코드] 권한 확인하기
https://developer.android.com/training/permissions/requesting#already-granted
예제) 권한 목록과 모든 권한 확인
import android.Manifest
import androidx.core.content.ContextCompat
...
private val PERMISSIONS_REQUIRED = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO)
...
fun hasPermissions(context: Context) = PERMISSIONS_REQUIRED.all {
ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}
코드 설명
- 함수 원형:
- public static int checkSelfPermission(@NonNull Context context, @NonNull String permission)
- Permission 상수 값들은 android.Manifest.permission 클래스에 선언되어 있음
- 둘 중 하나의 값 리턴
- PERMISSION_DENIED (-1)
- PERMISSION_GRANTED (0)
shouldShowRequestPermissionRationale
예)
ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)
설명
사용자 UI, 예를 들어 권한이 필요한 이유를 설명하는 화면를 보여줘야할 필요가 있다고 안드로이드 운영체제가 판단하는지 여부를 확인하는 함수
문제는 언제 true/false 값을 주는지 앱 개발자 측면에서 명확하지는 않다.
다만 안드로이드 공식 예제를 통해 처리 시점을 가늠해 본다
3. [코드] 권한 요청
권한 요청하는 방식은 2가지
- requestPermissions() & onRequestPermissionsResult() 방식
- AppCompatActivity 와 Fragment 에 내장된 함수들
- AcitivtyResultApi 방식 (공식 문서 추천)
3.1. requestPermissions() & onRequestPermissionsResult() 방식
requestPermissions() -> override fun onRequestPermissionsResult()
3.2. ActivityResultApi 방식 (공식 문서 추천)
requestPermissions 와 차이점
- 주요 차이점: request code 필요 없음
- 코드 스타일: 권한 핸들러를 따로 독립적으로 구현하여 Activity flow 와 섞임 방지
단일 권한
예제)
class MainActivity : AppCompatActivity() {
private val requestPermission = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
// returns boolean representind whether the
// permission is granted or not
if (isGranted) {
Log.i("DEBUG", "permission granted")
} else {
Log.i("DEBUG", "permission denied")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener {
// call launch with string containing permission to be
// requested to show the system permission dialog
requestPermission.launch(Manifest.permission.CAMERA)
}
}
}
복수 권한
예제)
class MainActivity : AppCompatActivity() {
private val requestPermission = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.forEach { actionMap ->
when (actionMap.key) {
Manifest.permission.CAMERA -> {
if (actionMap.value) {
Log.i("DEBUG", "permission granted")
} else {
Log.i("DEBUG", "permission denied")
}
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.button).setOnClickListener {
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
}
}
}