1. 개요
마시멜로 버전(API 23)부터 권한을 일반 권한과 위험 권한으로 나뉘었다. 이전에는 앱을 설치하는 시점에서만 권한을 부여할 것인지 물어보았는데, 사용자가 아무런 생각 없이 앱을 설치하는 경우가 많아 앱에서 아무리 많은 권한을 요구해도 그냥 승인되는 경우가 많았기 때문이다. (나도 대충 확인하고 그냥 설치했던 기억이 난다)
위험 권한은 앱이 실행된 후에 사용자에게 권한 허용을 요청해야 한다. (그래서 언제부턴가 앱 설치 후에 해당 기능을 이용하려면 특정 권한을 허용해주세요 라는 알림이 뜨는 이유인가보다.)
Developer 사이트를 참고해보니, 특별 권한이라는 것도 있다. SYSTEM_ALERT_WINDOW, WRITE_SETTINGS는 특히 민감하므로, 대부분 앱은 이 권한을 사용하지 않아야한다고 나와있다. 이 권한을 필요로 할 경우, 매니페스트에 선언한 후 사용자 승인을 요청하는 인텐트를 전송해야한다. (구글링해보니, 안드로이드 랜섬웨어에 이 권한이 악용되었다고 한다(잠금화면 못열게 하기...). 다른 방법으로 쓰이는 것은 어떤 앱이 뜨던간에 항상 최상위에 떠있게 할 수 있다. 블루라이트 차단 필터가 이 권한을 사용한 것 같다.)
2. 설명
예를 들면, 인터넷을 사용할 때 부여하는 INTERNET 권한은 일반 권한이므로 앱을 설치할 때만 승인하면 되지만 위험 권한으로 분류되는 RECEIVE_SMS의 경우에는 설치 시에 부여한 권한 외에도 실행 시에 사용자에게 권한을 부여할 것인지 물어보아야 한다.(잘못하면 악용될 가능성이 상당히 높은 것 같다.)
만약 사용자가 권한을 부여하지 않을 경우 해당 기능은 동작하지 않는다. 즉, 앱을 설치했더라도 권한에 따라 실행할 수 있는 기능에 제약이 생기는 것이다.
API 22 버전까지는 위험 권한도 매니페스트에 등록하기만 하면 그냥 부여된다. (설치할때에만 한번 묻는 형식)
3-1. 일반 권한의 종류
일반 권한은 그냥 매니페스트에 등록하기만 하면 아무런 문제없이 권한이 부여된다.
ACCESS_LOCATION_EXTRA_COMMANDS / ACCESS_NETWORK_STATE / ACCESS_NOTIFICATION_POLICY / ACCESS_WIFI_STATE / BLUETOOTH / BLUETOOTH_ADMIN / BROADCAST_STICKY / CHANGE_NETWORK_STATE / CHANGE_WIFI_MULTICAST_STATE / CHANGE_WIFI_STATE / DISABLE_KEYGUARD / EXPAND_STATUS_BAR / GET_PACKAGE_SIZE / INSTALL_SHORTCUT / INTERNET / KILL_BACKGROUND_PROCESSES / MANAGE_OWN_CALLS / MODIFY_AUDIO_SETTINGS / NFC / READ_SYNC_SETTINGS / READ_SYNC_STATS / RECEIVE_BOOT_COMPLETED / REORDER_TASKS / REQUEST_COMPANION_RUN_IN_BACKGROUND / REQUEST_COMPANION_USE_DATA_IN_BACKGROUND / REQUEST_DELETE_PACKAGES / REQUEST_IGNORE_BATTERY_OPTIMIZATIONS / REQUEST_INSTALL_PACKAGES / SET_ALARM / SET_WALLPAPER / SET_WALLPAPER_HINTS / TRANSMIT_IR / USE_FINGERPRINT / VIBRATE / WAKE_LOCK / WRITE_SYNC_SETTINGS
3-2. 위험 권한의 종류
위험 권한으로 분류된 주요 권한들을 보면 대부분 개인정보가 담겨있는 정보에 접근하거나 개인정보를 만들어낼 수 있는 단말의 주요 장치에 접근하는 경우에 부여되는 권한이라는 것을 알 수 있다.
출처 : Android Developer 사이트
Developer 사이트의 설명에 의하면 권한 그룹 내 하나의 권한이 이미 허용되어있을때, 동일 그룹 내 권한이 요청될 경우 사용자에게 묻지 않고 즉시 허용된다고 한다. (시스템은 사용자에게 개별 권한이 아닌 앱이 필요로 하는 권한 그룹만 알린다.) 예를 들면, READ_EXTERNAL_STORAGE 권한을 부여받은 상태에서 WRITE_EXTERNAL_STORAGE 권한을 요청한 경우 시스템이 즉시 이 권한을 부여한다.
4. 위험 권한 부여 방법 예제
권한 요청을 받을 액티비티 클래스의 onCreate()에 구현하면 된다.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 해당 권한이 부여되어 있는지 확인하는 메소드
int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "SMS 수신 권한 주어져 있음.", Toast.LENGTH_SHORT).show();
} else { // PackageManager.PERMISSION_DENIED
Toast.makeText(this, "SMS 수신 권한 없음.", Toast.LENGTH_SHORT).show();
// 해당 권한에 대한 설명이 필요한 경우.
// 이 예제에서는 필요하다고 나온다.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECEIVE_SMS)) {
Toast.makeText(this, "SMS 권한 설명 필요함.", Toast.LENGTH_SHORT).show();
}
// 시스템이 권한 요청 대화상자를 띄움.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECEIVE_SMS}, 1);
}
}
그리고 권한이 부여되었을 때 호출되는 콜백메소드를 다음과 같이 재정의 하면,
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "SMS 수신 권한을 사용자가 허용함.", Toast.LENGTH_SHORT).show();
} else if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
Toast.makeText(this, "SMS 수신 권한을 사용자가 거부함.", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this, "SMS 수신 권한을 부여받지 못함.", Toast.LENGTH_SHORT).show();
}
}
}
어떤 권한이 부여되었는지 여부를 확인할 수 있다.
마시멜로(API 23) 버전부터는 위험 권한을 요청해서 허용하는 과정을 구현해놓아야다고 했는데, 이를 무시하고 매니페스트에만 추가해놓았다면 당연히 해당 권한을 사용해야하는 기능이 작동하지 않는다. (파일 읽고 쓰기 권한에 대해서는 실험해보지 않았지만, 다른 포스트 내용인 브로드캐스트 리시버를 이용한 SMS 읽어오기 기능이 동작하지 않았다.)
출처 : 부스트코스 강의, Android Developer 사이트
'Android > Basic' 카테고리의 다른 글
[Android] Time to String 및 시간순으로 정렬하기 (0) | 2018.06.22 |
---|---|
[Android] Action Bar (0) | 2018.05.27 |
[Android] startActivityForResult() 활용 예제 (0) | 2018.05.18 |
[Android] Broadcast receiver 예제 (6) | 2018.05.16 |
[Android] Activity 생명주기 (0) | 2018.05.15 |