확 바뀐 Android 6.0 Marshmallow 권한관리를 소개합니다.

안드로이드가 6.0 Marshmallow로 업데이트되면서 많은 변화가 일어났지만, 개발자에게 가장 크게 느껴지는 변경점은 바로 권한 부여 방식일 겁니다. Marshmallow에서 어떤 변화가 일어났는지 간략히 살펴보고 특히 권한 부여가 어떻게 바뀌었는지 소개합니다.


소개

Android 6.0 Marshmallow 릴리즈에서는 많은 기능 변화가 일어났습니다. 배터리 효율이 개선됐으며, 제어 및 보안에서 대대적인 변경이 발생했습니다. 지문을 사용한 간편 보안이 적용됐고, 선택적인 권한 부여 방식을 채택했습니다. Now on Tap 기능도 출시될 예정입니다. 배터리 효율 개선, 지문 보안, 그리고 아직 선보이기 전인 Now on Tap 기능은 사용자들이 기꺼워할 편리한 기능으로 보입니다. 그렇다면 선택적인 권한 부여는 어떨까요?

선택적인 권한 부여

앱의 권한이 부여되는 시점이 앱 설치 단계였던 이전 버전과 달리, Marshmallow에서는 특정 권한이 필요한 시점, 즉 Runtime permission 방식으로 권한을 획득해야 합니다. 다시 말하자면, 6.0 미만 버전에서는AndroidManifest.xml에 권한을 설정하는 것만으로 영구적으로 앱의 권한을 선택할 수 있었지만, 6.0 이상에서는 비동기, 콜백 형태로 앱 실행 시에 앱 권한을 일일이 획득해야 한다는 뜻입니다. 특히 사용자가 부여한 권한을 언제든지 시스템 설정에서 취소할 수 있으므로, 매번 특정 권한이 필요한 기능을 실행하기 전에 반드시 권한 획득 여부를 확인해야 한다는 점이 까다롭습니다.

이런 개발 뉴스를 더 만나보세요

앱 권한 획득 순서

비동기, 콜백 방식으로 runtime 시에 권한을 획득하는 순서를 간단히 정리해 봤습니다.

먼저 AndroidManifest.xml에 권한을 설정한 후, PermissionChecker의 checkSelfPermission 메서드를 통해 특정 권한이 이미 획득됐는지 확인합니다.

권한이 획득되었다면 특정 권한을 사용하는 기능을 바로 수행할 수 있지만, 획득되지 않았다면 ActivityCompat의 requestPermissions 메서드로 권한을 요청해야 합니다.

사용자가 이 권한 요청을 처음 만날 때 새 process 팝업이 뜨며, 사용자가 이를 수락하면 역시 권한 사용 기능을 수행할 수 있게 됩니다. 이 권한 설정 팝업은 표준 dialog box로 커스터마이징이 불가능합니다.

권한 요청 거절 이후의 앱 권한 획득 순서

만약 사용자가 권한 요청 팝업에서 수락을 누르지 않으면 문제가 조금 복잡해집니다. 일단 사용자가 권한 요청을 한 번 거절하면 ActivityCompat의 shouldShowRequestPermissionRationale 메서드 반환 값이 true가 됩니다.

사용자에게 제시되는 팝업 모양도 조금 변하는데 다시는 이 팝업을 띄우지 않도록 설정하는 체크박스가 추가됩니다. 만약 사용자가 이 체크박스를 선택하고 거절을 누른다면, 앱 상에서 다시는 권한 설정 팝업을 보여줄 수 없고, 사용자가 직접 설정에서 앱을 찾아 해당 권한을 부여하기 전까지 영영 그 기능을 사용할 수 없습니다.

따라서 권한 요청 거절이 거절된 다음에는 Toast나 dialog 등을 동원해서 특정 기능이 왜 필요한지 설명하는 것이 좋습니다.

Toast.makeText(this, "앱 실행을 위해서는 전화 관리 권한을 설정해야 합니다", 
				Toast.LENGTH_LONG).show();

권한 설정 예제

다음은 안드로이드 개발자 사이트에서 소개하는 권한 설정 예제입니다.

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {

        // Show an explanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.

    } else {
        // No explanation needed, we can request the permission.
        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

앞서 설명한 대로 두 번째 if 절 안에 user에게 비동기적으로 권한 설정이 왜 필요한지 알려준 후 다시 권한을 요청하라는 설명이 포함돼 있습니다.

권한 획득 콜백

OnRequestPermissionResult는 android.support.v4.app.ActivityCompat의 메서드로 권한 요청의 결과를 받습니다.

한 개 이상의 권한 요청을 할 경우 액티비티에서 해당 권한에 대한 요청 값을 int로 지정할 수 있으며, onRequestPermissionsResult에서는 이 요청값으로 어떤 권한을 획득했는지 구분합니다.

public final int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 1;
public final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 2;
@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

물론 Marshmallow의 선택적인 권한 부여가 코드 라인 수를 늘리고 앱의 기능을 제한할 가능성이 있다는 부작용이 있지만, 사용자가 선택할 수 있는 폭을 넓힌다는 점에서 결국 안드로이드가 지향해야 하는 방향일 것으로 보입니다. 더 자세한 내용은 안드로이드 개발자 튜토리얼을 확인해 주세요.

추가로 일어보기

조금더 많은 예제 코드를 Permissions – Part 1 에서 확인하실 수 있습니다.

컨텐츠에 대하여

이 컨텐츠는 저자의 허가 하에 이곳에서 공유합니다.


Eunjoo Im

Realm Asia 팀에서 일하는 임은주입니다. iOS와 안드로이드 개발자로, 현재 Realm의 기술 컨텐츠 생산 및 관리에 주력하고 있습니다.

4 design patterns for a RESTless mobile integration »

close