TAE

[Android/Kotlin] 갤러리 접근 권한(Premission) 설정하기 - 커스텀 갤러리(1) 본문

android/코드

[Android/Kotlin] 갤러리 접근 권한(Premission) 설정하기 - 커스텀 갤러리(1)

tg-world 2023. 3. 16. 15:32
반응형

안드로이드 앱을 개발하다 보면 특정 권한을 얻어야지만 사용이 가능한 기능들이 있습니다.

Android6.0 (API 수준 23) 마쉬멜로우 이전 버전은 메니페스트에 권한을 넣어주면 사용이 가능했지만, 마쉬멜로우 이상 부터 접근 권한을 받아야 사용이 가능하도록 바뀌었습니다.

 

안드로이드 권한에 관하여 알아보겠습니다.

 

실행 동작


1. 권한 종류

모든 기능에 권한이 필요한 것이 아니라 민감한 정보(앨범, 저장소, 연락처, 전화걸기, 위치정보 등등)등 에 대한 기능에 권한이 필요합니다.

아래 디벨롭 사이트에 자세한 확인이 가능합니다.

https://developer.android.com/guide/topics/permissions/overview?hl=ko#normal-dangerous

 

Android에서의 권한  |  Android 개발자  |  Android Developers

Android에서의 권한 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 앱 권한은 다음 항목에 대한 액세스를 보호하여 사용자 개인 정보 보호를 지원합니다. 제

developer.android.com

https://developer.android.com/reference/android/Manifest.permission#public-constructors

 

Manifest.permission  |  Android Developers

 

developer.android.com

 

2. 코틀린 코드

권한추가(AndroidManifest.xml)

Manifests에 저장소 읽기 권한을 추가합니다. (앨범 불러오기 이므로 앨범은 저장소 읽기 권한을 사용합니다.)

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.videoselectthumbnail">
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.VideoSelectThumbnail">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 


권한 얻기(MainActivity.kt)

먼저 위에서 보았던 영상처럼 "앨범 불러오기" 버튼을 만든 후 클릭 리스너를 정의 해 줍니다.

 binding.goAlbumTV.setOnClickListener {
            when {
                ContextCompat.checkSelfPermission(
                    this,
                    android.Manifest.permission.READ_EXTERNAL_STORAGE
                ) == PackageManager.PERMISSION_GRANTED -> {
                    //스토리지 읽기 권한이 허용이면 커스텀 앨범 띄워주기
                    //권한 있을 경우 : PERMISSION_GRANTED
                    //권한 없을 경우 : PERMISSION_DENIED
                }

                shouldShowRequestPermissionRationale(android.Manifest.permission.READ_EXTERNAL_STORAGE) -> {
                    //권한을 명시적으로 거부한 경우 : ture
                    //다시 묻지 않음을 선택한 경우 : false
                    //다이얼로그를 띄워 권한 팝업을 해야하는 이유 및 권한팝업을 허용하여야 접근 가능하다는 사실을 알려줌
                    showPermissionAlertDialog()
                }

                else -> {
                    //권한 요청
                    requestPermissions(
                        arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
                        PERMISSION_CODE
                    )
                }
            }
        }

checkSelfPermission

첫번째로 checkSelfPermission을 실행한다. 인자로 해당 권한을 넣고 확인하는데 주석 해놓은 것 처럼

권한 있을 경우 : PERMISSION_GRANTED

권한 없을 경우 : PERMISSION_DENIED

을 반환한다.

ContextCompat.checkSelfPermission(
                    this,
                    android.Manifest.permission.READ_EXTERNAL_STORAGE
                ) == PackageManager.PERMISSION_GRANTED -> {
                    //스토리지 읽기 권한이 허용이면 커스텀 앨범 띄워주기
                    //권한 있을 경우 : PERMISSION_GRANTED
                    //권한 없을 경우 : PERMISSION_DENIED
                }

PackageManager.PERMISSION_GRANTED 이면 접근 권한이 있는 것으로 원하는 동작을 실행해 주면 됩니다.(다음 동작은 다음 장에서..)

 

shouldShowRequestPermissionRationale

두번째 when문인 shouldShowRequestPermissionRationale 는 권한이 거부 된 경우 이다.

주석에 표시한것 처럼 반환값은

//권한을 명시적으로 거부한 경우 : ture

//다시 묻지 않음을 선택한 경우 : false

처음으로 거부 할 경우 ture를 반환하여 다이얼로그를 통하여 한번 더 권한을 승인 할 것이냐고 묻는 팝업을 띄워준다.

    shouldShowRequestPermissionRationale(android.Manifest.permission.READ_EXTERNAL_STORAGE) -> {
                    //다이얼로그를 띄워 권한팝업을 허용하여야 접근 가능하다는 사실을 알려줌
                    showPermissionAlertDialog()
                }

 

*다이얼 로그 팝업(showPermissionAlertDialog)

    private fun showPermissionAlertDialog() {
        AlertDialog.Builder(this)
            .setTitle("권한 승인이 필요합니다.")
            .setMessage("사진을 선택 하시려면 권한이 필요합니다.")
            .setPositiveButton("허용하기") { _, _ ->
                requestPermissions(
                    arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
                    PERMISSION_CODE
                )
            }
            .setNegativeButton("취소하기") { _, _ -> }
            .create()
            .show()
    }

 

requestPermissions(권한 요청)

                else -> {
                    //권한 요청
                    requestPermissions(
                        arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
                        PERMISSION_CODE
                    )
                }

권한을 요청하는 함수.

처음 when문 분기문으로 허용상태가 아니고, 다시묻지 않음인 경우가 아닐 경우 권한 요청을 한다.

 

requestPermissions은 인자로 array를 받는데, 여러개의 권한을 요청 할 경우가 있기 때문입니다.

두번째 인자는 requestCode(PERMISSION_CODE)인데 이 code값은 아래에 설명할 onRequestPermissionsResult 에서 사용됩니다.

 

onRequestPermissionsResult

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            PERMISSION_CODE -> {
                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //권한 허용클릭
                    //TODO()앨범으로 이동시키기!
                } else if (shouldShowRequestPermissionRationale(android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
                    //권한 처음으로 거절 했을 경우
                    //한번더 권한 요청
                    showPermissionAlertDialog()
                } else {
                    //권한 두번째로 거절 한 경우 (다시 묻지 않음)
                    //설정 -> 권한으로 이동하는 다이얼로그
                    goSettingActivityAlertDialog()
                }
            }
        }
    }

권한팝업이 뜨고 권한을 허용을 하였는지 거부를 하였는지를 체크하여 해당 이벤트에 맞는 동작을 실행하는 함수이다.

override하여 사용하시면 됩니다.

 * cantrol + 엔터 후 검색

첫번째 if문은 위에서 설명했듯이 권한이 허용 되었을 경우 PackageManager.PERMISSION_GRANTED 으로 넘어옴으로 권한 승인 후 동작을 구현 해 주면 됩니다.

 

두번째 if문

권한이 처음으로 거절되었을 경우는 반환값으로 true가 반환되고, 두번째는 flase가 반환되는데,

첫번째로 거절되었을 경우 위와 같이 권한 승인 팝업을 띄워준다.

 

else 구문

다시 묻지 않음인 경우가  되었을 경우에는 더이상 requestPermissions을 실행 하지 않으므로, 설정으로 가서 사용자가 직접 권한을 허용하게 하여야 한다.

그렇게 하기 위해 앱 설정으로 가겠냐는 다이얼로그 팝업을 추가 해 주었습니다

 

* goSettingActivityAlertDialog

    private fun goSettingActivityAlertDialog() {
        AlertDialog.Builder(this)
            .setTitle("권한 승인이 필요합니다.")
            .setMessage("앨범에 접근 하기 위한 권한이 필요합니다.\n권한 -> 저장공간 -> 허용")
            .setPositiveButton("허용하러 가기") { _, _ ->
                val goSettingPermission = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                goSettingPermission.data = Uri.parse("package:$packageName")
                startActivity(goSettingPermission)
            }
            .setNegativeButton("취소") { _, _ -> }
            .create()
            .show()
    }

이상 안드로이드 코틀린 권한 얻는 법 포스팅 이였습니다.

궁금하신점이나 잘못된게 있다면 댓글 달아주시면 감사하겠습니다!

 

반응형
Comments