이번 편의 목표: 주소록 전체 권한과 화면 캡처 권한 없이, 사용자가 고른 연락처 필드와 색 하나만 받습니다.

안드로이드 17은 넓고 영구적인 권한 대신, 이번 동작에서 사용자가 고른 값만 잠깐 넘기는 시스템 화면을 늘렸습니다. 연락처는 ACTION_PICK_CONTACTS로 이메일이나 전화번호처럼 필요한 필드만 고르게 합니다. READ_CONTACTS로 주소록 전체를 읽지 않아도 됩니다. 업무 프로필과 개인 프로필은 이 선택 화면에서 분리됩니다.

화면의 한 점의 색은 ACTION_OPEN_EYE_DROPPER로 받습니다. 앱이 화면 전체를 캡처하거나 미디어 프로젝션을 받을 필요가 없습니다. 결과는 EXTRA_COLOR에 들어 있습니다.

Kotlin
private val eyeDropper = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    if (result.resultCode != Activity.RESULT_OK) {
        return@registerForActivityResult
    }
    val color = result.data?.getIntExtra(Intent.EXTRA_COLOR, Color.BLACK) ?: Color.BLACK
    applyCoverColor(color)
}

fun pickCoverColor() {
    eyeDropper.launch(Intent(Intent.ACTION_OPEN_EYE_DROPPER))
}

사용자가 스포이트를 취소하면 RESULT_OK가 아니므로 기존 색을 유지합니다. 색을 고르면 applyCoverColor만 호출합니다.

사진 선택 화면은 PhotoPickerUiCustomizationParams로 썸네일 비율을 맞출 수 있습니다. 세로 사진만 다루는 앱이 시스템 사진 선택기를 세로 썸네일로 보게 할 때 씁니다. 정확한 위치는 앱 안에 시스템이 그려 주는 위치 단추로, 이번 세션에만 받을 수 있습니다. 세션이 끝나면 정밀 위치 권한은 남지 않습니다.

이 화면들은 앱이 데이터를 보관하지 않습니다. 사용자가 고른 한 건만 결과 인텐트로 들어옵니다.

직접 해 보기

스포이트로 상태 표시줄의 색과 본문의 색을 각각 집어 applyCoverColor에 전달되는 정수가 달라지는지 확인하세요. 취소했을 때는 함수가 호출되지 않아야 합니다.

해설

RESULT_OK인 경우에만 EXTRA_COLOR를 읽습니다. 인텐트 데이터가 없으면 Color.BLACK으로 두고, 취소는 그 분기에 들어가지 않습니다.