티스토리 뷰

권한 처리

  1. 일반 권한 (internet) : manifest에 명시해주는 것 만으로도 사용할 수 있다.
  2. 위험 권한 (camera) : manifest에도 명시하고 코드에서도 한 번 더 확인해야함
    • 개인정보 관련된 정보를 앱이 사용자에게 한 번 더 확인하여 물어보게 됨

간단한 권한 요청 (카메라 권한 요청)

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.example.permission.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        binding.permissionButton.setOnClickListener {
            checkPermission()
        }

    }

    private fun checkPermission() {
        // 카메라 권한이 뭔지를 체크를 해서 cameraPermission에 저장
        val cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)

        if(cameraPermission == PackageManager.PERMISSION_GRANTED) {
            openCamera()
        } else {
            requestPermission()
        }
    }

    private fun openCamera() {
        Toast.makeText(this,"카메라를 실행합니다.", Toast.LENGTH_SHORT).show()

        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                // startActivityForResult 이제 지원안함
        startActivityForResult(intent, 99)
    }

    private fun requestPermission() {
        // 실제 권한 요청
        // ActivityCompat를 쓰는 이유는 하위 버전에서는 호환이 안될 수 있어서임
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 99)
        // 이렇게 하면 사용자에게 위 권한을 사용할건지 물어보게 됨
        // 그리고 승인하든 거절하든 그 결과값은 onRequestPermissionsResult으로 가게 됨.
    }

        // onRequestPermissionsResult으로 가게 됨.
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when(requestCode) {
            99 -> {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    openCamera()
                } else {
                    Toast.makeText(this, "권한을 승인하지 않으면 앱이 종료됩니다.", Toast.LENGTH_SHORT).show()
                    finish()
                }
            }
        }
    }
}
  • 내일 할 일 registerForActivityResult에 대해 꼭 알아보기

출처:

Android - 앱 권한 요청 (kotlin)

Permission 중에는 여러 가지 permission이 있는데, 이 중 앱이 사용자에게 요청을 하고 사용자가 이를 수락해야 받을 수 있는 permission을 runtime permission이라고 한다.

따라서 permission이 필요한 API를 사용하려면, 꼭 수락이 필요하다. (외부 저장소에 접근한다던가 그런 경우를 의미힌다.)

더욱이 만약에 앱이 보낸 요청을 사용자가 거부한다면, 이를 위한 예외처리도 필요하다.

참고로 runtime permission은 SDK API 23(Mashmello)부터 지원된다. 23 미만의 경우 앱이 설치될 때 퍼미션을 획득한다고 한다. 그렇기 때문에 23 미만은 runtime permission을 따로 요청하지 않아도 된다.

추가적으로 설치될 때 얻는 permission을 install permission이라고 한다.

🌕 Permission Request API

Activity가 AppCompatActivity()를 상속하면 대표적으로 3개의 permission API를 사용할 수 있다.

  1. checkSelfPermission() 권한이 있는지 확인
    • 앱에 권한이 필요한 이유 설명 (실제 android 공식 문서에 있는 설명)
      • ContextCompat.checkSelfPermission() 메서드가 PERMISSION_DENIED를 반환하면 [shouldShowRequestPermissionRationale()](https://developer.android.com/reference/androidx/core/app/ActivityCompat?hl=ko#shouldShowRequestPermissionRationale(android.app.Activity,%20java.lang.String))을 호출하세요. 이 메서드가 true를 반환하면 교육용 UI를 사용자에게 표시합니다. 이 UI에서 사용자가 사용 설정하려는 기능에 특정 권한이 필요한 이유를 설명합니다.
  2. requestPermssion() 권한이 없으면 권한을 사용자에게 요청함
  3. shouldShowRequestPermissonRational()

위 API를 활용하면, 앱이 permission을 사용자에게 요청할 수 있습니다.

또한 ActivityCompat으로 동일한 동작을 수행하는 API를 사용할 수 있습니다.

  1. ActivityCompat.checkSelfPermission()
  2. ContextCompat.checkSelfPermission() → 이번 예시 플젝에서 사용한 API
  3. ActivityCompat.requestPermissions()
  4. ActivityCompat.shouldShowRequestPermissionRationale()

📖 permission이 있는지 확인하기

checkSelfPermission()으로 앱이 permission을 갖고 있는지 확인할 수 있다. 이를 위해 다음과 같은 코드를 작성해보자.

if (checkSeldPermission(android.Manifest.Permission.READ_EXTERNAL_STORAGE)) {
        // Permission이 granted 됨
}
else {
        // Permission이 denied 됨
}

근데 여기서 중요한건 android.Manifest.Permission.READ_EXTERNAL_STORAGE를 사용하려면 AndroidManifest.xml안에 다음과 같은 코드를 작성해주어야 함.

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

위 의미는 현재 앱이 permission을 해야하는 것을 알리는 것임.

그리고 packageManager에서 PERMISSION_GRANTEDPERMISSION_DENIED를 확인할 수 있음.

requestPermissions의 경우 안에 array가 들어가야 하기 때문에 arrayOf를 이용함.