마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안드로이드14 대응 커스텀갤러리

0 추천
안드로이드14 대응하고 있습니다 커스텀 갤러리를 사용중이고
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    val imgPermissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES)

    if (imgPermissionCheck == PackageManager.PERMISSION_DENIED
        && ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_MEDIA_IMAGES)
    ) {
        showDeniedDialog()
    } else {
        requestPermission(Manifest.permission.READ_MEDIA_IMAGES)
    }
}

기존에는 이렇게 처리했는데 안드로이드 14에서 권한 모두허용시 정상적으로 동작하나
제한된 엑세스 허용을 누르면 사진이 안나옵니다 onpermissiondenied로 잡히더라구요

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
    val imgPermissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)

    if (imgPermissionCheck == PackageManager.PERMISSION_DENIED) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)) {
            showDeniedDialog()
        } else {
            val permissions = arrayOf(
                Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED,
                Manifest.permission.READ_MEDIA_IMAGES
            )
            requestPermissionAndroid14(permissions)
            requestPermission(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
        }
    }
}

이렇게 분기를 하나추가해주니 기존에 되던 전체허용도 사진이 안나오는 현상이 있고
제한된 엑세스허용도 똑같이 안되고 있습니다 어떻게 해야될까요

수원통학러 (3,590 포인트) 님이 2024년 7월 10일 질문

2개의 답변

0 추천

저는 Android 13 이상인 경우 별도 권한 요청이 아닌

ActivityResultContracts.PickVisualMedia

를 호출하는 방식으로 변경하였습니다.

이게 어떤건지는 찾아보시면 나올테니 길게 설명하지 않겠습니다.

익명사용자 님이 2024년 7월 10일 답변
구글에서 제공하는 피커를 쓰고싶지만 회사에서 커스텀갤러리로 써서요..
0 추천

먼저 SDK가 Android 14 또는 이상이면 READ_MEDIA_VISUAL_USER_SELECTED 를 AndroidManifiest.xml에 추가해야 합니다.

https://developer.android.com/about/versions/14/changes/partial-photo-video-access

런타임 퍼미션도 OS에 맞게 요청해 주시고요.

// Register ActivityResult handler
val requestPermissions = registerForActivityResult(RequestMultiplePermissions()) { results ->
    // Handle permission requests results
    // See the permission example in the Android platform samples: https://github.com/android/platform-samples
}

// Permission request logic
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
    requestPermissions.launch(arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_VISUAL_USER_SELECTED))
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    requestPermissions.launch(arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO))
} else {
    requestPermissions.launch(arrayOf(READ_EXTERNAL_STORAGE))
}

 

안드로이드 14의 경우는 READ_MEDIA_VISUAL_USER_SELECTED 를 핸들링해주셔야 한다고 되어 있습니다.

퍼미션 체크는 아래의 로직을 통해 하라고 되어 있습니다.

if (
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
    (
        ContextCompat.checkSelfPermission(context, READ_MEDIA_IMAGES) == PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(context, READ_MEDIA_VIDEO) == PERMISSION_GRANTED
    )
) {
    // Full access on Android 13 (API level 33) or higher
} else if (
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
    ContextCompat.checkSelfPermission(context, READ_MEDIA_VISUAL_USER_SELECTED) == PERMISSION_GRANTED
) {
    // Partial access on Android 14 (API level 34) or higher
}  else if (ContextCompat.checkSelfPermission(context, READ_EXTERNAL_STORAGE) == PERMISSION_GRANTED) {
    // Full access up to Android 12 (API level 32)
} else {
    // Access denied
}

콜백에서도 적절하게 처리를 해주셔야 합니다.

기존  로직에서 퍼미션이 거절일 때  shouldShowRequestPermissionRationale를 처리하지 마시고 아래 순서로 하세요.
퍼미션 승인 상태 -> 통과
shouldShowRequestPermissionRationale -> 사용자에게 퍼미션이 왜 필요한지 설명
그외 -> 퍼미션 요청 (이 경우는 콜백에서만 처리가 가능하나 모든 경우는 처리되지 않음)

퍼미션 거절은 최초의 상태에서도 나오기 때문에 거절 상태인지 아닌지를 체크하시면 안됩니다. 콜백에서 승인이나 shouldShowRequestPermissionRationale 가 아닌 경우가 나오면 시스템 설정으로 갈 수 있도록 UI를 처리하는 것이 사용자에게 필요할 수 있습니다.

안드로이드 퍼미션 디자인은 기본적으로 문제점이 많은 기능입니다. 테스트를 다양하게 해보고 처리하시는게 제일 좋습니다.

spark (230,170 포인트) 님이 2024년 7월 10일 답변
현재 전체 허용시에는 정상적으로 되고
제한된 액세스 허용시엔 퍼미션 거부가 되면서 한번 더 요청하는데
디나이 메소드에서 Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
허용체크해서 띄우니 되긴됩니다만
권한요청도 두번 이미지 선택기도 두번떠서 플래그로 심어 권한요청을 한번만 하게 했는데요
이번엔 사진이 안나오더라구요 페이징3라이브러리 쪽에 로그심고보니
사진을 3장선택하면 Array list size가 3 찍히고 한번 더호출을 왜하는지 모르겠으나..한번더호출하고 있습니다 그러고 array list size가 0이 되면서 사진이 안나오는 형태인거같은데 이경우엔 어딜봐야될까요..?
님의 코드를 보면

requestPermissionAndroid14(permissions)
requestPermission(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)

퍼미션을 연속으로 두번 요청하고 있어요.

그리고 다시 한번 말씀드리지만, denied는 아무 것도 안해도 리턴되는 상태라서 제일 먼저 체크하시면 안됩니다. granted와 shouldShowRequestPermissionRationale 만 체크하시는게 좋고 denied는 별도로 체크하셔도 정확하게 동작하지 않습니다. 여러 시나리오로 테스트해 보시면 왜 그런지 아실 수 있을 겁니다.

그리고 권한 요청 상태를 플래그를 두어서 처리하시면 안됩니다. 사용자가 시스템으로 가서 퍼미션을 바꾸고 앱으로 올 수가 있습니다. granted나 shouldShowRequestPermissionRationale이 아닌 경우는 퍼미션을 요청한 다음 콜백에서 처리하셔야 해요.
한번 더 말씀드리지만
imgPermissionCheck == PackageManager.PERMISSION_DENIED
는 사용자의 동작에 따라서는 정확하게 동작하지 않는 코드입니다. 한가지의 시나리오는 사용자가 퍼미션 처음 처리할 때, 한번 거절시, 한번 이상 거절시, 권한 다이얼로드의 바깥을 클릭해서 취소한 경우(콜백) 모두 true로 나옵니다.
...