JEP's Diary

Android 6.0 마시멜로 대응(런타임 권한 모델) 본문

Development/Android

Android 6.0 마시멜로 대응(런타임 권한 모델)

지으니88 2016. 3. 14. 00:01

Android 6.0 마시멜로 대응(런타임 권한 모델)

안드로이드 6.0부터는 인터넷같은 사용권한은 기본권한에 포함되어 사용자의 동의를 구하지 않아도 되지만, 기기를 제어할 수 있는 권한은 사용자의 동의를 구해야만 한다. 또한 사용자가 동의 했다가 다시 권한을 취소 할 수 있다. 이에 따른 퍼미션 대응이 필요!


런타임 권한 모델

기존처럼 앱이 설치될 때 필요한 권한을 요청하는 것이 아니라, 새로운 런타임 퍼미션 모델에 따라, 앱 실행 중에 필요한 권한을 요청해야 한다.

(타겟 API23 이상으로 빌드된 앱이 안드로이드 6.0에서 동작하는 경우)


디자인 가이드라인

올바른 순간에 권한을 요청하는 것이 중요한데, 구글 디자인 사이트에는 새로운 런타임 권한 모델을 적용할 때 참고할 수 있는 UX패턴이 정리 되어 있다.

언제 권한을 요청해야 하는지, 왜 권한이 필요한지 어떻게 잘 설명할 수 있는지, 사용자가 권한 요청을 거부한 경우 어떻게 해야 하는지 상황에 따른 가이드라인을 제시하고 있다.


서포트 라이브러리

앱 내에서 런타임 권한을 요청해야 하는 경우, 하위 호환성 걱정 없이 새로운 API를 할 수 있도록 서포트라이브러리에 관련된 API가 추가 되었다.(support-v4 library, revision 23)

ContextCompat.checkSelfPermission() : 현재 앱이 특정 권한을 갖고 있는지 확인 가능

ActivityCompat.requestPermission() : 안드로이드 시스템이 사용자에게 권한 요청 대화창을 표시 하도록.

ActivityCompat.shouldShowRequestPermissionRationale() : 사용자가 이전에 권한 요청을 거부한 경우에 true반환. 이 경우, 권한 요청을 위한 대화창에는 '다시 묻지 않기' 체크박스와 함께 표시된다. 사용자가 이를 선택하면 이후에 앱이  requestPermissions 메서드를 호출해도 권한 요청 대화창이 표시되지 않고, 바로 사용자가 해당 권한을 거부할 때와 동일 하게 콜백 함수가 호출된다.


Permission

아래에 해당하는 퍼미션은 앞으로 권한 획득 창을 뛰어 권한 획득을 받아야만 한다.

Table 1. Dangerous permissions and permission groups.

Permission GroupPermissions
CALENDAR
CAMERA
CONTACTS
LOCATION
MICROPHONE
PHONE
SENSORS
SMS
STORAGE


권한 획득을 위한 주요 API

1. 권한 획득하기 전 권한 유효성 체크

checkSelfPermission(String) != PackageManager.PERMISSION_GRANTED

현재 앱이 특정 권한을 갖고 있는지 확인 가능


2. 설명이 필요할 경우 처리

 shouldShowRequestPermissionRationale(String)

권한 획득이 필요한 이유를 설명해야 한다면 다음 옵션을 추가하여 별도 처리가 가능. 사용자가 이전에 권한 요청을 거부한 경우에 true반환. 이 경우, 권한 요청을 위한 대화창에는 '다시 묻지 않기' 체크박스와 함께 표시된다. 사용자가 이를 선택하면 이후에 앱이  requestPermissions 메서드를 호출해도 권한 요청 대화창이 표시되지 않고, 바로 사용자가 해당 권한을 거부할 때와 동일 하게 콜백 함수가 호출된다.


3. 권한 획득을 위한 API

 Activity.requestPermissions(String[], int) 

위의 권한 중 Group과 permission 2가지를 선택적으로 던질 수 있다. 한 번에 1개가 아닌 String[] 배열로 넘겨 한 번에 필요한 permission을 한 번에 획득할 수 있다.

 

4. requestPermission의 경우 callback으로 return 됩니다. 

 onRequestPermissionResult(int, String[], int[])

 권한 획득에 대한 성공/실패에 대한 정보를 담은 callback. 다음 함수 내에서 배열로 전달되므로 필요한 퍼미션이 잘 받아졌는지 확인하여 이후 처리가 가능.


예제

퍼미션 체크 부분

1
2
3
4
5
6
7
8
9
10
11
12
13
private void checkPermission() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        // 권한이 없을 경우
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
            // 사용자가 임의로 권한을 취소시킨 경우
            // 권한 재요청
            ActivityCompat.requestPermissions(thisnew String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
        } else {
            // 권한 요청 (최초 요청)
            ActivityCompat.requestPermissions(thisnew String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
        }
    }
}
cs


퍼미션 체크 후 콜백 메서드 부분

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0== PackageManager.PERMISSION_GRANTED) {
                // 동의 및 로직 처리
                Log.e(TAG, ">>> 동의함.");
            } else {
                // 동의 안함
                Log.e(TAG, ">>> 동의를 해주셔야 합니다.");
            }
            return;
        }
        // 예외 케이스
    }
}
cs


참고. 

http://googledevkr.blogspot.kr/2015/09/android60runtimepermission.html

https://developer.android.com/intl/ko/training/permissions/requesting.html


'Development > Android' 카테고리의 다른 글

Android ViewModel  (0) 2018.08.08
Android Unit Tests(단위 테스트) - Local Unit Tests  (1) 2016.03.15
Realm 모바일 데이터 베이스(Android)  (0) 2016.03.13
안드로이드 샘플 불러오기  (0) 2015.11.25
Recycler + Switch Button  (0) 2015.11.25