나의 경우 마이페이지 자체가 앱 내에서 비중있는 기능이 아니고, 특히 그 중에서도 이미지 수정은 보조 기능이기 때문에 마이페이지가 켜지자마자 나오게 하면 안되고, 수정 버튼을 눌렀을 때 퍼미션 체크를 해서 없으면 권한을 받도록 한다.
또, override fun onRequestPermissionsResult가 deprecated 되었기 때문에, permissionLauncher를 사용하여 권한을 받도록 했다.
private fun initActivityResultContracts() {
permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
getImg()
} else {
val builder = AlertDialog.Builder(requireContext())
builder.setMessage("프로필 이미지 수정을 하시려면\n파일 및 미디어 권한을 허용해주세요")
.setPositiveButton("확인", DialogInterface.OnClickListener { _, _ ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(Uri.parse("package:" + requireActivity().packageName))
startActivity(intent)
})
.setNegativeButton("취소", null)
builder.show()
}
}
imageLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
binding.btnProfileEdit.visibility = View.GONE
profileImgUri = result.data?.data
binding.ivProfileImg.scaleType = ImageView.ScaleType.CENTER_CROP
Glide.with(binding.root).load(profileImgUri).into(binding.ivProfileImg)
}
}
}
private fun checkPermissionVersion() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermission(android.Manifest.permission.READ_MEDIA_IMAGES)
} else {
requestPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
}
}
private fun requestPermission(permission: String) {
if (ContextCompat.checkSelfPermission(requireContext(), permission) != PackageManager.PERMISSION_GRANTED) {
permissionLauncher.launch(permission)
} else {
getImg()
}
}
private fun clickEditImg() {
with(binding) {
btnEditImg.setOnClickListener {
checkPermissionVersion()
}
}
}
private fun getImg() {
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
imageLauncher.launch(intent)
profileImgUri = "".toUri()
}
원래는 이미지 수정 버튼을 클릭하면 바로 이미지 선택 인텐트로 넘어가고, imageLauncher를 통해 바로 가져온 이미지를 ivProfileImg에 세팅해주는 방식이었는데,
이미지 권한이 존재해야지 이미지를 가져올 수 있으므로, 우선 이미지를 가져오도록 인텐트 연결하는 부분을 getImg()로 분리했다. 이 때, profileImgUri이 null 인지 아닌지로 이미지 선택 인텐트에서 돌아올 때 유저 정보가 갱신되는지 아닌지를 판별하기 때문에 "" 빈값을 넣어서 갱신되지 않도록 해준다.
imageLauncher는 permissionLauncher와 함께 초기화 되도록 initActivityResultContracts에 묶어서 onViewCreated에서 초기화 되도록 빼주었다.
clickEditImg을 통해 이미지 수정 버튼을 누르면 먼저 checkPermissionVersion으로 안드로이드 버전에 따른 이미지 접근 권한을 갖도록 한다. 티라미수(13) 버전을 기점으로 저장소에 대한 접근 권한이 세부적(오디오,비디오,이미지)으로 바뀌었는데, 나는 프로필 이미지를 바꾸는 것이기 때문에 13버전부터는 READ_MEDIA_IMAGES를 통해 이미지에 대한 권한만 요구하도록하고, 그 전 버전들은 READ_EXTERNAL_STORAGE 저장소 권한을 그대로 사용한다.
권한 버전 체크를 하면 requestPermission에서 권한이 없는 경우 해당하는 권한을 요청하도록 permissionLauncher.launch를 연결한다. else를 통해 권한이 있다면 바로 이미지 선택 인텐트로 넘어가도록 getImg를 걸어준다.
permissionLauncher에서는 permissionLauncher.launch를 통해 권한이 허용 되었는지 접근 결과값을 isGranted 로 받아서 권한이 허용되었다면 이미지 선택 인텐트로 넘어가고, 허용되지 않았다면 다시 이미지 권한을 선택할 수 있도록 다이얼로그를 생성한다.
-> 권한 체크에서 한 번 허용 안함을 눌러버리면 다시 권한 확인 창이 뜨지 않는다. 그래서 이미지 수정 버튼을 다시 눌러도 권한이 없다고만 나왔기 때문에, 수정을 하고 싶으면 어플을 나가서 앱 설정을 켜서 권한을 추가해줘야한다. 이런 방법으로는 어플 이탈율만 높이고 사용성이 좋지 않다고 판단했기 때문에 다이얼로그를 통해 바로 권한 설정을 할 수 있는 앱 설정 페이지로 넘기는 인텐트를 연결해주었다.