[android(kotlin)] 권한 허용에 대한 고찰

깨미·2021년 5월 22일
0

📱 Android 📱

목록 보기
5/16
post-thumbnail

권한 요청 dialog를 불러오는 부분에 대해서는 이전에 "외부 저장소에서 폴더 생성하기" 글에서 간략하게 올린 적이 있다.

한 번만 요청하는 건 사용자가 거부할 수도 있고, 다시 묻지 않기를 누를 수도 있다.
이번에는 조금 더 진화된(?) 느낌으로 권한 허용을 요청하도록 해보자.

가장 쉬운 방법은 처음 시작할 때 권한 허용을 위한 화면을 만드는 것이다. 해당 화면을 지나가지 않으면 아예 다음 화면으로 넘어갈 수 없도록.

본인은 해당 프로젝트에서 요구 받은 사항으로 권한 허용에 대한 화면은 없다. 그렇기 때문에 처음 시작할 때 권한 요청 dialog 만을 활용하여 모든 권한이 허용되어야 앱을 사용할 수 있도록 하여야 한다.

1. onStart() 에서 권한 요청이 안되어 있을 경우 권한 요청 하기.

    override fun onStart() {
        super.onStart()
        if (!hasPermission(Manifest.permission.ACCESS_FINE_LOCATION) ||
            !hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
            !hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
        ) {// 권한 허용이 되어 있지 않다면
            ActivityCompat.requestPermissions(
                this,
                arrayOf(
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE
                ), REQUEST_LOCATION_PERMISSION
            )
        } else {// 권한 허용이 되어 있다면
            scanEnable()
        }
    }
    //permission 체크 함수
    private fun Context.hasPermission(permission: String) =
        ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED

2. onRequestPermissionsResult 에서 사용자 event 확인하기

사용자가 수락했는 지, 거절했는 지에 따라 다시 권한을 요청하도록 한다.

   override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 1 && grantResults.isNotEmpty()) {
            if (ContextCompat.checkSelfPermission(
                    this,
                    Manifest.permission.ACCESS_FINE_LOCATION
                ) != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(
                    this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
                ) != PackageManager.PERMISSION_GRANTED ||
                ContextCompat.checkSelfPermission(
                    this,
                    Manifest.permission.READ_EXTERNAL_STORAGE
                ) != PackageManager.PERMISSION_GRANTED
            ) { // 권한이 거절된 상태
                if (ActivityCompat.shouldShowRequestPermissionRationale(
                        this,
                        Manifest.permission.ACCESS_FINE_LOCATION
                    ) || ActivityCompat.shouldShowRequestPermissionRationale(
                        this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                    ) || ActivityCompat.shouldShowRequestPermissionRationale(
                        this,
                        Manifest.permission.READ_EXTERNAL_STORAGE
                    )
                ) {
                    // 승인 거절
                    permissionCheck = false
                    val toast = Toast.makeText(this, "앱을 사용하려면 권한을 허용해주세요.", Toast.LENGTH_LONG)
                    toast.show()
                    Handler().postDelayed({
                        ActivityCompat.requestPermissions(
                            this,
                            arrayOf(
                                Manifest.permission.ACCESS_FINE_LOCATION,
                                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                Manifest.permission.READ_EXTERNAL_STORAGE
                            ), REQUEST_LOCATION_PERMISSION
                        )
                    }, 1500)
                } else { // 다시 묻지 않음 옵션을 선택,  승인요청을 한적이 없는 경우
                    val snackBar = Snackbar.make(
                        findViewById(R.id.mainLayout),
                        "권한을 허용해야 앱을 사용할 수 있습니다. 확인을 누르면 설정 화면으로 이동합니다.",
                        Snackbar.LENGTH_INDEFINITE
                    )
                    snackBar.setAction("확인") {
                        val intent = Intent()
                        intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                        val uri = Uri.fromParts("package", packageName, null)
                        intent.data = uri
                        startActivity(intent)
                    }
                    snackBar.show()
                }
            } else { // 4. 권한이 승인된 상태
                scanEnable()
            }
        }
    }

주석이 처리가 되어 있지만 설명하자면, if (requestCode == 1 && grantResults.isNotEmpty()) { 를 통해 사용자 event 결과를 확인한다.
권한을 거절한 상태라면 1. 승인을 거절한 경우, 2. 다시 묻지 않음 옵션을 선택한 경우 & 승인 요청을 한적 없는 경우. 로 나뉜다.

(1) 승인을 거절한 경우

승인을 거절한 경우, Toast 로 권한을 요청하라고 안내 문구가 띄워지고 다시 권한을 요청한다.

Toast로 띄우는 코드와 권한을 요청하는 코드(ActivityCompat.requestPermissions)를 그냥 같이 쓸 경우, Toast가 아주 잠시 나오고 바로 요청에 대한 dialog가 나온다. 이를 방지 하기 위해 handler를 사용하여 Toast가 나오고, 1500ms 이후 요청할 수 있도록 하였다.

(2) 다시 묻지 않음 옵션 선택 & 승인 요청 한적 없는 경우

snackBar를 활용하여 확인 버튼을 눌렀을 때 intent를 통해 바로 설정 화면으로 이동할 수 있도록 한다.
본인은 이 권한에 대한 부분을 고찰하면서 snackBar를 처음 접했다. dialog나 Toast 처럼 유용하게 사용될 수 있을 듯 하다.

해당 코드를 통해 권한 허용이 되지 않은 경우에는 절대로 앱을 동작할 수 없게 된다.

고찰

반복하여 사용되는 부분은 함수로 만들기
권한에 대해 array로 만들어놓은 다음 활용하기


한달 정도 지나 이 글을 다시 읽어보니 권한 허용이 필요한 부분을 실행할 때마다 권한에 대한 클래스나 함수를 만들어 flag를 체크하는 방식으로 구현해도 좋을 거 같다 😏 방법은 자기가 편한대로~

profile
vis ta vie

0개의 댓글