[안드로이드] 다이얼로그와 알림 - 퍼미션 설정하기

·2022년 5월 18일
0

Doit 안드로이드

목록 보기
10/12
post-thumbnail

퍼미션 설정하기

퍼미션(permission)이란 앱의 특정 기능에 부여하는 접근 권한을 말한다. 내가 개발하는 앱이 다른 앱이나 안드로이드 시스템에서 보호하는 특정 기능을 이용할 때 퍼미션 사용을 설정해야 한다.

퍼미션 설정과 사용 설정

앱의 컴포넌트를 보호하고 싶을 때 매니페스트 파일에서 퍼미션을 설정할 수 있고, 퍼미션으로 보호받는 앱을 이용하는 외부 앱은 매니페스트 파일에 해당 퍼미션을 사용하겠다고 설정해야 한다.

매니페스트 파일에 퍼미션을 설정할 때는 <permission> 태그와 다음 속성을 사용한다.

  • name : 퍼미션의 이름
  • label, description : 퍼미션을 설명
  • protectionLevel : 보호 수준
  • 퍼미션 설정
<permission android:name="com.example.permission.TEST_PERMISSION"
        android:label="Test Permission"
        android:description="@string/permission_desc"
        android:protectionLevel="dangerous" />
  • normal : 낮은 수준의 보호. 사용자에게 권한 허용을 요청하지 않아도 된다.
  • dangerous : 높은 수준의 보호. 사용자에게 권한 허용을 요청해야 한다.
  • signature : 같은 키로 인증한 앱만 실행한다.
  • signatureOrSystem : 안드로이드 시스템 앱이거나 같은 키로 인증한 앱만 실행한다.

protectionLevel의 속성값은 보통 normal, danger, signature를 사용한다. normal은 퍼미션 사용 설정을 해야 하지만 사용자에게 권한 허용을 요청하지 않아도 되고 dangerous는 퍼미션 사용 설정은 물론 사용자에게도 권한 허용을 요청해야 한다.

  • 퍼미션 사용 설정
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

매니페스트 파일에 <permission>을 설정했다고 해서 컴포넌트가 보호되지 않는다. <permission>을 설정한 다음 이 퍼미션으로 보호하려는 컴포넌트에 적용해야 한다. 퍼미션을 컴포넌트에 적용할 때는 android:permission 속성을 이용한다.

  • 컴포넌트에 퍼미션 적용
<activity android:name=".OneActivity" android:permission="com.example.TEST_PERMISSON">
        <intent-filter>
            <action android:name="android.intent.action.PICK" />
        </intent-filter>
</activity>

이제 이 컴포넌트는 com.example.TEST_PERMISSON에 의해 보호되며 이 컴포넌트를 이용하는 곳에서는 매니페스트 파일에 <uses-permission>을 선언해야 정상으로 실행된다.

이처럼 외부 앱과 연동할 때 퍼미션 사용을 설정해야 하지만 안드로이드 시스템에서 보호하는 기능을 사용할 때도 매니페스트 파일에 사용 설정을 해야 한다. 시스템이 보호하는 기능은 대표적으로 다음과 같다.

  • ACCESS_FINE_LOCATION : 위치 정보 접근
  • ACCESS_NETWORK_STATE : 네트워크 정보 접근
  • ACCESS_WIFI_STATE : 와이파이 네트워크 정보 접근
  • BATTERY_STATS : 배터리 정보 접근
  • BLUETOOTH : 블루투스 장치에 연결
  • BLUETOOTH_ADMIN : 블루투스 장치를 검색하고 페어링
  • CAMERA : 카메라 장치에 접근
  • INTERNET : 네트워크 연결
  • READ_EXTERNAL_STORAGE : 외부 저장소에서 파일 읽기
  • WRITE_EXTERNAL_STORAGE : 외부 저장소에 파일 쓰기
  • READ_PHONE_STATE : 전화기 정보 접근
  • SEND_SNS : 문자 메시지 발신
  • RECEIVE_SMS : 문자 메시지 수신
  • RECEIVE_BOOT_COMPLETED : 부팅 완료 시 실행
  • VIBRATE : 진동 울리기

퍼미션 허용 확인

API 레벨 23 버전부터 허가제가 되었다. 개발자가 <uses-permission> 으로 선언했더라도 사용자가 이를 거부할 수 있다.
만약 사용자가 앱의 권한 설정에서 특정 퍼미션을 거부하면 <uses-permission>을 선언하지 않은 것과 같으며 앱에서는 해당 기능을 이용할 수 없다. 결국 API 레벨 23부터는 매니페스트 파일에 <uses-permission>을 선언하는 것뿐만 아니라 앱을 실행할 때 사용자가 퍼미션을 거부했는지 확인하고 만약 거부했으면 다시 퍼미션을 허용해 달라고 요청해야 한다.

앱을 설치한 후 초기 퍼미션은 모두 거부 상태이다. 따라서 필요한 권한을 허용해 달라고 사용자에게 요청해야 한다.
사용자가 퍼미션을 허용했는지 확인하려면 checkSelfPermission() 함수를 이용한다.

  • 퍼미션 허용 확인 함수
open static fun checkSelfPermission (
	@NonNull context : Context,
    @NonNull permission : String
) : Int

두 번째 매개변수가 퍼미션을 구분하는 이름이며 결괏값은 다음 중 하나의 상수로 전달된다.

  • PackageManager.PERMISSION_GRANTED : 권한을 허용한 경우
  • PackageManager.PERMISSION_DENIED : 권한을 거부한 경우
  • 퍼미션 허용 확인 예
val status = ContextCompat.checkSelfPermission(this, "android.permission.ACCESS_FINE_LOCATION")
if (status == PackageManager.PERMISSION_GRANTED) {
	Log.d("log", "permission granted")
} else {
	Log.d("log", "permission denied")
}

만약 퍼미션을 거부한 상태라면 사용자에게 해당 퍼미션을 허용해 달라고 요청해야 한다. 사용자에게 퍼미션 허용을 요청할 때는 AcitivityResultLauncher 를 이용한다. 이 클래스는 액티비티에서 결과를 돌려받아야 할 때 사용하며 대표적으로 퍼미션 허용 요청과 다른 액티비티를 실행하고 결과를 돌려 받을 때이다.

ActivityResultLauncher 객체는 registerForActivityResult() 함수를 호출해서 만든다.

  • registerForActivityResult() 함수
public final <I, O> ActivityResultLauncher<I> registerForActivityResult (
		@NonNull ActivityResultContract<I, O> contract,
        @NonNull ActivityResultCallback<O> callback)

이 함수는 매개변수가 2개이다. 첫 번째 매개변수는 어떤 요청인지 나타내는 ActivityResultContract 타입 객체이며 다양한 요청에 대응하는 서브 클래스들이 있다. 대표적으로 다른 액티비티를 실행하고 결과를 돌려받을 때는 StartActivityForResult, 퍼미션 허용을 요청할 때는 RequestPermission을 사용한다.

두 번째 매개변수는 결과를 받았을 때 호출되는 콜백이다.

  • 퍼미션 허용 요청 확인
val requestPermissionLauncher = registerForActivityResult(
	ActivityResultContracts.RequestPermission()
    ) { isGranted ->
    if (isGranted) {
    	Log.d("log", "callback, granted...")
    } else {
    	Log.d("log", "callback, denied...")
    }
}

registerForActivityResult() 함수로 ActivityResultLauncher 객체를 만들었다면 필요한 곳에서 ActivityResultLauncher 객체의 launch() 함수를 호출하여 요청을 실행한다.

  • 퍼미션 허용 요청 실행
requestPermissionLauncher.launch("android.permission.ACCESS_FINE_LOCATION")

요청 결과는 registerActivityResult() 함수의 두 번째 매개변수로 등록한 콜백으로 전달된다. 위 예제는 퍼미션 허용 요청과 결과를 받는 방법이었고 액티비티를 실행하고 결과를 돌려받는 방법은 이후에 다루겠다.

profile
SOOP

0개의 댓글