반응형

시스템 설정 변경을 위해서는 android.permission.WRITE_SETTINGS 퍼미션이 필요하다. 익히 알다시피 마시멜로부터는 권한 획득 방법이 바뀌었다. 그런데 이 권한은 마시멜로에 도입된 런타임 권한으로는 얻을 수 없고 조금 다른 방식으로 얻어야 한다.

저번에 만든 셔터음 조절 앱을 최신 API에서도 작동하도록 다시 방법을 연구해봤는데 권한을 얻어도 시스템에 정해져 있는 키를 제외한 키는 수정이 불가해서 시도는 실패로 돌아갔다. (하긴 그게 가능했으면 이미 관련 앱들이 잔뜩 나와 있었겠지...) 아무튼 나중에 또 필요할지 모르니 정리해 둔다.

WRITE_SETTINGS 권한은 마시멜로 이후 다른 권한들과 다르게 허용 여부를 물어보는 게 아닌 설정 창을 띄워서 사용자가 직접 해당 권한을 활성화해주어야 한다. 일단 매니페스트에 권한을 부여해주고

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

(여담이지만 저 권한을 적으면 안드로이드 스튜디오에서 시스템 앱에만 부여되는 권한이라고 빨간색으로 표시된다. 거슬리지만 저게 없으면 설정 창에서 권한을 활성화할 수가 없다.)

Settings.System.canWrite 메소드로 권한이 있는지 없는지를 알 수 있다. 권한이 없으면 아래 코드처럼 Settings.ACTION_MANAGE_WRITE_SETTINGS에 인텐트를 날려서 사용자가 직접 권한을 활성화할 수 있게 만들면 된다.


if (!Settings.System.canWrite(this)) {
    val alertDialog = AlertDialog.Builder(this)
            .setTitle("권한 요청")
            .setMessage("시스템 설정 변경 권한이 필요합니다.\n권한 허용 창으로 이동합니다. 권한을 허용해 주세요.")
            .setPositiveButton("계속") { dialogInterface: DialogInterface, _: Int ->
                val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
                intent.data = Uri.parse("package:${packageName}")
                startActivityForResult(intent, 0)
                dialogInterface.dismiss()
            }.setNegativeButton("취소") { dialogInterface: DialogInterface, _: Int ->
                Toast.makeText(this, "권한을 얻지 못하였습니다", Toast.LENGTH_SHORT).show()
                dialogInterface.cancel()
            }.create()
    alertDialog.show()
}

설정 창에서 앱으로 돌아오면 onActivityResult가 실행되니 여기서 적절한 행동을 하면 된다.


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

    if (resultCode == 0) {
        if (Settings.System.canWrite(this)) {
            Toast.makeText(this, "권한을 얻었습니다", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(this, "권한을 얻지 못하였습니다", Toast.LENGTH_SHORT).show()
        }
    }
}

정리 끝!

반응형

+ Recent posts