본문 바로가기
Android 개발/Android

Android 에서 동적 권한 얻기 # State registerForActivityResult Runtime Permission

by Developer88 2022. 10. 24.
반응형

안드로이드를 앱을 개발하면서, 부딛히는 어려움 중 하나는, 바로 Runtime Permission 입니다.

이 글을 쓰고 4년뒤인 지금 Kotlin코드로 다시 업데이트하였는데요.

Android OS버전이 올라가면서 유저에게 승인받아야 할 권한은 계속 늘어나고 있습니다.

(심지어 Notification도 권한을 받아야 한다고 하는군요.)

 

Runtime Permission은 External Storage와 관련된 작업인, 주소록이나, DB파일 혹은 이미지캐쉬를 저장하거나,

위치를 사용하는 앱일 경우에는 반드시 넘어야 할 산인데요.

오늘은 유저에게 외부저장소의 읽고 쓰기에 대해 동적으로 권한을 요청하는 것을 가지고 정리해 보도록 하겠습니다.

 

1. Manifest 선언먼저

권한을 요청할 때는 항상 Manifest 먼저 선언해야 합니다.

아래의 INTERNET 과 같이Manifest에 선언만 하면 되는 권한이 있구요.

 

 

어떤 권한은 동적으로 유저에게 요청해야 하는 권한들도 있습니다.

하지만, 동적으로 요청하는 권한들도,

Manifest에서 선언하는 것이 먼저입니다.

 

코드를 아무리 잘 작성해 봐도,

이것이 선언되어 있지 않으면,

권한 요청코드는 정상적으로 도착하지 않습니다.

 

참고로 WRITE_EXTERNAL_STORAGE는 이제는 필요하지 않지만,

하위호환을 위해서 아직은 같이 선언하는 것이 좋습니다.

 

Manifest에서 권한을 선언했다면 이제는 동적으로 권한을 요청하겠습니다.

 

2. 어떤 권한이 Runtime Permission 대상인가?

동적권한 요청의 대상이 되는 것들은 안드로이드 개발자 사이트에 나와있는데요.

https://developer.android.com/guide/topics/permissions/requesting.html 의중간정도에 나와있습니다.

 

예전에는 아래 이미지와 같이 동적으로 요청해야하는 위험한 요청들이 정해져서 표로 제공됬었는데요.

공식문서가 업데이트되면서, 사라졌거나, 다른주소로 이동된 것 같습니다.

이제는 아래 사이트에서 시나리오별로 점검이 필요합니다.

>> https://developer.android.com/training/permissions/evaluating

 

예전문서이지만, 아래의 Permission들은 여전히 동적요청대상이니 참고만 해주시구요.

현재 기준으로는 위의 링크에서 개별적으로 확인이 필요합니다.

추가해야할 권한요청은 계속 늘어나고 있고, 개발자들이 조금 괴로워지고 있습니다.

 

3. 권한 체크 구현

3-1. 권한 확인

가장 먼저 해야 하는 일은, 권한을 가지고 있는지 체크하는 일인데요.

권한을 체크하는 함수는 checkSelfPermission() 인데요.

 

잠시 이 메소드의 소스코드를 보겠습니다. 컨텍스트와 퍼미션을 인자로 받아서, 퍼미션이 존재하는지 확인하는 군요.

퍼미션의 종류와 안드로이드 프로세스 계정에서 권한을 가지고 있는지 보네요. (이부분에서 너무 깊이 들어가지는 않겠습니다.)

 

 

permission을 요청하고 승인이 되면, PERMISSION_GRANTED가 오는데요.

아래와 같은 함수를 만들어서 사용하도록 하겠습니다.

 

 

또한 아래와 같이 미리 사용할 permission들과 Code들도 정의해 놓겠습니다.

 

 

 

이제 준비가 되었으니 Activity에서 Permission을 가지고 있는지 호출해 보도록 하겠습니다.

 

 

아직 권한을 요청한 적이 없으니 당연히 없다고 나오겠지요.

 

 

만약, enum에 정의했던 권한들을 모두 체크하려면 아래와 같이 해볼수도 있겠네요.

 

 

3-2. 권한요청

하나의 권한을 요청하는 방법을 먼저 보겠습니다.

아래와 같이 registerForActivityResult 함수를 이용해서 권한을 요청하는 launcher를 정의해 줍니다.

 

 

 

이렇게 정의된 launcher를 아래와 같은 코드로 실행해 주면, 권한요청이 론칭됩니다.

보통 권한이 필요한 시점에 이런 코드를 론칭해 주는 것이,

유저입장에서 권한의 필요성을 이해하고 허락해줄 가능성이 높아지겠지요.

 

requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)

 

 

 

그럼 아래와 같이 권한요청화면이 나옵니다.

 

 

3-3. 여러개의 권한을 요청하기

여러개의 권한을 요청하는 것도 어렵지 않습니다.

결과는 키와 밸류의 Map객체로 넘어오는데요.

Key 값이 권한종류이고, Value 값은 권한승인여부입니다.

 

 

 

3-4. 권한체크해서 승인되지 않은 것들만 요청하기

모든 권한이 필수여서 반드시 허락을 받아야 한다면 어떻게 해야할까요?

아래와 같이 forEach로 다 확인한 다음, 유저에게 Permission을 요청해야 합니다.

MainActivity에서 시작하면서 체크해주면 좋겠지요.

 

 

 

4. 권한을 받지 못한 경우

만약 유저가 권한을 주지 않으면 어떻게 해야할까요?
우선은 유저에게 다시한번 다이얼로그를 띄어서, 권한의 필요성을 설명하고,
다시 권한을 수정해줄수 있도록 하는 것이 좋겠지요.

하지만, 구글에서는 유저의 결정을 존중하고, 설정화면으로 이동시키는 것은 하지말라고 권고되어있습니다.

그러나, 화면위에 그리기 같은 권한이 없으면 앱이 완전히 동작하지 않는다면,
어쩔수 없이 설정화면으로라도 이동시켜주어야 하겠지요.
예전에는 이런일을 할 수 있는 showRequestAgainDialog()라는 메소드를 만들어서, 유저가 권한주기를 취소한 경우에 실행되도록 하였습니다. (아래는 예전 Java코드입니다. Intent부분만 가져다 쓰면 충분할 것 같네요.)

 

 

참고로 설정> 애플리케이션> 해당앱> 권한 에 가셔서 권한을 오프하시면 테스트가 가능하니, 사용하시면 좋을 것 같습니다.

이렇게 해서 머리아픈 동적 권한 요청에 대해서 정리해 보았구요.

좀더 좋은 방법을 알게되면 다시한번 정리해보도록 하겠습니다.

728x90

댓글