Android

Android - 런타임 권한(Permission) 요청과 처리 방법

임베디드 친구 2024. 11. 24. 10:35
반응형

안드로이드 애플리케이션 개발에서는 사용자 데이터를 보호하기 위해서 권한 관리가 필수적입니다. Android 6.0 (API 23)부터는 권한이 설치 시점이 아닌, 애플리케이션 실행 중 런타임에서 요청되어야 합니다. 이번 포스팅에서는 안드로이드에서 런타임 권한을 요청하고 처리하는 방법에 대해 설명하고, 예제 코드를 통해 쉽게 이해할 수 있도록 도와드리겠습니다.

런타임 권한 개요

런타임 권한은 앱이 특정 작업을 수행하기 위해 사용자의 동의를 필요로 할 때, 앱 실행 중에 사용자에게 요청하는 권한입니다. 예를 들어, 카메라 사용, 위치 정보 접근, 연락처 읽기 등의 작업을 수행하려면 해당 권한을 사용자로부터 동적으로 허용받아야 합니다.

권한을 요청하는 절차는 다음과 같습니다:

  1. 권한을 선언하기 (AndroidManifest.xml 파일에 필요 권한 추가)
  2. 권한이 부여되었는지 확인하기
  3. 권한이 없을 경우, 권한을 사용자에게 요청하기
  4. 사용자의 응답에 따라 동작 처리하기

이제 코틀린으로 권한 요청 예제를 보면서 구체적인 방법을 알아보겠습니다.

AndroidManifest.xml 파일에 권한 선언

런타임 권한을 요청하기 전에, 먼저 AndroidManifest.xml 파일에 해당 권한을 선언해야 합니다. 예를 들어, 위치 정보를 사용하려면 아래와 같이 권한을 선언합니다:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.runtimepermission">

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

</manifest>

런타임 권한 요청 예제 (Kotlin)

아래는 코틀린으로 위치 정보 권한을 런타임에서 요청하고 처리하는 간단한 예제입니다.

package com.example.runtimepermission

import android.content.pm.PackageManager
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import android.widget.Toast

class MainActivity : AppCompatActivity() {

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

        // 권한이 부여되어 있는지 확인합니다.
        if (ContextCompat.checkSelfPermission(
                this,
                android.Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            // 권한이 부여되지 않았을 경우, 권한을 요청합니다.
            requestLocationPermission()
        } else {
            // 권한이 이미 부여된 경우 위치 서비스 사용 로직을 실행합니다.
            startLocationService()
        }
    }

    // 권한 요청 함수
    private fun requestLocationPermission() {
        // 권한 요청 런처를 이용해 권한을 요청합니다.
        val requestPermissionLauncher =
            registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
                if (isGranted) {
                    // 권한이 허용된 경우 위치 서비스 사용 로직을 실행합니다.
                    startLocationService()
                } else {
                    // 권한이 거부된 경우 사용자에게 메시지를 표시합니다.
                    Toast.makeText(this, "위치 권한이 필요합니다.", Toast.LENGTH_SHORT).show()
                }
            }

        // 권한 설명이 필요한 경우, 사용자에게 설명을 제공합니다.
        if (ActivityCompat.shouldShowRequestPermissionRationale(
                this,
                android.Manifest.permission.ACCESS_FINE_LOCATION
            )
        ) {
            Toast.makeText(this, "이 앱은 위치 정보를 사용해야 정상적으로 동작합니다.", Toast.LENGTH_LONG).show()
        }

        // 권한 요청 실행
        requestPermissionLauncher.launch(android.Manifest.permission.ACCESS_FINE_LOCATION)
    }

    // 위치 서비스 사용 로직
    private fun startLocationService() {
        Toast.makeText(this, "위치 서비스가 시작되었습니다.", Toast.LENGTH_SHORT).show()
        // 위치 서비스 코드 구현
    }
}

코드 설명

  1. 권한 확인
     if (ContextCompat.checkSelfPermission(
             this,
             android.Manifest.permission.ACCESS_FINE_LOCATION
         ) != PackageManager.PERMISSION_GRANTED
     ) {
         requestLocationPermission()
     }
  2. 먼저 ContextCompat.checkSelfPermission() 메서드를 사용하여 권한이 이미 부여되었는지 확인합니다. 만약 PackageManager.PERMISSION_GRANTED가 반환되지 않는다면, 권한이 아직 부여되지 않은 상태이므로 권한을 요청해야 합니다.
  3. 권한 요청
     val requestPermissionLauncher =
         registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
             if (isGranted) {
                 startLocationService()
             } else {
                 Toast.makeText(this, "위치 권한이 필요합니다.", Toast.LENGTH_SHORT).show()
             }
         }
  4. registerForActivityResult()ActivityResultContracts.RequestPermission()을 사용하여 권한을 요청합니다. 이 함수는 권한 요청 결과를 처리하는 콜백을 제공합니다. 사용자가 권한을 허용하면 위치 서비스를 시작하고, 거부할 경우 메시지를 표시합니다.
  5. 권한 설명
     if (ActivityCompat.shouldShowRequestPermissionRationale(
             this,
             android.Manifest.permission.ACCESS_FINE_LOCATION
         )
     ) {
         Toast.makeText(this, "이 앱은 위치 정보를 사용해야 정상적으로 동작합니다.", Toast.LENGTH_LONG).show()
     }
  6. ActivityCompat.shouldShowRequestPermissionRationale() 메서드를 사용하면 사용자가 권한 요청을 거부했을 때 권한이 필요한 이유를 설명할 수 있습니다. 이를 통해 사용자가 권한을 허용해야 하는 이유를 더 명확히 이해할 수 있도록 도와줍니다.
  7. 위치 서비스 실행
     private fun startLocationService() {
         Toast.makeText(this, "위치 서비스가 시작되었습니다.", Toast.LENGTH_SHORT).show()
         // 위치 서비스 코드 구현
     }
  8. 권한이 허용되었을 때 실행할 위치 서비스 코드를 startLocationService() 함수에 구현합니다. 이 부분에는 실제 위치 정보를 가져오는 로직을 추가할 수 있습니다.

주의사항

  • 사용자가 권한 요청을 거부하고, "다시 묻지 않기" 옵션을 선택할 수 있습니다. 이 경우, 설정 화면에서 수동으로 권한을 부여할 수 있도록 사용자에게 안내해야 합니다.
  • Android 11(API 30)부터는 민감한 권한(위치, 카메라 등)에 대해 "이번만 허용" 옵션이 추가되었습니다. 이에 대한 추가 처리가 필요할 수 있습니다.

결론

이번 포스팅에서는 안드로이드 런타임 권한의 개념과 이를 처리하는 방법에 대해 알아보았습니다. 런타임 권한 관리는 사용자 데이터를 보호하고, 앱의 보안을 높이기 위한 필수적인 요소입니다. 코틀린 예제를 통해 권한 요청과 처리를 구현하는 방법을 이해하셨기를 바랍니다.

권한 관리에 대한 더 많은 정보를 원하시면, Android 공식 문서를 참고하시기 바랍니다.

반응형