permission
개발포스팅은 언제나 유통기한을 조심하세요.
Github : https://github.com/junghun9102/AndroidTemplate
Branch : base/permission
권한이 필요한 기능에 대한 동작 정의
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)
}