RIEN😚
이상한 나라의 개발자
RIEN😚
전체 방문자
오늘
어제
  • 분류 전체보기 (125)
    • Algorithm (68)
      • 알고리즘 (0)
      • Baekjoon (8)
      • 프로그래머스 (55)
      • HackerRank (5)
    • Android (30)
      • Project (1)
      • Error (2)
      • Studio (1)
      • Android (26)
    • Kotlin (6)
    • CS (4)
      • 네트워크 (2)
      • 데이터베이스 (2)
    • Front End (5)
      • React (1)
      • VUE (3)
      • Project (0)
      • 기타 (1)
    • 기록 (11)
      • 회고록 (6)
      • TIL (5)

블로그 메뉴

  • Github🔥
  • 포트폴리오🌹

공지사항

인기 글

티스토리

250x250
반응형
hELLO · Designed By 정상우.
RIEN😚
Android/Android

[Android] 실행시점에 Permission 요청하기

Android/Android

[Android] 실행시점에 Permission 요청하기

2023. 4. 23. 20:44
728x90
반응형

토이 프로젝트로 진행하고 있는 하루네컷에서 사용자에게 권한을 요청해야 하는 UseCase가 있어,

Android Permission Request 부분에 대해 복습도 해볼겸 이렇게 포스트를 정리해보게 되었습니다. 🤗

 

혼자 독학하고 있는 안드로이드 초보자입니다.

혹시 틀린 부분이 있다면 꼭 댓글로 말씀 부탁드립니다. :-)

 

👇🏻 참고

 

런타임 권한 요청  |  Android 개발자  |  Android Developers

런타임 권한 요청 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 모든 Android 앱은 액세스가 제한된 샌드박스에서 실행됩니다. 앱이 자체 샌드박스 밖에 있

developer.android.com

 

1. Permission 요청 flow

앱을 만들다보면 가끔(?) Device 내 제한된 데이터에 접근하거나 제한된 동작을 수행하애 하는 경우가 있습니다.

이럴 때는 적절한 권한(Permission)을 요청해야 하며, Permission에 종류에 따라 정해진 flow에 따라 개발을 진행해야 합니다.

예를 들어, install-time permission들은 위 이미지에 보이는 것과 같이 추가적인 요청 작업(4) 없이 권한을 얻을 수 있습니다.

 

그럼 여기서 말하는 Permission에 종류에는 어떤것이 있을까요?

2. Permission의 종류

Permission은 크게 제한 범위에 따라

  • install-time permission
  • runtime-permission
  • special permission

으로 나누어지게 됩니다.

 

2.1 Install-time permission

Install-time permission은 가장 좁은 범위의 Permission으로

시스템 또는 다른 앱에 영향을 주지 않는 데이터 / action과 관련된 permission입니다.

 

선언된 Install-time permission은 App store의 App 상세 정보 페이지에서 확인할 수 있으며,

사용자가 앱을 설치할 때 자동적으로 시스템에 의해 동의(grant)되게 됩니다.

 

2.2 Runtime permission

Runtime permission은 dangerous permissions이라고도 하며,

시스템 또는 다른 앱에 영향을 줄 수 있는 제한된 데이터 또는 action과 관련된 permission입니다.

 

Install-time permission과 다르게 사용자에게 권한을 요청하는 추가적인 작업이 필요하며,

권한 요청 시, 👇🏻아래와 같은 창을 보신 적이 있을거예요.

이러한 Runtime permission으로 접근 가능한 데이터들은 위치, 연락처 정보 등과 같이 민감한 정보가 해당됩니다.

 

2.3 Special permissions

오직 platform과 OEM들에 의해서만 정의될 수 있는 특별한 권한으로, 특정 데이터 또는 action에 대한 접근을 막고자 정의됩니다.

 

👇🏻 아래는 Device의 설정에서 확인할 수 있는 Special app access 화면이며,

여기에 속하는 대부분의 동작이 Special permission으로 제공됩니다.

 

2.4 Permission groups

이러한 Permission들은 종류가 다양하지만 하나의 그룹으로 묶여 사용될 수 있습니다.

예를 들어, 가장 자주 사용된다고 생각되는 Camera Permission Group에는 사진 요청과 비디오 촬영과 관련된 Permission이 속해있습니다.

 

Permission을 그룹화하는 이유는 System이 사용자에게 권한을 요청하는 Dialog를 최대한 적게 띄우기 위해서입니다.

요청하는 권한별로 Dialog를 하나씩 띄우게 된다면 사용자로 하여금 앱에 대한 불신감을 키울 수 있기 때문입니다.😭

뭐야.. 왜 이렇게 사용하는 데이터가 많은거지?🤨 이런 느낌이지 않을까요?

 

🌹 적절한 Permission 요청은 사용자와 앱 간의 신뢰성을 높이고 안정적인 서비스 제공을 보장하는 조건 중 하나라고 생각해요.

이번에는 위에서 보았던 여러 Permission 타입 중 Runtime permission 적용방법에 대해 학습하고 정리해보고자 합니다. 🔥👍🏻

 

3. Runtime permission 요청하기

Runtime permission은 앞에서도 말했듯, dangerous permission(이름만 들어도 위험해 보이는..)이라 하며,

권한을 요청하기 위해서는 추가적인 작업이 필요하게 됩니다. 🤗

🏠 정확히는 Android 6.0(API 23) 이상의 기기에서만 필요하지만, 제가 알기로 이제는 API 23 이상만 지원한다고 알고 있어 앞으로는 무조건 추가 작업이 필요할 듯 해요.

 

3.1 Runtime permission 권장사항

Runtimer Permission은 사용자에게 권한을 요청하기 때문에, 아래와 같은 사항들을 지키는 것을 권장합니다.

  1. 그 권한이 필요한 기능이 실행될 때 권한 요청해야 합니다.
  2. 권한을 수락하거나 거절할 수 있는 방법을 반드시 제공해주어야 합니다.
  3. 만약 사용자가 권한 요청을 거부하였어도, 해당 기능을 제외한 축소된 서비스를 제공하여 사용자가 계속 앱을 이용할 수 있도록 해야 합니다.
  4. 권한이 필요한 특정 기능을 사용할 때는 해당 권한이 허가되었는지 매번 검사하는 로직을 추가해야 합니다.

 

3.2 Permission 요청 순서

 

가장 먼저 선행되어야 하는 작업은

📌 3.2.1 진짜 그 permission이 필요한가?

최근 Android 버전이 올라가면서, 여러 permission이 생겨나고 사라지고 있는 것으로 알고 있습니다.

또한 특정 라이브러리를 통해 권한을 별도로 요청하지 않아도 내부적으로 처리해주는 기능 또한 존재하죠.

 

따라서, 해당 권한이 실제 필요한지 먼저 검증하는 단계가 필요합니다.

 

📌 3.2.2 permission 추가

permission 요청이 필요한 것으로 결정되었다면, 해당 permission을 manifest 파일에 추가해줍니다.

👇🏻 요렇게!

 

📌 3.2.3 UX 설계

어떠한 기능을 제공받기 위해 이러한 권한을 요청하는 것인지 사용자가 인식할 수 있도록 적절한 UX 설계해야 합니다.

 

📌 3.2.4 사용자가 특정 권한이 필요한 기능을 사용하기 전까지 대기 

앱을 시작하는 순간부터 사용자에게 권한을 요청하는 것이 아닌, 해당 권한이 실질적으로 필요한 기능을 

사용자가 실행했을 때 권한이 요청되도록 기다려야 합니다.

 

📌 3.2.5 권한 승인 여부 확인

권한 요청이 실행되었을 때 가장 먼저 해당 권한이 이미 승인되어 있는지 확인하는 작업이 필요합니다.

이미 승인이 되어있다면 바로 해당 데이터에 접근하거나 Action을 수행할 수 있고, 승인이 되어있지 않다면 권한 승인을 위한 다음 작업을 수행해야 합니다.

🔥 여기서 주의해야 할 점! 한번 권한이 승인되었다고 해서 계속 유지되는 것은 아닙니다. 때문에 권한이 필요한 특정 기능을 수행할 때마다 매번 권한 승인 여부를 확인하는 작업이 이루어져야 합니다.

👇🏻 요렇게!

 

📌 3.2.6 사용자에게 권한이 필요한 이유에 대해서 설명을 해야 하는지 확인

시스템에서 특정 권한이 필요한 이유를 사용자에게 설명해줘야 하는 권한이라고 지정한 경우에는 설명이 포함된 UI를 사용자에게 제공해주어야 합니다.

👇🏻 요렇게!

 

이 UI에는

  • 접근하려는 데이터는 무엇인가?
  • 해당 권한을 승인하였을 때의 이점은 무엇인가?

에 대한 세부적인 설명을 제시해주어야 합니다. 🤗

( * 만약 설명해줄 필요가 없는 권한인 경우에는 선택사항입니다. )

🏠 사용자에게 요청하는 권한과 요청 이유에 대해 설명해줌으로서 앱의 신뢰성을 높일 수 있어, 저는 설명 UI를 추가하는 것을 선호해요. 😆
더보기

추가적으로 Android 12(API 31)부터는 privacy indicator라고 하여, 앱이 마이크나 카메라에 접근하여 사용중이라면 화면에 사용중이라는 것을 표시해주는 기능이 제공되고 있습니다.

이렇듯 특정 상황에서는 실시간으로 사용자의 정보에 접근하고 있다는 것을 Notification 등으로 보여주는 것도 유용합니다. 👍🏻

 

따라서, 앱에서 특정 권한이 필요한데, 그 이유가 사용자에게 있어서 분명하지 않을 경우에는 요청 근거에 대해서 알려줄 수 있는 방법을 고민해보아야 합니다.

 

📌 3.2.7 permission 요청

사용자에게 권한에 대한 설명을 보여준 후 사용자가 권한을 승인하거나, 권한에 대한 설명을 보여줄 필요가 없는 경우

시스템에 권한을 요청하게 됩니다.

 

이를 위해 AndroidX에서 제공해주는 RequestPremission을 사용할 수 있습니다. 👍🏻

🌹 해당 방법은 시스템에서 request code를 관리하며, 좀 더 간편하게 로직을 구성할 수 있도록 해줍니다. 때문에 해당 포스트에서는 RequestPermission을 사용한 방법만 정리하도록 하겠습니다. 😌
더보기

하지만 만약 직접 result code를 지정하는 방법이 궁금하시다면,

👉🏻 여기를 클릭해주세요. :-)

 

RequestPermission을 사용하기 위해서는 아래 dependency가 필요합니다.🤗

  • androidx.activity 1.2.0 이상
  • androidx.fragment 1.3.0 이상

 

👇🏻 아래와 같이 ActivityResultLauncher를 만들어줍니다.

사용자가 시스템이 띄워준 prompt를 클릭하면 정의한 callback method가 호출되게 됩니다.

🛠 여러 Permission을 요청할 때는 RequestPermission 대신, RequestMultiplePermissions를 사용해야 합니다.

 

이후, 정의한 requestPermissionLauncher를 호출해줍니다.

 

📌 3.2.8 사용자가
  • 권한을 승인한 경우: 필요한 데이터에 접근
  • 권한을 거부한 경우: 제한된 서비스를 제공

 

여기까지 코드를 작성하면 기본적인 권한 요청은 완료되었습니다. 👏🏻👏🏻👏🏻


이후에는 공식문서에 포함되어 있는 추가적인 내용에 대해서 정리해보도록 하겠습니다. 🔥

4. location 권한 요청

앱 내에서 가장 민감한 정보를 하나 뽑아보라 하면 location을 들 수 있을거 같은데요.

때문에 Location과 관련해서는 UseCase에 맞게 사용할 수 있는 다양한 권한들이 존재합니다.

 

4.1 Foreground location

아래 상황에서 현재 기기의 위치 정보를 얻고자 할 때 foreground locaion 권한이 필요합니다.

  • 화면에 보이고 있는 Activity에서
  • Foreground Service에서
🌹 Android 10(API 29) 이상에서는 location 정보에 접근하는 foreground service는 manifest에 등록할 때 service type을 location으로 지정해주어야 합니다.
( * 이전 버전에서는 선택사항이지만 권장하고 있습니다! :-) )
<!-- Recommended for Android 9 (API level 28) and lower. -->
<!-- Required for Android 10 (API level 29) and higher. -->
<service
    android:name="MyNavigationService"
    android:foregroundServiceType="location" ... >
    <!-- Any inner elements go here. -->
</service>

 

이 때 필요한 권한은 

4.1.1 대략적인 위치 정보가 필요한 경우
<!-- Include this permission any time your app needs location information. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
4.1.2 정확한 위치 정보가 필요한 경우
<!-- Include only if your app benefits from precise location access. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

 

4.2 Background location

앱 서비스 상 앱이 종료되어도 Background에서 계속해서 기기의 위치를 수집해야 하는 경우가 있습니다.

예를 들어,

  • 가족들간에 위치 공유 서비스
  • 사용자 위치 기반의 IOT 서비스 앱

Background Location의 정확도는 Foreground Location과 동일하게

어떠한 Location Permission을 사용하고 있는지에 따라 다릅니다.

 

4.2.1 Android 10 (API 29) 이상부터는

Background Location을 사용하기 위해 ACCESS_BACKGROUND_LOCATION 권한이 manifest에 필수로 추가되어야 합니다.📌

( * 이전 버전에서는 foreground location 접근 권한이 있다면 background location 또한 접근 가능합니다. )

<manifest ... >
  <!-- Required only when requesting background location access on
       Android 10 (API level 29) and higher. -->
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

 

5. 사용자가 Permission을 거부했을 때는..

개인 정보가 중요해지고 있는 지금.. 사용자들은 자신들의 정보를 보호하기 위해 민감한 정보와 관련된 Permission을 거부할 수 있습니다.

 

때문에 사용자에게 해당 권한이 필요한 근거와 해당 권한을 거부했을 때의 상황에 대한 설명을 통해,

사용자가 계속해서 서비스를 이용할 수 있도록 해야합니다.

 

5.1 권장사항

5.1.1 UI를 이용해 사용자에게 알려주기

권한 거부로 인해 사용이 불가능한 버튼 또는 기능에 대해 사용자가 인식할 수 있도록 다른 UI로 표현할 수 있습니다.

5.1.2 권한을 거부하더라도 계속해서 앱을 사용할 수 있도록 하기

권한을 거부한 이후 사용자가 더이상 앱을 사용할 수 없도록 경고 문자(또는 화면)을 전체화면 가득 채우거나 하지 않기

 

Android 11 (API 30)부터, 기기에 앱이 설치된 이후 사용자가 한번이라도 권한을 거부하였다면,

이후에 다시 권한요청을 요청하더라도 관련된 System Prompt를 띄우지 않습니다.

 

사용자가 한번 이상 "거부"에 의사를 밝혔다면, 영구적으로 권한을 승인하지 않겠다는 의미로 해석하고 있으며,

때문에 해당 권한이 실질적으로 필요한 경우에 권한을 요청하여 사용자가 이러한 권한이 왜 필요한지 확실히 인식하여 최대한 권한을 승인할 수 있는 방안을 모색해야 합니다.

🌹 실제 토이 프로젝트 중에도 사용자가 한번 시스템 Prompt에서 권한을 거부하게 되면 다음부터는 Prompt를 띄우지 않아 기횡을 수정하는 일이 있었습니다. 😭

 

또한, 권한은 특정 상황에 따라 자동적으로 승인되거나 거부될 수 있기 때문에 앱 내에서는 항상 권한이 필요한 기능을 실행하기 전에

권한을 검사하고 필요한 경우에는 요청하는 로직을 추가해야 합니다.🔥🔥

 

6. One-time permissions

Android 11 (API 30)부터 사용자에게 권한을 요청하는 Prompt에는

👇🏻 요렇게 "이번만 허용(Only this time)"이라는 선택지가 포함되어 있습니다.

사용자가 "이번만 허용"을 선택하게 되면 일시적으로만 권한이 승인되게 되며, 아래 상황 중 하나일 때까지 그 권한이 유지됩니다.

  • 앱의 Activity가 보이는 중에는 데이터에 접근 가능합니다.
  • 사용자가 앱을 background로 보낸다면, 짧은 기간동안은 데이터에 접근 가능합니다.
  • Activity가 보이는 중에 Foreground service를 실행되고 그 후에 사용자가 앱을 background로 보냈다면, foreground service가 살아있을 때까지는 데이터에 접근 가능합니다.

 

단, 만약 사용자가 시스템 설정 등에서 이러한 One-time permission까지 취소시킨다면 foreground service가 살아있어도,

권한과 관련된 데이터에 접근할 수 없으며, 앱 자체가 종료되게 됩니다.

🌹 이후 사용자가 다시 앱을 실행하거나 해당 기능을 요청하게 되면, 위 이미지와 같은 권한을 요청하는 Prompt가 다시 뜨게 됩니다.

 

7. 사용하지 않는 permission Deny 시키기

6.1 App에서 Deny 시키기

Android 13(API 33) 이상부터는 더이상 필요로 하지 않는 runtime 권한을 제거할 수 있는 기능을 제공해주고 있습니다. 🤗

이렇게 사용하지 않는 권한들을 제거함으로써 사용자로 하여금 앱에 대한 신뢰도를 높이는 것이 목적입니다. :-)

 

runtime 권한을 제거하기 위해서는

revokeSelfPermissionOnKill(Mainfest.permission.EXTERNAL_STORAGE)

와 같이 permission의 이름을 revokeSelfpermissionOnKill 메서드에 전달하여 Deny 시킬 수 있습니다.

( * 여러 permission을 한번에 Deny 시킬 때는 revokeSelfPermissionsOnKill()을 사용할 수 있습니다. )

🌹 이러한 권한 Deny 작업은 비동기적으로 수행되며 app의 UID와 연관된 모든 프로세스를 종료합니다.

 

📌 추가

시스템이 앱의 권한들을 Deny 시키려면 앱과 관련된 모든 프로세스들이 종료되기에

가장 안전하게 프로세스를 종료될 수 있는 시점에 해당 작업을 수행하게 됩니다.

보통은 앱이 foreground에서 background로 이동할 때까지 기다린 후에 작업을 진행하게 됩니다.

 

사용자게에 특정 권한이 더이상 사용되지 않는다는 것을 알려주는 것은 해당 작업이 이루어진 이후에 Dialog로 보여지게 됩니다. 👏🏻

 

6.2 사용하지 않는 permission 자동으로 Deny

만약 앱이 Android 11(API 30) 이상을 타겟팅하고 있고 사용자가 앱을 몇달 동안 사용하지 않은 경우에는

시스템이 자동적으로 사용자의 민감한 정보들을 보호하기 위해 runtime permission들을 Deny 상태로 설정해줍니다. 👍🏻

 


현재 개인적으로 진행하고 있는 토이 프로젝트에서 권한 요청 기능 구현이 필요해서

관련 내용을 정리할 겸 포스트를 작성하게 되었습니다. 🤗

 

감사합니다.

👇🏻 제 프로젝트에 사용자에게 권한에 대해 설명해주는 화면이예요. :-)

 

반응형

'Android > Android' 카테고리의 다른 글

[Test] Hamcrest를 위한 Junit의 assertThat이 Deprecated된 건에 대해  (0) 2024.11.19
[Compose Internal] changed 예시 코드 분석  (0) 2024.11.07
[Android] 2023 Google Play Policy Bytes  (0) 2023.04.12
[Compose] Custom BoxShadow를 만들어보자!  (1) 2023.04.04
[Compose] Font에 적용되는 Padding 제거하기  (0) 2023.04.04
  • 1. Permission 요청 flow
  • 2. Permission의 종류
  • 3. Runtime permission 요청하기
  • 4. location 권한 요청
  • 5. 사용자가 Permission을 거부했을 때는..
  • 6. One-time permissions
  • 7. 사용하지 않는 permission Deny 시키기
'Android/Android' 카테고리의 다른 글
  • [Test] Hamcrest를 위한 Junit의 assertThat이 Deprecated된 건에 대해
  • [Compose Internal] changed 예시 코드 분석
  • [Android] 2023 Google Play Policy Bytes
  • [Compose] Custom BoxShadow를 만들어보자!
RIEN😚
RIEN😚
안드로이드 / 코틀린 독학으로 취업하자!

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.