최근에 처음으로 Notification 런타임 권한요청을 할 일이 생겨서 정리하는 시간을 가져보았다. (링크 첨부)
사이드 프로젝트는Jetpack Compose 100% 로 진행하고 있는데 Composable 함수에선 어떻게 런타임 권한요청을 할지 궁금해졌다.
직접 만들어 쓸 수도 있겠지만 권한처럼 필수적인 기능은 공식에 가까운 라이브러리가 있을 것 같았다.
찾아본 결과 google 레포의 accompanist 에 Permission 섹션이 있었다.
간단한 사용법과 구현 코드 그리고 주의점에 대해 알아보자.
사용방법 간단하게 정리
먼저 아래와 같이 권한을 추가해준다. 버전은 현재 프로젝트의 Compose 버전을 확인하여 리드미에 나와있는대로 accompanist 라이브러리의 버전을 설정한다.
implementation "com.google.accompanist:accompanist-permissions:$compose_accompanist"
아래는 간단하게 작성해본 예시코드이다.
(요청은 아무거나 했다.)
여러권한 요청도 아래와 유사하게 진행된다.
rememberPermissionState (여러 권한요청 시 rememberMultiplePermissionState) 로 원하는 권한의 상태를 가져와서
권한요청을 한다. 결과는 rememberPermissionState 에 전달했던 콜백으로 받는다.
실행해보면 권한 상태에 따라 텍스트가 바뀜을 확인할 수있다.
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun TestScreen() {
val notificationPermissionState =
rememberPermissionState(permission = Manifest.permission.POST_NOTIFICATIONS) { result ->
Log.d("SR-N", "result $result")
}
val text by derivedStateOf {
when {
notificationPermissionState.status.isGranted -> "이미 권한 허용됨"
notificationPermissionState.status.shouldShowRationale -> "Show rationale"
else -> "권한 요청"
}
}
Button(onClick = {
if (!notificationPermissionState.status.isGranted) {
if (notificationPermissionState.status.shouldShowRationale) {
Log.d("SR-N", "Show rationale")
} else {
notificationPermissionState.launchPermissionRequest()
}
}
}) {
Text(text = text)
}
}
구현 간단하게 알아보기
Composable 에서는 상태로 뷰를 관리하는데, rememberPermissionState 를 사용해서 권한 관련해서도 상태를 만들 수 있다.
rememberPermissionState 는 인자로 어떤 권한(permission)을 요청할지와 권한 요청결과 콜백(onPermissionResult)을 전달받고 PermissionState 를 반환해준다.
interface PermissionState {
val permission: String
val status: PermissionStatus
fun launchPermissionRequest(): Unit
}
PermissionState 는 아래와 같이 permission 과 status 라는 프로퍼티를 갖는 인터페이스이다.
내부 코드를 확인한 결과 rememberPermissionState 에 인자로 전달했던 permission 이 그대로 들어간다.
status 는 인자로 전달한 permission 의 Granted 여부와 권한이 왜 필요한지 안내해줘야하는 시점인지 상태를 가지고 있다. 그 정보를 아래와 같은 확장 프로퍼티로 읽어올 수 있다.
@ExperimentalPermissionsApi
val PermissionStatus.isGranted: Boolean
get() = this == PermissionStatus.Granted
@ExperimentalPermissionsApi
val PermissionStatus.shouldShowRationale: Boolean
get() = when (this) {
PermissionStatus.Granted -> false
is PermissionStatus.Denied -> shouldShowRationale
}
status 는 적절한 타이밍에 계속 업데이트된다. 그렇게 현재 권한 상태를 감지한다.
Localcontext.current 로 context 를 가져와서 현재 Activity 를 찾아서 두 상태값을 가져오도록 구현되어있다.
checkSelfPermission, shouldShowRationale 사용하고
launchPermissionRequest 도 똑같이 ActivityResultLauncher 사용하여 구현되어있다.
주의점
launchPermissionRequest 는 Composable 스코프 밖에서 호출하도록한다.
예를들면 사이드 이펙트나 이 글에 나온 예시처럼 클릭 콜백 리스너에서 말이다.
리컴포지션마다 호출될 순 없지 않은가..!
참조
'Android > 이론 학습' 카테고리의 다른 글
[Android/GraphQL] Apollo Kotlin (시작 ~ 쿼리실행) (0) | 2022.03.08 |
---|---|
[Android/Firebase] 기존 프로젝트에 Crashlystics 적용하기 (0) | 2022.03.06 |
[Kotlin/백준] 5430, AC (시간초과 해결) (0) | 2022.02.27 |
[Android] WorkManager 로 복잡한 백그라운드 작업을 쉽게 해결한다고? (기본 사용법과 예시코드 포함) (0) | 2022.02.23 |
[Android] Service 의 타입과 사용법 그리고 권장사항 (0) | 2022.02.23 |