본문 바로가기

Android/개념 및 예제

안드로이드 권한 (런타임 퍼미션) 요청하기 [Kotlin]

권한 요청이란??

안드로이드 앱에서 다른 앱이나 시스템에 영향을 줄 수 있는 권한의 경우 위험한 권한으로 분류되어 사용자에게 사용 요청을 하고, 사용자에게 허가를 받아야 합니다. 사용자에게 권한 사용을 요청해야 하는 권한을 위험 권한, 런타임 권한이라고 합니다.

 

권한을 요청할 때 지켜야 할 주요 원칙 중 하나는 다음과 같습니다.

사용자가 권한이 필요한 기능과 상호작용하기 시작할 때 컨텍스트에 따라 권한을 요청합니다.

즉 앱 시작할 때 앱에 필요한 모든 권한을 요청하는 것이 아니라 사용자가 앱 내에서 특정 기능을 수행할 때 이에 대한 권한을 요청해야 한다는 것입니다. 예를 들어 프로필 사진 업로드를 하려고 할 때 카메라 권한을 요청하는 것과 같습니다.

 

구글에서 권장하는 권한 요청 프로세스는?? 

구글에서 권장하는 권한 요청 워크플로우는 다음과 같습니다.

주의해서 봐야할 부분은 권한을 요청하고 사용자가 거부했을 경우입니다.

사용자가 권한 요청을 거부하면 앱 내에서 권한이 필요한 설명을 하고 다시 권한을 요청해야 합니다.

 

결과 영상

위 영상처럼 권한 사용을 사용자가 거부하면 권한이 필요한 이유를 설명하는 다이어로그를 통해 사용자에게 권한이 필요한 이유를 설명하고 권한 허가를 해달라고 합니다.

 

개발 과정

오디오 권한을 요청하는 과정을 예로 들겠습니다.

1. 메니페스트에 권한을 선언한다.

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

 

2. 권한을 요청합니다.

 

// 요청할 권한
private val requiredPermissions = arrayOf(Manifest.permission.RECORD_AUDIO)

companion object {
        // 권한 요청 코드
        private const val REQUEST_RECORD_AUDIO_PERMISSION = 201
}

 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 사용자에게 오디오 권한 요청하기
        requestPermissions(requiredPermissions, REQUEST_RECORD_AUDIO_PERMISSION)
}

 

3. 권한 요청 결과를 확인합니다.

 override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        // 다음 두 가지 조건을 만족해야 오디오 권한 요청을 사용자가 허가했다고 판단한다.
        // 1. 요청 코드가 requestPermissions()의 파라미터로 전달한 요청코드인 경우
        // 2. 허가한 요청 중 첫 번째 권한을 승인한 경우 (권한이 많으면 grantResults안의 권한을 반복해서 확인해야 함)
        val audioRecordPermissionGranted =
            requestCode == REQUEST_RECORD_AUDIO_PERMISSION &&
                    grantResults.firstOrNull() == PackageManager.PERMISSION_GRANTED

        if (!audioRecordPermissionGranted) {
            // 요청에 대한 이유를 안보여주면 권한 설명 다이어로그를 보여줌
            showPermissionExplanationDialog()
        }

}

 

4. 권한을 허가하지 않은 경우 권한에 대한 설명을 사용자에게 보여줍니다.

private fun showPermissionExplanationDialog() {
        AlertDialog.Builder(this)
            .setMessage("녹음 권한을 켜주셔야지 앱을 사용할 수 있습니다. 앱 설정 화면으로 진입하셔서 권한을 켜주세요.")
            .setPositiveButton("권한 변경하러 가기") { _, _ -> navigateToAppSetting() }
            .setNegativeButton("앱 종료하기") { _, _ -> finish() }
            .show()
}