본문 바로가기
Android

[깡쌤의 안드로이드 프로그래밍 with 자바 - 2022 - 쌤즈] 정리 15 - 퍼미션 허용

by 들풀민들레 2022. 5. 9.

책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.

 

if(ContextCompat.checkSelfPermission(this,
	Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){
		//...
}
본 글은 [깡쌤의 안드로이드 프로그래밍 with 자바 - 2022 - 쌤즈] 의 내용을 발췌한 것입니다.
좀더 자세한 내용은 책 혹은 인강(www.ssamz.com)을 통해 확인해 주세요.

 

 

7.1.2. 퍼미션 허용


앞에서 살펴본 퍼미션과 관련된 내용은 API Level 1부터 제공되었던 내용이고 지금도 유효합니다.
<permission>으로 보호된 기능을 이용하는 곳에서는 <uses-permission>을 선언해야 실행할
때 에러가 발생하지 않습니다. 그런데 퍼미션 내용이 안드로이드 6.0 (API Level 23)부터 변화가
생겼습니다. 6.0 이전까지 퍼미션은 일종의 개발자 신고제였습니다. 사용자에게 위험 부담이 큰
퍼미션이라도 개발자가 AndroidManifest.xml 파일에 <uses-permission>으로 등록만 하면
실행하는 데 문제가 없었습니다. 즉, <uses-permission>을 이용하여 사용자에게 이 앱이 어떤 기능을
이용하는지 알려줄 수 있지만, 사용자가 거부할 수 없는 상황이었습니다.
예로 사용자가 간단한 메모장 앱을 설치했다고 가정해 봅시다. 메모장 앱에서 사용자 위치를 추적하고
있습니다. 그런데 사용자 관점에서는 메모장 앱이 왜 내 위치를 추적하는 거지? 이해가 안 될 수도
있습니다. 위치와 관련된 어떤 서비스도 제공하지 않으면서 메모장 앱이 자신의 위치를 추적하는 게
기분 나쁠 수도 있습니다. 그래서 사용자는 메모장 앱에서의 위치 추적을 못 하게 막고 싶습니다.

 

그런데 6.0 이전 스마트폰에서는 사용자가 이 퍼미션을 거부할 수 없었습니다. 개발자가 자신의 코드에
<uses-permission>으로 부여하면 그냥 실행되는 일종의 신고제였기 때문입니다. 그런데 안드로이드
6.0부터는 사용자가 퍼미션을 거부할 수 있게 변경되었습니다.

 

그림은 카카오맵의 권한 화면입니다. 사용자가 앱의 퍼미션을 확인하는 것뿐 아니라, 직접 조정할
수도 있습니다. 문제는 사용자가 위 화면에서 퍼미션을 거부해버리면 AndroidManifest.xml 파일에
<uses-permission>이 선언 안 된 것처럼 된다는 점입니다. 아무리 개발자가 <uses-permission>을
추가했더라도 사용자가 거부하면 위치 추적이 안 됩니다. 그러므로 AndroidManifest.xml 파일의
<uses-permission> 선언은 당연하고, 앱 설치 후 사용자가 퍼미션을 거부하는 상황을 고려해야
합니다.
사용자가 퍼미션을 거부하는 상황을 고려해서 프로그램을 작성한다면, 가장 먼저 현시점에 퍼미션
상태를 확인하는 코드가 들어가야 합니다. checkSelfPermission () 함수를 이용하면 퍼미션의 상태를
확인할 수 있습니다.

 

int checkSelfPermission (Context context, String permission)

 

두 번째 매개변수가 퍼미션의 이름이며, 이 함수의 반환값은 둘 중 하나입니다.

  • PERMISSION_GRANTED: 퍼미션이 부여된 상태
  • PERMISSION_DENIED: 퍼미션이 부여되지 않은 상태

 

checkSelfPermission () 함수가 PERMISSION_GRANTED 값을 반환한다면, 퍼미션이 부여된
것이므로 관련 기능을 실행하면 됩니다.

 

if(ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){
//...
}

만일 퍼미션이 부여되지 않았다면 기능 수행 시 에러가 발생합니다. 그래서 사용자에게 퍼미션
허용을 요청해야 합니다. 그런데 사용자가 퍼미션을 허용하려고 환경설정의 권한 화면으로 가는
건 앱을 벗어나야 해서 상당히 귀찮을 수 있습니다. 따라서 앱 안에서 퍼미션 허용 여부를 묻는
대화상자(Dialog)를 띄워주는 게 좋습니다.

 

위 그림은 앱에서 위치 정보 액세스 퍼미션을 부여하지 않은 상태에서 실행한 화면입니다. 이처럼
퍼미션이 부여되지 않았다면 앱 내부에서 대화상자를 띄워 퍼미션 허용을 요청해야 합니다. 코드로 직접
퍼미션을 부여할 수는 없습니다. 코드에서는 대화상자를 띄우는 일밖에 못 합니다.
퍼미션 허용 여부를 묻는 대화상자는 시스템 다이얼로그이고, 사용자가 이곳에서 거부 혹은 허용을
선택하게 됩니다. 사용자로부터 결과를 되돌려 받을 때 사용하는 ActivityResultLauncher로 퍼미션
허용을 요청합니다. ActivityResultLauncher는 이후 인텐트를 다룰 때 다시 한번 설명하도록
하겠습니다.

 

우선, ActivityResultLauncher는 registerForActivityResult () 함수에 의해서 만들어집니다.

 

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

registerForActivityResult ( ) 함수는 2개의 매개변수를 갖습니다. 첫 번째 매개변수는
ActivityResultContract 타입의 객체로, 어떤 요청인지를 표현하기 위해서 사용됩니다. 다양한 요청을
표현하는 서브 클래스가 있으며, 퍼미션을 요청할 때는 RequestPermission을 사용합니다. 두 번째
매개변수는 결과를 받았을 때 호출하는 콜백입니다.

 

ActivityResultLauncher<String> permissionLauncher
	= registerForActivityResult( new ActivityResultContracts.RequestPermission(), isGranted -> {
		if (isGranted) {
			Log.d("kkang","granted...");
		} else {
			Log.d("kkang","denied...");
		}
});

ActivityResultLauncher 객체를 생성하면, launch () 함수를 호출하여 필요한 요청을 할 수 있습니다

 

permissionLauncher.launch("android.permission.ACCESS_FINE_LOCATION");

요청의 결과가 registerForActivityResult () 함수의 두 번째 매개변수에 등록된 콜백이 호출되면서
전달됩니다.

 

책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.