창고

permission

날아갔나요 2020. 2. 26. 17:49

개발포스팅은 언제나 유통기한을 조심하세요.

 

 

Github : https://github.com/junghun9102/AndroidTemplate

Branch : base/permission

 

junghun9102/AndroidTemplate

Contribute to junghun9102/AndroidTemplate development by creating an account on GitHub.

github.com

 

 

권한이 필요한 기능에 대한 동작 정의

 

1. Manifest에 권한을 추가한다.

2. 권한이 필요한 기능을 요청한다.

3-1. 권한이 있다면 그대로 기능을 실행 -> FIN

3-2. 권한이 없다면 권한 요청 -> 4

4-1. 권한 요청 수락하면 기능 실행

4-2. 권한 요청 거절하면 메시지 표시

 

 

 

전체코드 먼저 보기

더보기
object PermissionHelper {

    const val PERMISSIONS_CAMERA = 1

    private val permissionList = mapOf(
        PERMISSIONS_CAMERA to arrayOf(android.Manifest.permission.CAMERA)
    )

    private fun getPermissions(requestCode: Int) = permissionList[requestCode] ?: throw IllegalArgumentException("You must use requestCode defined at PermissionHelper")

    fun checkPermission(context: Context, requestCode: Int): Boolean {
        val permissions = getPermissions(requestCode)
        return checkPermissions(context, permissions)
    }

    private fun checkPermission(context: Context, permission: String): Boolean {
        return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
    }

    private fun checkPermissions(context: Context, permissions: Array<String>): Boolean {
        return permissions.fold(true, { acc, permission ->
            acc && checkPermission(context, permission)
        })
    }

    fun requestPermissions(activity: Activity, requestCode: Int) {
        val permissions = getPermissions(requestCode)
        ActivityCompat.requestPermissions(activity, permissions, requestCode)
    }

    fun onRequestPermissionResult(context: Context, requestCode: Int, funcAllowed: () -> Unit, funcNotAllowed: () -> Unit = {}) {
        val permissions = getPermissions(requestCode)
        if (checkPermissions(context, permissions)) {
            funcAllowed.invoke()
        } else {
            funcNotAllowed.invoke()
        }
    }
}

// PermissionHelper Extensions
fun Activity.requestPermissions(requestCode: Int) = PermissionHelper.requestPermissions(this, requestCode)

fun Context.checkPermissions(requestCode: Int) = PermissionHelper.checkPermission(this, requestCode)

fun Context.onRequestPermissionResult(requestCode: Int, funcAllowed: () -> Unit, funcNotAllowed: () -> Unit = {}) =
    PermissionHelper.onRequestPermissionResult(this, requestCode, funcAllowed, funcNotAllowed)

fun Activity.checkPermissionsAndDoFunctionOrRequest(requestCode: Int, funcAllowed: () -> Unit) {
    if (this.checkPermissions(requestCode))
        funcAllowed.invoke()
    else
        this.requestPermissions(requestCode)
}

 

 

 


필요한 권한 추가 (1)

 

AndroidManifest.xml

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

 

권한 정리

    const val PERMISSIONS_CAMERA = 1

    private val permissionList = mapOf(
        PERMISSIONS_CAMERA to arrayOf(android.Manifest.permission.CAMERA)
    )

 

기능별로 필요한 권한들을 정리해둔다.

 

 

 

 

 


기능 요청 (2 ~ 3)

 

MainActivity

    private fun initViews() {
        btn_main_camera.setOnClickListener {
            checkPermissionAndStartCamera()
        }
    }

    private fun checkPermissionAndStartCamera() {
        checkPermissionsAndDoFunctionOrRequest(PermissionHelper.PERMISSIONS_CAMERA) {
            startCamera()
        }
    }

    private fun startCamera() {
        Toast.makeText(this, "카메라를 시작합니다 위이잉", Toast.LENGTH_SHORT).show()
    }

 

권한이 있다면 바로 기능 수행

 

 

extensions

fun Activity.requestPermissions(requestCode: Int) = PermissionHelper.requestPermissions(this, requestCode)

fun Context.checkPermissions(requestCode: Int) = PermissionHelper.checkPermission(this, requestCode)

fun Activity.checkPermissionsAndDoFunctionOrRequest(requestCode: Int, funcAllowed: () -> Unit) {
    if (this.checkPermissions(requestCode))
        funcAllowed.invoke()
    else
        this.requestPermissions(requestCode)
}

 

Activity.checkPermissionsAndDoFunctionOrRequest에서 퍼미션을 체크하고

모두 권한이 주어져있다면 funcAllowed가 아니라면 requestPermissions 수행

 

 

PermissionHelper

object PermissionHelper {

    const val PERMISSIONS_CAMERA = 1

    private val permissionList = mapOf(
        PERMISSIONS_CAMERA to arrayOf(android.Manifest.permission.CAMERA)
    )

    private fun getPermissions(requestCode: Int) = permissionList[requestCode] ?: throw IllegalArgumentException("You must use requestCode defined at PermissionHelper")

    fun checkPermission(context: Context, requestCode: Int): Boolean {
        val permissions = getPermissions(requestCode)
        return checkPermissions(context, permissions)
    }

    private fun checkPermission(context: Context, permission: String): Boolean {
        return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
    }

    private fun checkPermissions(context: Context, permissions: Array<String>): Boolean {
        return permissions.fold(true, { acc, permission ->
            acc && checkPermission(context, permission)
        })
    }

    fun requestPermissions(activity: Activity, requestCode: Int) {
        val permissions = getPermissions(requestCode)
        ActivityCompat.requestPermissions(activity, permissions, requestCode)
    }
    
    ...
    
}

 

코드가 길어 읽기 싫지만 별거없는 코드다.

 

 

 

 

 


권한 요청에 따른 반응 (4)

 

MainActivity

	override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        when (requestCode) {
            PermissionHelper.PERMISSIONS_CAMERA ->
                onRequestPermissionResult(PermissionHelper.PERMISSIONS_CAMERA, {
                    startCamera()
                }) {
                    showPermissionDeniedMessage()
                }
        }
    }

    private fun showPermissionDeniedMessage() {
        Toast.makeText(this, "권한을 허용하지 않아 카메라를 사용할 수 없습니다.", Toast.LENGTH_SHORT).show()
    }

 

권한 요청에 응답을 한 뒤에

다시 요청한 권한리스트를 확인하고 이에 따라 기능을 수행하거나 거부했을 때의 기능을 수행한다.

절대적으로 권한을 승락하게 하고 싶다면 Activity.checkPermissionsAndDoFunctionOrRequest를 사용하면 거절시 다시 요청하게 된다.

 

 

PermissionHelper

    fun onRequestPermissionResult(context: Context, requestCode: Int, funcAllowed: () -> Unit, funcNotAllowed: () -> Unit = {}) {
        val permissions = getPermissions(requestCode)
        if (checkPermissions(context, permissions)) {
            funcAllowed.invoke()
        } else {
            funcNotAllowed.invoke()
        }
    }

 

퍼미션에 관한 코드를 캡슐화함으로 MainActivity의 코드가 많이 줄었다.

권한과 관련된 유명한 TedPermission도 있지만 직접 내 코드를 만들고 싶었다.

 

 

 

 

 


전체 코드

 

object PermissionHelper {

    const val PERMISSIONS_CAMERA = 1

    private val permissionList = mapOf(
        PERMISSIONS_CAMERA to arrayOf(android.Manifest.permission.CAMERA)
    )

    private fun getPermissions(requestCode: Int) = permissionList[requestCode] ?: throw IllegalArgumentException("You must use requestCode defined at PermissionHelper")

    fun checkPermission(context: Context, requestCode: Int): Boolean {
        val permissions = getPermissions(requestCode)
        return checkPermissions(context, permissions)
    }

    private fun checkPermission(context: Context, permission: String): Boolean {
        return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
    }

    private fun checkPermissions(context: Context, permissions: Array<String>): Boolean {
        return permissions.fold(true, { acc, permission ->
            acc && checkPermission(context, permission)
        })
    }

    fun requestPermissions(activity: Activity, requestCode: Int) {
        val permissions = getPermissions(requestCode)
        ActivityCompat.requestPermissions(activity, permissions, requestCode)
    }

    fun onRequestPermissionResult(context: Context, requestCode: Int, funcAllowed: () -> Unit, funcNotAllowed: () -> Unit = {}) {
        val permissions = getPermissions(requestCode)
        if (checkPermissions(context, permissions)) {
            funcAllowed.invoke()
        } else {
            funcNotAllowed.invoke()
        }
    }
}

// PermissionHelper Extensions
fun Activity.requestPermissions(requestCode: Int) = PermissionHelper.requestPermissions(this, requestCode)

fun Context.checkPermissions(requestCode: Int) = PermissionHelper.checkPermission(this, requestCode)

fun Context.onRequestPermissionResult(requestCode: Int, funcAllowed: () -> Unit, funcNotAllowed: () -> Unit = {}) =
    PermissionHelper.onRequestPermissionResult(this, requestCode, funcAllowed, funcNotAllowed)

fun Activity.checkPermissionsAndDoFunctionOrRequest(requestCode: Int, funcAllowed: () -> Unit) {
    if (this.checkPermissions(requestCode))
        funcAllowed.invoke()
    else
        this.requestPermissions(requestCode)
}