상상하라 그리고 현실로 만들어라.

상상하는 모든 것이 미래다.

Kotlin과 Android/Android

코틀린으로 안드로이드 위험권한, 사용자에게 요청하기

월터제이(Walter J) 2021. 2. 8. 09:00

안녕하세요, 반갑습니다!

 

안드로이드 앱을 만들어야겠다!

하고 어떤 앱을 만들어야 할지 고민을 시작했다면, 

안드로이드에서의 권한을 생각해봐야 합니다.

 

최근의 대부분 앱들은 앱을 설치하고 실행하면 이런 메세지들을 자주 봅니다.

바로 이것이 바로 권한입니다.

 

 

조금 더 정확하게 말하면 개인정보를 위협하는 위.험.한 접근 및 작업에 대해 사용자에게 써도 되는지 허락해주십사 하는것이죠.

 

사실 안드로이드 5.1(Lollipop, API 22) 까지는 모든 권한이 자동으로 부여됐었습니다.

안드로이드 5.1 이라니, 너무 오래된 이야기죠?

 

네, 맞습니다 그동안 사용자 개인정보 등에 대한 보안성이 많이 중요해졌습니다.

안드로이드 6.0(API 수준 23) 부터는 위험한 권한에 대해서 사용자들에게 권한을 요청 하도록 바뀌었습니다.

(개발자들이 신경써야 할 일이 늘어난...)

 

"글쎄, 나는 딱히 권한을 요청할 만한 앱은 안만들건데?"

 

그렇다면 지금은 이 글을 보실 필요가 없습니다.

그저 필요하실 때, 보셔도 충분합니다.

하지만!! 권한에 대해 알고만 계셔도 분명히 유용하실 것이라 말씀드리고 싶네요.

 

자, 그럼 안드로이드 공식 사이트에서는 어떻게 설명하고 있는지 먼저 볼까요?

 

앱 권한은 다음 항목에 대한 액세스를 보호하여 사용자 개인정보 보호를 지원하고 있습니다.

  • 제한된 데이터 (예 : 시스템 상태 및 사용자의 연락처 정보)
  • 제한된 작업 (예 : 페어링된 기기에 연결 및 오디오 녹음)

 

개인정보는 물론이고 시스템 즉, 하드웨어를 건드리는 일 또한 사용자에게 권한을 요청해야합니다.

이를테면, 외부 저장소에 접근해서 읽고 쓴다든가 위치 정보 등을 이용할 때를 말합니다.

위 예시처럼 오디오 녹음들도 포함될 수 있겠네요.

 

권한은 크게 3가지로 나눌 수 있습니다.

  • 설치 시간 권한(일반 권한, 서명 권한)
  • 런타임 권한
  • 특별 권한

 

1. 설치 시간 권한

다시 2개의 권한으로 나눌 수 있습니다.

 

일반 권한

사용자의 개인정보 또는 하드웨어에 미치는 영향이 거의 없는 작업을 하기 위한 권한을 말합니다.

 

이 링크의 '일반' 보호 수준이 일반 권한에 해당됩니다.

developer.android.com/reference/android/Manifest.permission

 

Manifest.permission  |  Android 개발자  |  Android Developers

 

developer.android.com

 

이 권한은 사용자에게 요청할 필요없이 앱 설치될 때 자동으로 부여됩니다.

권한 설정 방법은 간단합니다.

manifest 파일에 권한을 선언해주면 됩니다.

 

AndroidManifest.xml 에 작성하기

<manifest>
    <!-- 일반 권한 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><!-- 네트워크 연결 상태 확인 -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/><!-- 와이파이 상태 확인 -->
    <uses-permission android:name="android.permission.BLUETOOTH"/><!-- 블루투스 상태 확인 -->
    <uses-permission android:name="android.permission.INTERNET"/><!-- 네트워크 및 인터넷 사용 -->
    <uses-permission android:name="android.permission.NFC"/><!-- 기기간 근거리 통신 사용 -->
    <uses-permission android:name="android.permission.SET_ALARM"/><!-- 알람설정 -->
    <uses-permission android:name="android.permission.VIBRATE"/><!-- 진동설정 -->
    <uses-permission android:name="android.permission.CAMERA"/><!-- 카메라 -->
    
    <application>
    .
    .
    .
    </application>
</manifest>

 

※ 물론, 일반 권한 뿐만 아니라 위험 권한들도 manifest.xml 에 선언해주어야 해야합니다.

 

서명 권한

이것은 두 앱이 동일한 인증서로 서명이 되어 있을 때, 권한이 부여되는 방법입니다.

인증서가 동일하다면 타 앱의 권한으로 상호작용할 수 있습니다.

 

2. 런타임 권한

런타임 권한, 이른바 '위험 권한'이라고도 합니다.

이 권한은 사용자에게 권한 요청 대화상자를 띄워 응답을 받아야 합니다.

그것이 거부가 될지라도요.

아, 물론 타겟이 되는 단말기가 안드로이드 5.1 (API 수준 22) 이하라면 이 단계는 무시해도 됩니다.

다만 지금 나오는 단말기들은 당연히 안드로이드 5.1 이상이겠지요?

 

먼저 이 런타임 권한 요청을 하기 위해서 알아두어야할 기본 원칙이 있습니다.

  • 권한이 필요한 기능을 사용하는 그 순간에 권한 요청하기
  • 사용자를 차단하지 않으며 항상 취소 옵션을 제공하기
  • 만약, 사용자가 거부하거나 취소하면 앱의 성능을 저하시키되 앱을 계속 사용할 수 있도록 하기
  • 동일한 권한 그룹은 대화상자의 수를 최소하 하는데 도움이 될뿐, 그 권한이 표시된다고 가정하지 않기

그리고 이 런타임 권한이 바로 개발자가 직접 구현해야 하는 부분입니다.

 

구현은 생각보다 간단하며, 요청 방법은 다음 3단계를 거칩니다.

  • 1단계 : 권한에 대한 사용자 승인 확인 (이전에 승인했는지)
  • 2단계 : 사용자에게 승인 요청
  • 3단계 : 사용자 승인 후 처리

권한확인

//권한 확인
fun checkPermission() {
    val cameraPermission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
    if (cameraPermission == PackageManager.PERMISSION_GRANTED) {
        //승인된 상태일 경우 진행
        startProcess()
    }
    else {
        //승인되지 않았다면 권한 요청 프로세스 진행
        requestPermission()
    }
}

조금 설명을 보태면,

Manifest.xml 에 작성된 권한을 확인합니다. 즉, 런타임 권한을 사용자에게 직접 요청 하더라도 Manifest.xml 에 필요한 권한을 작성해주어야 합니다.

한번 권한을 요청하고 응답을 받으면, 앱을 지우지 않는 한 그 상태가 저장됩니다.

권한 확인은 그 상태를 확인하고 해당 기능을 실행할지, 권한을 요청할지 정하게 되는 것이죠.

 

권한요청

//권한 요청
private fun requestPermission() {
    ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.CAMERA), 99)
}

ActivityCompat.requestPermissions() 는 3개의 인자가 필요합니다.

Context 정보, 권한 목록, 요청하는 고유 값이죠.

위 예시에서는 카메라 1개의 권한이긴하지만 배열에 담아 넘겼습니다.

만약, 필요한 권한이 여러개라면 역시 배열에 담아 넘기면 되겠죠?

 

 

권한처리

//권한 처리
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
//    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    when (requestCode) {
        99 -> {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startProcess()
            }
            else {
                Log.d("HOME", "종료")
            }
        }
    }
}

구조는 onActivityForResult() 와 같습니다.

요청하는 고유값을 확인 후, 승인이 되었다면 해당 기능을 실행하고 거절하면 해당 기능을 사용할 수 없게 됩니다.

 

 

3. 특별 권한

이 권한은 특정 플랫폼과 OEM만이 정의할 수 있습니다.

이를테면, 일반적으로 다른 앱 위에 그리기와 같이 강력한 작업에 대한 접근을 보호하기 위해 정의합니다.

 

그런데 일반적인 수준에서 특별권한은 다룰 일이 많지 않습니다.

만약, 필요한 경우에는 권한 API 참조 페이지 를 참고하시면 됩니다.

'appop' 보호 수준이 특별 권한에 해당 됩니다.

developer.android.com/reference/android/Manifest.permission

 

Manifest.permission  |  Android 개발자  |  Android Developers

 

developer.android.com

 

4. 권장사항

앱에 대한 권한을 사용자에게 요청하거나 부여하기하기 전에, 먼저 이 권한이 앱에 필요한지를 생각해보라고 구글(Google)은 말합니다.

한참 앱을 사용하고 있는 사용자에게 권한 요청으로 방해할 수 있다는 것이 그 이유지요.

 

그런데 개발자 또한 구글의 말을 진지하게 생각해볼 필요가 있습니다.

사용자는 왕이니까 권한 요청에 대한 이유를 납득하지 못하면 앱을 지울 수도 있으니까요.

(사용자는 사소한 것에서 기분나빠할 수도 있어요...)

 

어쨌든, 그래서 다음과 같은 대안들을 구글은 제시하고 있습니다.

 

주변 장소 표시

지도 등 위치 정보를 알아야 할 때가 있습니다.

그래서 무작정 권한을 요청하기 보다는 사용자에게 직접 주소 또는 우편번호를 입력받는 것입니다.

더 정확한 정보가 필요할 때도 있습니다. 그때 ACCESS_FINE_LOCATION 권한을 사용하도록 하고 있습니다.

 

사진 찍기

특별한 용도가 아닌 경우 내장된 카메라 앱을 사용하도록 권하고 있습니다.

ACTION_IMAGE_CAPTURE 를 intent 로 호출할 수 있습니다.

 

동영상 녹화

역시 안드로이드 자체의 카메라 앱을 사용할 수 있습니다.

ACTION_VIDEO_CAPTURE 를 intent 로 호출할 수 있습니다.

 

다른 앱의 미디어 또는 문서 열기

어차피 안드로이드 10 (Pie, API 수준 29) 부터는 직접 접근할 수 없지만, READ_EXTERNAL_STORAGE 권한을 선언하기 보다는 미디어 저장소를 사용해서 파일을 열고, 저장소 액세스 프레임워크를 사용할 것을 권하고 있습니다.

 

공유 저장소의 미디어 파일에 액세스 링크를 참고해주세요.

developer.android.com/training/data-storage/shared/media

 

공유 저장소의 미디어 파일에 액세스  |  Android 개발자  |  Android Developers

많은 앱에서 더욱 풍부한 사용자 환경을 제공하기 위해 사용자가 외부 저장소 볼륨에서 사용 가능한 미디어를 제공하고 액세스할 수 있게 합니다. 프레임워크는 미디어 저장소라고 하는 미디어

developer.android.com

 

블루투스를 통해 기기와 페어링

ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, BLUETOOTH_ADMIN 권한을 선언하는 대신 호환 기기 페어링을 사용하도록 하고 있습니다.

 

호환 기기 페어링 링크를 참조해주세요.

developer.android.com/guide/topics/connectivity/companion-device-pairing

 

호환 기기 페어링  |  Android 개발자  |  Android Developers

Android 8.0(API 레벨 26) 이상을 실행하는 기기에서는 블루투스, BLE 및 Wi-Fi를 통해 호환 기기와 페어링할 때 표시되는 페어링 요청 대화상자를 맞춤설정할 수 있습니다. 앱에서 사용자에게 가능한

developer.android.com

 

앱이 중단될 때 미디어 일시정지

동영상을 보고 있다가 전화가 오거나 카톡 문자에 답장을 하거나 앱이 중단되는 경우가 있습니다.

이때 영상은 일시정지가 되어야 하는데, READ_PHONE_STATE 권한을 사용하기 보다는 오디오 포커스를 구현하여 멈추라고 권하고 있습니다.

 

오디오 포커스 링크를 참조해주세요.

developer.android.com/guide/topics/media-apps/audio-focus

 

오디오 포커스 관리  |  Android 개발자  |  Android Developers

두 개 이상의 Android 앱이 동일한 출력 스트림으로 동시에 오디오를 재생할 수 있습니다. 시스템이 모든 것을 혼합합니다. 이는 기술적으로 인상적이지만 사용자에게는 매우 좋지 않을 수 있습니

developer.android.com

 

 

 

감사합니다!

반응형