본문 바로가기

Android/Utility

[Android] TedPermission을 사용하여 권한을 편하게 체크해보자.

728x90

이번에는 필자가 예전부터 자주 사용해왔던 TedPermission Library에 대해서 글을 작성해 보고자 한다.

Permission 체크를 아주 쉽게 할 수 있도록 도와주고 손쉽게 적용할 수 있어서 상당히 유용한 Library라고 생각한다.

 

해당 라이브러리는 개발 공부를 위해 구글링을 좀 해봤다면 이름을 들어봤을거라고 생각하는 박상권 님이 만들어주신 라이브러리이다.

글을 쓰기 앞서 해당 github의 링크를 추가해두도록 하겠다.

https://github.com/ParkSangGwon/TedPermission

 

GitHub - ParkSangGwon/TedPermission: Easy check permission library for Android Marshmallow

Easy check permission library for Android Marshmallow - GitHub - ParkSangGwon/TedPermission: Easy check permission library for Android Marshmallow

github.com


TedPermission을 적용하기 위해서는 

Module 범위의 Gradle에 해당 라이브러리를 추가해주면 된다.

 

// TedPermission
implementation 'io.github.ParkSangGwon:tedpermission-normal:3.3.0'

 

라이브러리를 추가하였으면,

사용할 곳에서 Listener를 선언하고, TedPermission을 생성하여 사용해주면 된다.

 

우선,

리스너를 선언해주자.

 

리스너에서는 단순하게 권한 체크를 승낙하거나 거절하였을 때의 동작을 Override하여 구현만 해주면 된다.

필자는 우선 기본적으로 Github에 나와있는 사용 예시와 마찬가지로 Toast 메시지만 띄우도록 해두었다.

모든 설정이 완료 되었을 때는 Granted가, 하나라도 거절이 된다면 Denied가 호출되게 된다.

 

리스너를 선언하였으면, 

해당 리스너를 사용하는 TedPermission 객체를 만들어주면 된다.

 

 

필자는 우선 Alert창에 나오는 Text를 모두 변경하여 사용하도록 하였다.

 

.setPermissionListener(permissionListener)
.setPermissions(
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.READ_CONTACTS,
    Manifest.permission.ACCESS_FINE_LOCATION
)

 

setPermissionListener를 사용하여 위에 생성한 리스너를 추가해 주고,

setPermissions를 통해 권한을 받고자 하는 Permission을 추가하여 실행 시에 권한을 체크해 준다.

 

그다음으로,

각 변경한 텍스트가 어느 부분인지 확인해보자.

.setRationaleMessage("권한 설정 합시다.")
.setRationaleTitle("권한 설정 받는 중")
.setRationaleConfirmText("알겠습니다")

 

Rationale이라고 선언된 부분이다.

 

맨 처음 TedPermission을 실행하게 되면 뜨는 부분으로

타이틀, 내용, OK 버튼을 커스텀할 수 있다.

 

알겠습니다를 누르면, OS에서 제공하는 Permission Check Alert 창이 뜨게 되고,

하나라도 거부를 할 경우에는 그다음에 설정한 Text들을 볼 수 있다.

 

.setDeniedTitle("권한 설정을 거절.")
.setDeniedMessage("권한 설정 하려면 Setting 눌러서 직접 해주세요")
.setDeniedCloseButtonText("닫기")
.setGotoSettingButtonText("설정하러 가봅시다")

 

모든 권한을 설정해주면, 해당 Alert을 확인할 수 없고 Listener에서 설정한 Granted가 호출되게 된다.

하나라도 거절하게 되면, 거절한 권한에 대해서 직접 설정을 할 수 있게 가이드를 해주는 Alert이 뜨게 된다.

타이틀과 내용, 닫기 버튼과 설정 화면으로 이동할 수 있는 버튼의 Text를 변경할 수 있다.

 

설정 화면이란,

 

이처럼 사용자가 직접 권한을 설정할 수 있는 설정 창을 말한다.

 

이렇게 설정을 하면 TedPermission을 사용한 권한 체크 설정이 끝이 나게 된다.

 


간단하게 설정을 해두었지만,

해당 함수가 호출 될 때마다 권한 체크 Alert이 뜨던가, 권한 설정이 완료됐다는 Toast 메시지가 호출되게 된다.

 

필자는 여기서

DataStore을 사용하여 최초의 실행에서만 Permission을 확인하도록 코드를 추가해 보았다.

해당 예제는 MultiModule에 사용했던 예제를 그대로 사용하였다.

전체 코드는 하단에 추가해 두었다.

 

private val permissionKey = booleanPreferencesKey("permissionCheck")

val dataStorePermission: Flow<Boolean> = context.dataStore.data
    .catch { exception ->
        if (exception is IOException) {
            emit(emptyPreferences())
        } else {
            throw exception
        }
    }
    .map { preferences ->
        preferences[permissionKey] ?: false
    }

suspend fun setDataStorePermission(isCheck: Boolean) {
    context.dataStore.edit { preferences ->
        preferences[permissionKey] = isCheck
    }
}

 

DataStore 클래스에 다음과 같이 추가를 해준다.

dataStore를 사용하여 Permission Check에 대한 값을 설정해주고,

매 실행시 해당 값을 가져와서 확인하기 위하여 get/set 함수를 작성해 주었다.

 

class MainViewModel(
    private val navigation: Navigation
) : BaseViewModel(navigation) {

    suspend fun getPermission(): Boolean =
        withContext(CoroutineScope(Dispatchers.Main).coroutineContext) {
            BaseApplication.getInstance().getDataStore().dataStorePermission.first()
        }

    fun setPermission() {
        CoroutineScope(Dispatchers.Main).launch {
            BaseApplication.getInstance().getDataStore().setDataStorePermission(true)
        }
    }

}

 

그 후, MainViewModel에서 해당 값을 가져올 수 있도록 함수를 선언해 주었다.

 

getPermission에서는 first를 사용하여 동기적으로 데이터를 가져올 수 있도록 하였다.

이전 DataStore를 사용하는 예제에서는 CoroutineScope.async와 await()를 사용하였는데, 이처럼 withContext를 사용하여 호출해도 동일하게 동기적으로 데이터를 가져올 수 있다.

물론, 해당 함수를 사용해도 suspend는 붙여야 한다.

 

setPermission에서는 해당 함수가 호출되면 항상 true로 설정되도록 해두었다.

최초 호출 시 정상적으로 permission check가 끝나면 이후에는 다시 호출하지 않도록 하기 위해서 고정된 값을 사용하였다.

 

lifecycleScope.launch {
    if (!viewModel.getPermission()) {
        val permissionListener: PermissionListener = object : PermissionListener {
            override fun onPermissionGranted() {
                Toast.makeText(this@MainActivity,
                    "권한 설정 완료",
                    Toast.LENGTH_SHORT
                ).show()
                viewModel.setPermission()
            }

            override fun onPermissionDenied(deniedPermissions: List<String>) {
                Toast.makeText(
                    this@MainActivity,
                    "권한 거부\n$deniedPermissions",
                    Toast.LENGTH_SHORT
                ).show()
                viewModel.setPermission()
            }
        }
    }
}

 

viewModel에서 해당 함수를 호출하는 부분은, lifecycleScope.launch를 사용하여 별도의 스레드에서 사용하도록 하였다.

 

getPermission이 suspend로 선언되어 있기 때문에 이처럼 추가해 주었다.

getPermission 값은 DataStore에서 선언했다시피, 최초 접근 시 false가 호출되게 된다.

따라서 최초의 접근할 때는 반드시 TedPermission이 호출되게 되며, Listener에서 Override 한 Granted, Denied 함수에서 setPermission을 통해 true로 값을 변경하도록 하였다.

해당 함수를 타지 않는 경우에는 정상적으로 권한 체크가 끝나지 않았다는 것으로 판단하여, 재 접근 시에 호출되도록 하기 위해서이다.

 

이 부분에서 setPermission을 추가한 것은 필자의 개인적인 판단이기 때문에, 정상적으로 함수가 끝나지 않아도 최초 접근이 아니기 때문에 호출하면 안 된다. 하는 사람은 리스너 밖에서 해당 부분이 호출되자마자 값을 true로 세팅해주면 될 것이다.


아주 간단하게 적용해 볼 수 있는 TedPermission을 사용하여,

실제로 프로젝트에 그대로 가져다 놔도 사용할 수 있게 간단한 예제를 만들어 보았다.

다음 프로젝트에서는 DataStore도 사용하여 이처럼 Permission Check를 하도록 만들어 보아야 겠다.

 

TedPermission을 사용한 권한 체크가 워낙 간단하고 간결하게 되어있어서 모두가 적용하기 편할 것이다.

해당 라이브러리에 대한 자세한 정보를 알고 싶으면, 해당 게시글 최상단에 추가해 둔 gitHub 링크에서 확인하길 바란다.

 

해당 게시글에 사용한 예제는 GitHub에 올려두었다.

https://github.com/HeeGyeong/ModuleArchitecture

 

GitHub - HeeGyeong/ModuleArchitecture

Contribute to HeeGyeong/ModuleArchitecture development by creating an account on GitHub.

github.com

 

728x90