Jetpack Compose 멀티 Permission 권한 요청

노준혁·2023년 9월 24일
2

❓여러 개의 Permission 허용 방식

안드로이드 기능 중 일부는 권한을 획득하여야 사용할 수 있다. 위치기반, 카메라, 스토리지 접근 등이 이러한 예인데, 파티런 프로젝트에서는 위치기반과 알람 권한을 필수로 받아야 한다.
(https://github.com/SWM-KAWAI-MANS/party-run-application)

단순히 각각 Permission을 받도록 구현하는 것 자체는 쉽지만, 여러 개의 Permission을 동시에 획득하고 싶을 때, 더 나아가 거부 상태라면 기능 사용 전 Permission을 허용해야 한다고 유도해야 했다.

본 페이지는 Jetpack Compose를 통해 위 과정을 구현한 방식에 대해 설명한다.

  1. 연속적인 Permission 요청 구현:
    • Jetpack Compose에서 [필요한 Permission A, B, C...]를 연속적으로 사용자로부터 요청하는 과정 구현
    • 사용자 경험(UX)을 고려하여, 연속적인 권한 요청 시 불편함이 최소화되도록 설계
  2. Permission 거부 시 유도 프로세스 구현:
    • 사용자가 필요한 권한을 거부했을 때, 해당 기능의 중요성 및 권한 허용의 필요성을 설명하는 알림을 표시
    • 알림 내부에 '권한 설정' 버튼을 통해 사용자가 직접 Permission을 허용하도록 유도
  3. 사용자 경험 최적화:
    • Permission이 필요한 기능을 사용할 때만 프로세스를 수행하도록 구현

💡 구현

안드로이드의 Jetpack Compose와 함께 Google Accompanist 라이브러리의 Permission API를 사용하여 앱의 Permission을 요청하고 관리하는 방식에 대한 구현 내용이다.

  1. 사용자가 필수 권한이 필요한 기능을 사용하고자 할 때, 만약 그 권한이 허용되어 있지 않다면 showPermissionDialog 값을 true로 설정하여 권한 요청을 유도한다.
  2. 필요한 권한들의 상태를 확인하고, 거부된 권한이 있을 경우 해당 권한에 대한 설명과 함께 다이얼로그를 표시한다.
  3. 사용자는 다이얼로그에서 권한을 다시 요청하거나, 설정 페이지로 이동하여 수동으로 권한을 승인할 수 있다.

기본 변수 설정:

  • showPermissionDialog: 권한 요청 다이얼로그를 표시할 지 여부를 결정하는 mutable state
  • permissionsList: 앱이 요청할 권한들의 리스트. 본 파티런 프로젝트에서는 위치 권한과, TIRAMISU 버전 이상일 경우 알림 권한을 포함하고 있음.

권한 플로우 실행:

  • HandlePermissionActions는 권한 상태(permissionState)와 다이얼로그 표시 상태(showPermissionDialog)를 가지고 권한 요청의 전반적인 플로우를 관리한다.
  • 사용자가 권한 요청 다이얼로그를 보기를 원할 경우 (showPermissionDialog.value == true), CheckMultiplePermissions를 호출하여 여러 권한들의 상태를 확인하고 필요한 액션을 실행

다중 권한 확인:

  • CheckMultiplePermissions Composable 함수는 주어진 권한들의 상태를 확인하고, 모든 권한이 승인되었는지, 아니면 거부되었는지에 따라 적절한 액션을 수행한다.
  • permissionDecriptionProviderMap 은 각 권한에 대해 해당 권한이 왜 필요한지를 설명해주는 역할을 제공하기 위해 설정된 맵
  • 모든 권한이 승인된 경우 onPermissionResulttrue 값으로 호출
  • 하나 이상의 권한이 거부된 경우 RevokedPermissionsDialog를 호출하여 거부된 권한들에 대한 처리를 시작

Permission 인터페이스:

  1. 맵의 구성:
    • 키(Key): 권한의 문자열 이름. ex) Manifest.permission.ACCESS_FINE_LOCATION 같은 Android의 권한 문자열
    • 값(Value): 해당 권한에 대한 설명을 제공하는 PermissionDescriptionProvider의 구현체 ex) 위치 권한(ACCESS_FINE_LOCATION)에 대한 설명을 제공하는LocationPermissionDescriptionProvider 구현체
  2. createPermissionMap 함수:
    • 이 함수는 실행 중인 Android 버전에 따라 다른 permissionDescriptionProviderMap을 반환
    • 만약 실행 중인 Android 버전이 TIRAMISU 이상이라면, 파티런 프로젝트 기준으로 알림 권한(Manifest.permission.POST_NOTIFICATIONS)와 위치 권한(Manifest.permission.ACCESS_FINE_LOCATION)에 대한 설명을 모두 포함하는 맵을 반환한다.
    • 그렇지 않다면, 오직 위치 권한에 대한 설명만을 포함하는 맵을 반환

  1. PermissionDescriptionProvider 인터페이스:
    • 권한에 대한 설명을 제공하기 위한 메서드들로 구성되어 있다.
    • getTitle(context: Context): 해당 권한의 제목 반환
    • getDescription(context: Context, isPermanentlyDeclined: Boolean): 해당 권한의 설명을 반환. 만약 사용자가 권한 요청을 영구적으로 거부했다면(isPermanentlyDeclinedtrue인 경우), 추가적인 설명을 반환하여 권한 요청을 유도한다.
    • NotificationPermissionDescriptionProviderLocationPermissionDescriptionProvider는 이 인터페이스를 구현하여, 알림과 위치 권한에 대한 사용자에게 보여줄 설명을 제공

정리하면 , permissionDescriptionProviderMap은 권한 요청의 사용자 경험을 향상시키기 위해 설계된 인터페이스로, 사용자에게 각 권한이 왜 필요한지 명확하게 설명함으로써 사용자가 권한 요청을 승인하도록 유도한다.


거부된 권한 처리:

  • RevokedPermissionsDialog: 현재 거부된 권한들 중 마지막 권한(lastRevokedPermission)에 대해 사용자에게 다이얼로그를 표시 → 여기서 마지막 권한을 요청하는 이유는 다음과 같다. 한 번에 하나의 퍼미션만을 처리하기 위한 다이얼로그를 띄워야 하므로 for문 대신 lastOrNull() 처리
    1. 사용자 경험: 연속적으로 여러 개의 권한 요청 다이얼로그를 띄우는 것은 사용자 경험에 좋지 않다. 사용자는 다수의 연속적인 요청에 당황하거나 귀찮아 할 수 있기에 한 번에 하나의 요청만 처리하도록 구현하였다.
    2. 단순성: 한 번에 여러 개의 권한 요청 다이얼로그를 띄워서 동시에 처리하려면 추가적인 로직이나 상태 관리가 필요할 수 있지만, 한 번에 하나의 요청만 처리함으로써 해당 권한 요청에 집중할 수 있고 전체적인 구현의 단순화 이점을 얻을 수 있다.
  • 사용자에게 권한의 중요성을 설명하고, 권한 설정 페이지로 이동하거나 다시 권한 요청을 할 수 있는 선택지를 제공 ex)RevokedPermissionsDialog 함수에서 permissionDescriptionProviderMap을 사용하여 거부된 권한마다 사용자에게 적절한 설명과 함께 권한 요청 다이얼로그를 표시

권한 요청 다이얼로그 표시:

  • ShowPermissionDialog: 사용자에게 권한 요청 다이얼로그를 표시하며, 거부된 경우 권한의 중요성을 알려주고, onGoToAppSettingsClick을 통해 설정 스크린으로 이동하거나 다시 권한 요청을 할 수 있는 옵션을 제공한다.

데모

https://github.com/SWM-KAWAI-MANS/party-run-application/pull/140

  1. 의도적으로 위치 권한과 알람 권한을 거부
  2. 필수 권한이 필요한 ‘매칭 잡기’ 기능을 사용하기 위해 버튼 클릭 시 권한 확인
  3. 알람 권한 설정
  4. 위치권한 설정
  5. ‘매칭 잡기’ 기능 수행
profile
https://github.com/nohjunh

0개의 댓글