본문 바로가기
Programando/Android

[Android/Kotlin] 기기 권한 받아오기_(6)

기기 권한 받아오기

1. 앱에 이미 권한이 부여되었는지 확인

when {
    ContextCompat.checkSelfPermission(
        this,
        android.Manifest.permission.READ_EXTERNAL_STOREAGE
    ) == PackageManager.PERMISSON_GRANTED -> { // 권한이 부여되어 있다면
        // 갤러리에서 사진 선택
    }
    else -> { // 권한이 부여되어 있지 않다면
        // 권한 요청
    }
}

: ContextCompat.checkSelfPermission( ) 메서드에 권한을 전달하면, 이 메서드는 앱에 권한이 있는지에 따라 PERMISSION_GRANTED 또는 PERMISSION_DENIED를 반환한다.

 

2. 앱에 권한이 필요한 이유 설명

when {
    ContextCompat.checkSelfPermission(
        this,
        android.Manifest.permission.READ_EXTERNAL_STORAGE
    ) == PackageManager.PERMISSION_GRANTED -> {
    }
    shouldShowRequestPermissionRationale(android.Manifest.permission.READ_EXTERNAL_STORAGE) -> {
        // 교육용 UI를 사용자에게 표시 : 사용자가 사용 설정하려는 기능에 특정 권한이 필요한 이유를 설명
        showPermissionContextPopup()
    }
    else -> {
        // 권한 요청
    }
}

...

private fun showPermissionContextPopup() {
    AlertDialog.Builder(this)
        .setTitle("권한 요청")
        .setMessage("앱에서 사진을 불러오기 위해 권한이 필요합니다.")
        .setPositiveButton("동의", { _, _ ->
                requestPermissions(
                    arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
                    1000
                )
        })
        .setNegativeButton("취소", { _,_ -> })
        .create()
        .show()
}

: ContextCompat.checkSelfPermission( ) 메서드가 PERMISSION_DENIED를 반환하면 shouldShowRequestPermissionRationale( )를 호출하고, 이 메서드가 true를 반환하면 왜 이 권한이 필요한지를 설명하는 교육용 UI를 사용자에게 표시한다.

 

3. 권한 요청

when {
    ContextCompat.checkSelfPermission(
        this,
        android.Manifest.permission.READ_EXTERNAL_STORAGE
    ) == PackageManager.PERMISSION_GRANTED -> {
    }
    shouldShowRequestPermissionRationale(android.Manifest.permission.READ_EXTERNAL_STORAGE) -> {
        showPermissionContextPopup()
    }
    else -> {
        // 권한 요청
        requestPermissions(
            arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
            1000 // requestCode
        )
    }
}

: 단일 권한을 요청하려면 RequestPermission을 사용하고, 여러 권한을 동시에 요청하려면 RequestMultiplePermissions를 사용한다.

 

권한을 통해 사진 가져오기

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        
        when(requestCode) {
            1000 -> {
                if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // 권한 요청이 수락되었을 때
                    navigateGallery()
                } else {
                    // 권한 요청이 거부되었을 때
                    Toast.makeText(this, "권한을 거부하였습니다", Toast.LENGTH_SHORT).show()
                }
            }
            else -> {
            
            }
        }
    }

: onRequestPermissionsResult( )를 overried 한다. 개발자가 정의한 요청 코드와 반환된 requestCode의 값이 같으면 권한이 잘 부여되었는지나 혹은 권한이 거부되었는지를 확인하고, 권한이 수락되었을 때는 사용자의 갤러리를 탐색한다.

 

    private fun navigateGallery() {
        val intent = Intent(Intent.ACTION_GET_CONTENT)
        intent.type = "image/*"
        startActivityForResult(intent, 2000)
    }

: saf 기능을 이용한다. ACTION_GET_CONTENT 인텐트를 호출하면 ContentResolver.openInputStream( )을 사용하여 열 수 있는 데이터에 대한 모든 선택지를 표시하여 사용자가 이 데이터 중 하나를 선택한 다음 그 안의 데이터를 선택하고 결과 URI를 호출자에게 반환할 수 있도록 한다. startActivityForResult( )를 사용하여 Intent를 옮긴다.

 

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if(resultCode != Activity.RESULT_OK) {
            return
        }

        when(requestCode) {
            2000 -> {
                val selectedImageUri : Uri? = data?.data
                // nullable

                if(selectedImageUri != null) { // null 체크

                    if(imageUriList.size == 6) {
                        Toast.makeText(this, "이미 사진첩이 꽉 찼습니다.", Toast.LENGTH_SHORT).show()
                        return
                    }

                    imageUriList.add(selectedImageUri)
                    imageViewList[imageUriList.size - 1].setImageURI(selectedImageUri)
                } else {
                    Toast.makeText(this,"사진을 가져오지 못했습니다.", Toast.LENGTH_SHORT).show()
                }

            }
            else -> {
                Toast.makeText(this, "사진을 가져오지 못했습니다.", Toast.LENGTH_SHORT).show()
            }
        }

    }

: onActivityResult( )를 사용해 선택한 이미지의 URI을 가지고 와 ImageView에 넣어준다.

 


 

참고 사이트

반응형