Core areas/Permissions/Request app permissions/Request runtime permissions

2024. 5. 21. 16:33IT/Android

728x90

앱에서 알림을 전송하려면 Android 13(API 수준 33) 이상에서는 사용자에게 런타임 권한을 명시적으로 얻어야만 한다.

매니페스트 파일에서의 알림 권한 선언

<manifest ...>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <application ...>
        ...
    </application>
</manifest>

 

+권한 그룹 선언

<permission-group android:description="string resource"
                  android:icon="drawable resource"
                  android:label="string resource"
                  android:name="string" />

 

런타임 권한 요청

// Declare the launcher at the top of your Activity/Fragment:
private val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission(),
) { isGranted: Boolean ->
    if (isGranted) {
        // FCM SDK (and your app) can post notifications.
    } else {
        // TODO: Inform user that that your app will not show notifications.
    }
}

private fun askNotificationPermission() {
    // This is only necessary for API level >= 33 (TIRAMISU)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) ==
            PackageManager.PERMISSION_GRANTED
        ) {
            // FCM SDK (and your app) can post notifications.
        } else if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
            // TODO: display an educational UI explaining to the user the features that will be enabled
            //       by them granting the POST_NOTIFICATION permission. This UI should provide the user
            //       "OK" and "No thanks" buttons. If the user selects "OK," directly request the permission.
            //       If the user selects "No thanks," allow the user to continue without notifications.
        } else {
            // Directly ask for the permission
            requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
        }
    }
}

*ContextCompat.checkSelfPermission() : 해당 권한이 앱에 이미 부여되었는지 확인하는 메서드로, PERMISSION_GRANTER 혹은 PERMISSION_DENIED를 반환한다.

*shouldShowRequestPermissionRationale() : 해당 권한이 왜 필요한지 사용자에게 UI로 설명하기 위한 메서드로, 설명에 대한 사용자의 선택에 따라 Boolean 값을 반환한다.

*registerForActivityResult() : 권한을 요청하는 requestPermission() 메서드를 사용하고 그 결과를 처리하기 위해 onRequestPermissionsResult()로 구현했던 과거와 달리, 권한 요청과 그 결과에 대한 콜백을 정의할 수 있는 런처를 생성한다. 생성된 런처를 사용하여 launch() 메서드를 호출하면 시스템 권한 대화 상자를 출력할 수 있다.

*ActivityResultContracts.RequestPermission : 단일 권한을 요청하기 위해 사용되는 클래스로, 다중 권한을 요청한다면 RequestMultiplePermission을 고려할 수 있다.

 

런타임 권한 요청 기본 원칙

1. 권한 요청 시점 : 권한이 필요한 작업과 상호작용할 때 해당 권한을 요청한다.

2. 비차단 요청 : 권한 요청 다이얼 로그가 나타났을 때, 사용자가 즉시 응답하지 않고도 앱을 계속 사용할 수 있어야 한다.

3. 권한 거부 시 대처 : 권한을 거부하는 경우, 권한이 필요한 해당 작업만 제외하고 앱을 계속 사용할 수 있어야 한다.

4. 시스템 동작 가정 금지 : 권한에 따른 안드로이드 시스템의 동작을 정확히 파악하여 권한을 요청하도록 한다.

 

권한 요청 워크 플로

1. 매니페스트에서 필요한 권한 선언.

2. 특정 작업과 알맞은 권한을 설계.

3. 사용자가 호출하면 해당 권한을 요청.

4. 사용자가 이미 권한을 부여 했는지 확인.

5. 권한을 요청하는 이유를 UI로 설명.

6. 필요한 권한을 요청.

7. 권한에 대한 사용자의 응답 확인.

8. 비공개 데이터 엑세스.

 

사용자가 권한 다이얼 로그에서 가능한 동작

1. 허용 : 모든 알림 채널이 허용되고, 포그라운드 서비스의 알림이 게시된다.

2. 허용 안함 : 예외로 구별되는 앱이 아니라면 알림이 차단된다.

3. 다이얼 로그를 스와이프하여 제거 : 알림 권한의 상태가 변경되지 않는다.

 

+디바이스에서 앱의 알림 설정을 메서드를 통해 확인할 수 있다.

val areNotificationsEnabled = NotificationManagerCompat.from(context).areNotificationsEnabled()
if (areNotificationsEnabled) {
    // 알림이 활성화됨
} else {
    // 알림이 비활성화됨, 사용자에게 알림 설정을 안내
}

 

사용자의 위치 정보에 접근하려면 런타임 권한을 명시적으로 요청받야아만 한다.

포그라운드 위치

네비게이션, 음악 재생 앱 처럼 백그라운드로 이동해도 계속 실행되는 앱을 포그라운드 서비스라 하는데, 해당 기능을 지원하는 앱은 알림을 통해 서비스가 동작하고 있음을 사용자에게 알려야 하고 앱이 위치 정보를 수신하고 있다면 포그라운드 위치 정보 액세스 권한을 얻어야 한다. 시스템에 의해 우선 순위가 높게 지정되어 있기 때문에 자원 부족 시에도 쉽게 종료되지 않는 특징이 있다. 

 

매니페스트 파일에서의 포그라운드 서비스 유형 선언

<!-- 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>

 

백그라운드 위치

Android 10(API 수준 29) 이상에서는 앱이 백그라운드에서 실행중이면서 위치 정보에 액세스하는 경우, 사용자에게 명시적으로 런타임 권한을 얻어야 한다. 

 

매니페스트 파일에서의 백그라운드 위치 권한 선언

<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>

 

 

권한 목록 : https://developer.android.com/reference/android/Manifest.permission?authuser=0 

서비스 목록 : https://developer.android.com/guide/topics/manifest/service-element?authuser=0&hl=ko#foregroundservicetype

권한 가이드 :

https://developer.android.com/training/permissions/requesting?authuser=0&hl=ko

https://firebase.google.com/docs/cloud-messaging/android/client?hl=ko&authuser=0#kotlin+ktx

728x90