상세 컨텐츠

본문 제목

[Android] Permission Setting(권한 설정)

Programming

by Crape Myrtle 2024. 11. 19. 09:54

본문

: 필수 권한과 선택 권한이 있다.

: 기능을 필요로 하지만 필수가 아니라면 Manifest에 다음과 같이 등록해주어야 한다.

: <uses-feature android:name="permission name" android:required="false" />

 

현재 페이지를 보고 있을 미래의 나에게

: ActivityCompat.requestPermissions를 사용해서 권한을 요청하면(권한 요청 시스템 알림 팝업이 뜨겠지)

: 이용자가 권한을 승인하지 않은 상태에서 다시 앱을 접속하게 되면 권한 요청 시스템 알림 팝업이 표출되질 않는다...

: 그렇기 때문에 registerForActivityResult 인스턴스를 생성해서 Permission을 요청하는 것이 확실하다.

: 그리고 권한이 launch할 때 권한을 허용한 것은 알람 팝업이 생기지 않고, 허용하지 않은 권한만 알람 팝업이 표출된다.

 

먼저, 어떤 Permission을 받을 것인지 프로퍼티를 생성

/**
     * [requiredPermissions] required Permissions List.
     * */
    private val requiredPermissions = mutableListOf(
        Manifest.permission.BLUETOOTH,
        Manifest.permission.BLUETOOTH_ADMIN,
    ).apply {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            add(Manifest.permission.BLUETOOTH_SCAN)
            add(Manifest.permission.BLUETOOTH_ADVERTISE)
            add(Manifest.permission.BLUETOOTH_CONNECT)
        }
    }.toTypedArray()
// 요청할 권한 목록
    private val REQUIRED_PERMISSIONS: Array<String> = mutableListOf(
        Manifest.permission.CAMERA,
        Manifest.permission.RECORD_AUDIO
    ).apply {
        // 해당 버전에 맞게 설정하는 부분
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
            add(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        }
    }.toTypedArray()

 

 

함수 형태로 위에서 만든 REQUIRED_PERMISSIONS내용이 허용 되었는지 확인하여,

수락(Grant) 또는 거절(Reject) 되면 Boolean형태로 반환 될 수 있도록 함 

    private fun allPermissionsGranted(): Boolean = REQUIRED_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
    }

 

 

그래서, onCreate( ) 생명주기 함수에서 allPermissionGranted( )함수로 해당 Permission들이 허용된 상태인지 확인하고,

허용 되어 있지 않으면 사용자에게 요청한다. 

내가 보냈던 요청인지를 확인할 수 있는 코드 번호를 함께 보낸다.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // request permissions
        if (allPermissionsGranted()) {
            // Permission Granted
            startCamera()
        } else {
            // Permission Rejected
            ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }
    }

 

 

 

사용자에게 요청한 Permission이 다시 잘 허용 되었는지, 거절 되었는지 onRequestPermissionResult 오버라이드 함수에서 확인할 수 있다.

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                startCamera()
            } else {
                Toast.makeText(baseContext, "Permissions not granted by the user", Toast.LENGTH_SHORT).show()
                NLog.e("onRequestPermissionResult.. Permissions not granted by the user")
                finish()
            }
        }
    }

 

 

 

현재 안드로이드에서 제공하는 가장 심플한 Permission확인 방법이지 않을까 싶다.

혼자 개발하는 입장에서는 이만큼 편리한 방법이 없는 것 같다.

 

+ 추가 (AndroidManifest)

더보기
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    
    <!--request the necessary permissions-->
    <uses-feature android:name="android.hardware.camera.any" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
    
    ...
</manifest>

 

 

단일 Permission체크

: Launcher생성

: MultiplePermission으로 호출할 경우 여러개를 한 번에 선택할 수 있게함

    /**
     * permission
     * */
    // 단일 권한 : RequestPermission()
    // 여러 권한 : RequestMultiplePermission()
    private val requestPermissionLauncher = registerForActivityResult(RequestPermission()) { isGranted: Boolean ->
        NLog.v("requestPermissionLauncher.. isGranted:$isGranted")
        if (isGranted) {
        
        } else {

        }
    }

 

 

permission 확인 함수

: 2가지 요청 방식이 있다

: 시스템 관리 : requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)

: 직접 관리 : requestPermissions(context, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 12345)

    private fun checkPermission() {
        when {
            // 권한이 수락되어 있는지
            ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED -> {
                NLog.v("checkPermission.. checkSelfPermission Granted")
                initChannelInfo()
                createNotificationChannel()
            }
            // 사용자에게 왜 이 권한이 필요한지 설명
            ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.POST_NOTIFICATIONS) -> {
                // CAMERA권한만 주니까 다음 메시지가 표출됨
                Toast.makeText(this, "권한 설정해야해요", Toast.LENGTH_SHORT).show()
                NLog.v("checkPermission.. shouldShowRequestPermissionRationale..")
            } else -> {
                NLog.v("checkPermission.. cancel..")
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
                /*} else {*/
//                    ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.POST_NOTIFICATIONS, Manifest.permission.CAMERA), 12345)
                }
            }
        }
    }

 

 

 

Permission확인 오버라이드 함수

    // Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
    // 왜냐하면 requestPermissionLauncher에서 허용/거부를 체크하기 때문에
    // 이중으로 onRequestPermissionResult에서 체크해줄 필요가 없기 때문이다.
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            NLog.l(LogLevel.VERBOSE)
            NLog.v("onRequestPermissionResult.. requestCode:$requestCode")
            NLog.v("onRequestPermissionResult.. permissions:$permissions")
            NLog.v("onRequestPermissionResult.. grantResults:$grantResults")
            if (grantResults.isNotEmpty() && grantResults.first() == PackageManager.PERMISSION_GRANTED) {
                NLog.v("onRequestPermissionResult.. init..!!")
                initChannelInfo()
                createNotificationChannel()
            }
        }
    }

 

 

 

 : permission권한 허용 시스템 직접 들어가는 방법

: intent를 사용해서 직접 필요한 권한이 있는 위치로 이동시킬 수 있다.

val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (!notificationManager.isNotificationPolicyAccessGranted) {
    val intent = Intent(
        android.provider.Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS
    )

    startActivity(intent)
}

 

// 권한설정
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
String packageName = "package:" + getPackageName();
Log.i(TAG, packageName);
intent.setData(Uri.parse(packageName));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

 


Manifest.permission.READ_PHONE_STATE

: Android기기의 휴대전화 상태 및 정보에 접근할 수 있도록 하는 권한

: 전화번호, 네트워크 상태, SIM카드 정보

: 주로 통화 관련 앱, 통신 관련 앱 및 식별 용도로 사용됨

: 사용자의 개인정보 보호와 관련이 깊다.

 

Manifest.permission.WRITE_EXTERNAL_STORAGE

: 앱이 외부 저장소에 파일을 작성할 수 있음

: 외부라는 것은 휴대기기의 저장소를 뜻 함

Manifest.permission.INTERNET

: 인터넷 연결을 허용하여 '원격서버'와의 통신이 가능해짐

 

Manifest.permission.CAMERA

: 카메라 장치에 접근하여 사진 및 동영상 촬영을 가능하게 함

: 플래시 기능도 가능

 

Manifest.permission.POST_NOTIFICATIONS

: 앱에 알람을 띄우는 것을 허가하는 것

관련글 더보기