궁금한게 많은 개발자 노트

[ Android ] AndroidManifest.xml Permission Check 본문

App Development

[ Android ] AndroidManifest.xml Permission Check

궁금한게 많은 개발자 2020. 7. 1. 12:37

https://developer.android.com/training/permissions/requesting?hl=ko

 

앱 권한 요청  |  Android 개발자  |  Android Developers

모든 Android 앱은 액세스가 제한된 샌드박스에서 실행됩니다. 자체 샌드박스 밖에 있는 리소스나 정보를 앱이 사용해야 하는 경우에는 앱이 적절한 권한을 요청해야 합니다. 앱에 권한이 필요하�

developer.android.com

안드로이드에서는 기본적으로 권한이 없는상태에서 앱을 사용하게 되고,
각종 리소스나 정보가 필요할 경우에 적절한 권한을 요청하여 사용해야 한다.
사용하고자 하는 기능이 필요한 적절한 권한을 찾은 후 AndroidManifest.xml에 추가해준다.
아래에 보이는것 처럼 다양한 권한들이 존재하며, 사용자 마다 코딩시에 필요한 권한을 명세

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="custom.android_app">

	...
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    ...
    <uses-permission android:name="android.permission.REBOOT"
        tools:ignore="ProtectedPermissions" />
    ...

 


그러나, AndroidManifest.xml에 명세를 하더라도, 일반적인 custom 앱, 3rd party App에서
사용할 수 있는 권한이 있고
그렇지 않은 권한이 있기에 코드에서 권한이 있는지 확인하고
그에 맞는 동작을 실행하거나, 권한을 얻을 수 있다면 사용자에게 요청하고
그 응답에 맞게 진행시킬 수 있는 방법이 있다.

int permssionCheck = ContextCompat.checkSelfPermission(this,Manifest.permission.REBOOT);

//PackageManager.PERMISSION_GRANTED if you have the permission, 
//                                  or PackageManager.PERMISSION_DENIED if not.

ContextCompat이라는 class를 사용하여 context들의 feature정보를 확인할 수 있다.
그 중 public method인 checkselfPermission를 사용하여 첫번째 인자로 Context를 전달하고,
두번째 인자로는 확인할 권한을 넘겨주어, 해당 권한을 현재 Context에서 사용할 수 있는지 여부를 확인할 수 있다.

대부분의 AndroidManifest.xml에 명세한 권한들이라면 GRANTED를 반환 받겠지만,
system 권한이 필요한 REBOOT과 같은 권한은 위에서 언급한 일반적인 앱, 3rd party App에서는 사용할 수 없다.
그러므로, 위의 예제에서 보이는 REBOOT과 같은 권한들은 확인이 필요하고, 가능하다면 요청을 한 후 
승인 여부에 따라 적절한 코드를 구현하면 된다.

 

앱의 권한을 요청할때에 이 권한이 왜필요한지에 대해 설명이 필요할 수 있다.
또한, 이전에 사용자가 이 권한에 대한 요청을 거부했을 때 다시한번 필요성에 대해 설명을 할 경우
shouldShowRequestPermissionRationale() method를 활용 할 수 있다.

이 메서드는 사용자가 이전에 요청을 거부한 경우 
true를 반환하고 사용자가 권한을 거부하고
권한 요청 대화상자에서 
다시 묻지 않음 옵션을 선택했거나정책상 이 권한을 금지하는 경우 false를 반환한다.

if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.BOOT) != PackageManager.PERMISSION_GRANTED) {

        // Permission is not 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; 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.
        }
    } else {
        // Permission has already been granted
    }

위의 코드에서 처럼 첫번째 if문에서 권한이 없을 경우 shouldShowRequestPermissionRationale() 내부에서 
Toast나 적절한 도구를 사용하여 사용자에게 설명 후, 아래처럼 권한 요청을 진행.

 

ActivityCompat.requestPermissions(Context, new String[]{Manifest.permission.REBOOT},
                                       MY_PERMISSIONS_REQUEST_REBOOT);

권한요청 시에는 ActivityCompat.requestPermissions를 호출한다.
첫번째 인자로는 권한이 필요한 현재 Context를 넘겨주고, 두번째인자로는 새로운 String을 생성하면서 
필요한 권한을 명세, 세번째 인자로는 requestCode를 넘겨주는데 이는 사용자가 권한요청을 승인하였을때 사용된다.

 

권한 요청을 승인한 경우에 호출되는 callback구현으로는 onRequestPermissionsResult를 Override하게 되는데
이때 첫번째 인자인 requestCode가 위에서 언급한 ActivityCompat.requestPermissions의 세번째인자이다.

@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.
        }
    }

switch-case문에서 해당 requestCode인 경우에 권한 승인이 되었을때 구현할 코드와 
권한이 거부되었을 때 수행할 동작을 구현하면 사용자와 권한승인여부를 확인하는 인터페이스 구현을 완료하게 된다.

 

개발을 하면서 system권한을 사용하게 되는 경우가 많았는데, 안드로이드가 개발자 멋대로 
시스템상에서 원하는 동작을 구현하게 잘 두지 않는것 같다. 보안이 철저하다고 해야할것 같다.
그리고 느낀점은 이런게 자체 플랫폼을 가져야하는 이유와 자체플랫폼을 가졋을때의 장점인것 같다.

'App Development' 카테고리의 다른 글

[ Android ] AsyncTask  (0) 2020.11.25
[ Android ] Service에서 UI 변경하기  (0) 2020.06.30
Comments