ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Permission] 권한 체크, 획득
    Android/Permission 2021. 10. 21. 16:59

    목차

    권한 체크 방법

    권한 획득 방법

    Android 9, 10, 11 공통 차이점

    권한 요청 시스템 다이얼로그가 뜨지 않는 경우 사용자를 권한 설정으로 보내기

     

    다음 글

    [Android] 전반적인 권한 처리 로직


    • 권한 승인, 거부 상태

    PackageManger. PERMISSION_GRANTED

    PackageManger. PERMISSION_DENIED


    • 자신의 앱에서 사용하는 특정 권한의 승인, 거부 상태 체크

    ActivityCompat extends ContextCompat

     

    ContextCompat ->Helper for accessing features in Context

    ContextCompat.checkSelfPermission(컨텍스트: Context, 권한: String)

    (호환 api)

     

    또는 Context.checkSelfPermission (권한: String) - Added in api 23

     

    • 패키지명에 해당하는 앱에서 사용하는 특정 권한의 승인, 거부 상태 체크

    PackageManager.checkPermission(권한: String, 패키지명: String)

     

     

    위의 두가지 클래스를 통한 권한 체크시

    1. <uses-permission> 조차 선언하지 않은 권한의 경우에는 PERMISSION_DENIED 리턴됨

    2. 안드로이드 11의 경우 package visibility 변경사항으로 인해 다른 앱의 권한 승인, 거부 정보를 얻기 위해서는 

    <queries>태그나 QUERY_ALL_PACKAGES 권한을 선언하지 않으면 제대로된 획득상태 확인이 불가능한 것 같다.

     

    A앱에서 PackageManager를 통하여 B앱의 권한 획득 상태를 확인

     

    B앱에 선언된 권한 (설치시 자동획득되는 두개의 일반 권한)

    B앱 디바이스에 설치

     

    A앱에서 PackageManager를 통해 B앱에서 선언한(사용하는 있는) 권한 승인, 거부 상태 확인

    class CheckAnotherAppPermission : AppCompatActivity() {
    
        private var mPermissions //B앱에서 사용하는 권한
        = mutableListOf<String>(Manifest.permission.INTERNET, Manifest.permission.ACCESS_WIFI_STATE)
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_check_another_app_permission)
    
            log("PackageManager를 통해 디바이스에 설치된 다른 앱의 권한 체크")
            val pm = packageManager
            for (item in mPermissions) {
                log(item)
                var check: Int = pm.checkPermission(
                    item, "com.source.permission.permissionchecktargetapp" //B앱의 패키지명
                )
                if (check == PackageManager.PERMISSION_GRANTED) {
                    log("권한 승인")
                } else {
                    log("권한 거부")
                }
            }
            log("........................................")
        }
    
        private fun log(str: String) {
            Log.d("PERMISSION_TEST", str)
        }
    }

     

    안드로이드11의 패키지 가시성으로 인해 B앱에서 일반권한 두개 모두 승인상태인데 제대로 출력되지 않는다.

     

    A앱의 매니페스트에 추가하여 B앱의 패키지 정보를 얻을 수 있게 하고 테스트하면 제대로 출력된다


    • 권한 체크, 권한 설명 필요한지, 권한 요청, 권한 요청 결과 관련

    --ActivityCompat

     

    권한 획득 상태 확인( super class인 ContextCompat의 메서드)

    checkSelfPermission(컨텍스트: Context, 권한: String): Int

    패지키매니져의 GRANTED, DENIED로 리턴

     

    권한 설명이 필요한지

    shouldShowRequestPermissionRationale(액티비티: Activity, 권한: String) : Boolean

    설명이 필요하면 true, 필요하지 않으면 false

    (앱 첫 설치시에는 false로 초기화되어 있음)

     

    권한 요청

    requestPermissions(액티비티: Activity, 권한들: String[], 리퀘스트 코드: Int) 

    permission group에 해당하는 텍스트를 띄워주는 시스템 다이얼로그로, requestPermissions를 호출하였을시에는 다이얼로그를 커스터마이징 할 수 없다.

     

    --ActivityCompat. OnRequestPermissionsResultCallback 인터페이스

    (AppCompatActivity가 구현)

     

    권한 요청 후 콜백

     

    이외에 startActivityForResult가 Deprecated되어 registerForActivityResult를 사용해봤었는데 ActivityResultLauncher를 사용하는 법도 소개하고 있다.

    https://developer.android.com/training/permissions/requesting#allow-system-manage-request-code

     

    라이브러리도 많음


    • 코드

    WRITE_EXTERNAL_STORAGE 권한 획득 테스트

    단순 테스트를 위한 목적으로 10,11에서는 필요없다.

     

    const val REQUEST = 100
    
    class WriteExternalStoragePermission : AppCompatActivity() {
    
        private lateinit var mBinding: ActivityWriteExternalStoragePermissionBinding
        private val mPermission: String = Manifest.permission.WRITE_EXTERNAL_STORAGE
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            mBinding = DataBindingUtil.setContentView(
                this,
                R.layout.activity_write_external_storage_permission
            )
    
    
        }
    
    
        override fun onRequestPermissionsResult(
            requestCode: Int,
            permissions: Array<out String>,
            grantResults: IntArray
        ) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
            log("권한 요청 결과")
            if (requestCode == REQUEST) {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    log("권한 획득되어 기능을 수행합니다")
                } else {
                    log("권한 거부되어 기능을 사용할 수 없음")
                }
            }
        }
    
        fun onClick(view: View) {
            when (view.id) {
                R.id.check -> {
                    check(mPermission)
                }
                R.id.needExplain -> {
                    needExplain(mPermission)
                }
                R.id.request -> {
                    request(mPermission)
                }
            }
        }
    
        private fun check(permission: String) {
            log(
                "권한 상태: ${
                    ActivityCompat.checkSelfPermission(
                        this,
                        permission
                    ) == PackageManager.PERMISSION_GRANTED
                }"
            )
    
        }
    
        private fun needExplain(permission: String): Boolean {
            val bool = ActivityCompat.shouldShowRequestPermissionRationale(this, permission)
            log("$permission 설명해줘야 하나?  $bool")
            return bool
        }
    
        private fun request(permission: String) {
            ActivityCompat.requestPermissions(this, arrayOf(permission), REQUEST)
        }
    
        private fun log(str: String) {
            Log.d("PERMISSION_TEST", str)
        }
    }

     

    Android 9에서 태그결과를 확인

    밑에 10,11과의 다른점 추가

    //앱 처음 실행
    
    //권한 체크 버튼
    //Runtime Permission이라 권한 획득되지 않음
    D: 권한 상태: false 
    
    //설명해줘야하나? 
    //앱 처음 실행시에는 false로 초기화되어있음
    D: android.permission.WRITE_EXTERNAL_STORAGE 설명해줘야 하나?  false
    
    //권한 요청 버튼
    
    //사용자가 권한 거부
    D: 권한 요청 결과
    D: 권한 거부되어 기능을 사용할 수 없음
    
    //권한 체크 버튼
    D: 권한 상태: false
    
    //설명이 필요한지 버튼
    //거부하면 boolean값이 true로 변경됨
    D: android.permission.WRITE_EXTERNAL_STORAGE 설명해줘야 하나?  true
    
    //권한 요청 버튼
    
    //(다시 묻지 않음 체크박스가 딸린 다이얼로그 출력됨)
    
    //사용자가 권한 거부
    D: 권한 요청 결과
    D: 권한 거부되어 기능을 사용할 수 없음
    
    //설명 필요 버튼
    //true유지
    D: android.permission.WRITE_EXTERNAL_STORAGE 설명해줘야 하나?  true
    
    //권한 체크 버튼
    D: 권한 상태: false
    
    //다시 묻지 않기 체크상태로 사용자가 권한 거부
    D: 권한 요청 결과
    D: 권한 거부되어 기능을 사용할 수 없음
    
    //다시 묻지 않기 체크상태로 거부하면 true가 아니라 false로 됨
    D: android.permission.WRITE_EXTERNAL_STORAGE 설명해줘야 하나?  false
    
    //권한 요청 버튼
    
    //시스템 다이얼로그가 뜨지 않음
    //콜백은 자동으로 거부 상태를 받는다.
    D: 권한 요청 결과
    D: 권한 거부되어 기능을 사용할 수 없음
    D: 권한 요청 결과
    D: 권한 거부되어 기능을 사용할 수 없음
    D: 권한 요청 결과
    D: 권한 거부되어 기능을 사용할 수 없음
    D: 권한 요청 결과
    D: 권한 거부되어 기능을 사용할 수 없음

    Android 9, Android 10, Android 11 의 차이점

     

     

    Android 9, 10 공통, 차이점

     

    • Android 9의 경우

    앱 설치 후 처음 권한 요청

    거부 후 권한 두번째 요청

    다시 묻지 않음 체크박스가 추가됨

    다시 묻지 않음을 체크하고 거부한 경우는 아래에서 Android 10과 같이 묶어 설명


    • Android 10

    앱 설치 후 처음 권한 요청

    거부 후 권한 재요청

    다시 묻지 않음 + 거부 선택지가 추가된 다이얼로그

     

    • Android 9, Android 10 공통

    앱 설치후 계속 거부한다고 가정하고 두번째 권한 요청부터 다시 묻지 않음이 포함된 다이얼로그가 뜨는데

    사용자가 일반적인 거부를 선택하면 true를 유지하고 이후의 권한 재요청시 반복적인 다이얼로그 출력이 계속된다.

     

    사용자가 다시 묻지않음이 포함된 거부를 선택한 경우에만 false상태로 바뀌고

    권한 재요청시 다이얼로그가 출력되지 않으며 자동으로 거부콜백만 받는다.

    이러한 경우에는 따로 파악해놓아 사용자를 앱의 권한 설정 액티비티로 보내 권한을 승인상태로 변경할 수 있도록

    이동시키는 작업이 필요하다.

     

    권한이 획득되어 있는 상태에서 사용자가 권한 설정으로가서 해당 권한을 거부상태로 변경한 경우라면??

    권한 요청시 바로 다시 묻지 않음이 포함된 다이얼로그가 출력되며 기존의 경우처럼 동작


    • Android 11

    (안드로이드 11 변경사항)

    시스템이 사용자의 데이터를 보호하기 위해 민감한 runtime 권한을 몇달마다 자동으로 리셋시킨다

    (runtime 권한만 리셋시킨다)

     

    더이상 묻지 않기가 없어지고 앱 설치후 두번째 거절시에 암묵적으로 더이상 묻지않기로 간주된다.

     

    사용자가 권한 설정에서 허용되어있던 권한을 거부상태로 변경하고 권한을 요청한 경우라면 두번이 아닌 첫번째 거절시 바로 더이상 묻지 않기 거부로 간주

     

    앱 설치 후 처음 권한 요청

    거부 후 권한 재요청

    Android9, Android 10과 다르게 다이얼로그에 다시 묻지 않음은 포함되지 않음

    대신에 두번째 권한요청시에 거부하면 Android9, Android 10의 다시묻지 않음이 포함된 거부와 같이 동작한다

    (=이후에 권한요청을 하면 다이얼로그가 출력되지 않으며 권한 거부 콜백을 받는다, boolean값도 동일하게 동작)

     

    획득된 권한인 상태에서 사용자가 권한 설정으로가서 해당 권한을 거부상태로 변경한 경우라면??

    권한 요청이 들어오고 거부를 하면 다시묻지 않음 거부 상태로 간주되어 다음 요청부터는 다이얼로그가 뜨지 않았다.


    사용자가 특정 권한을 거부한채 앱을 사용할 수 있기 때문에 권한들에 의존하지 않게 앱을 설계해야함

    권한 요청 다이얼로그가 나오지 않을 경우 이 상태를 파악할 수 있도록 하여 권한 설정화면으로 이동시켜야함

     

    다음 포스팅에서 권한 설정화면으로 이동시키는 것을 추가하고 버튼 하나로 실제 앱처럼 동작하게 변경시켜보려 한다.


    참고

    https://codechacha.com/ko/android-check-permission/

     

    Android - 앱 권한 확인(Permission check)

    App이 어떤 권한을 갖고 있는지 확인하는 방법을 소개합니다. checkSelfPermission()는 인자로 permisison 이름을 받습니다. Context의 App이 인자로 전달된 퍼미션을 갖고 있다면 PERMISSION_GRANTED를 리턴합니다

    codechacha.com

     

    댓글

Designed by Tistory.