안드로이드 시스템·Compose 용어 사전
컴포넌트content:// · ContentResolver

ContentProvider

앱 경계를 넘어 데이터를 공유하는 표준 인터페이스. 연락처·미디어 접근의 통로.

앱 경계를 넘어 데이터를 공유하는 표준 인터페이스.

content://com.android.contacts/contacts content://media/external/images/media

URI 로 데이터를 지목하고 ContentResolver 로 접근한다 프로세스가 다르므로 Binder IPC 를 탄다

쓰는 쪽이 대부분이다

val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME)
context.contentResolver.query(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    projection, null, null,
    "${MediaStore.Images.Media.DATE_ADDED} DESC"
)?.use { cursor ->                       // ★ use 로 반드시 닫는다
    val idCol = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
    while (cursor.moveToNext()) { ... }
}

Cursor 를 안 닫으면 누수다 — use{} 로 감싼다 query 는 동기 호출이다 → Dispatchers.IO 에서 부른다

파일을 주고받을 때 — FileProvider

val uri = FileProvider.getUriForFile(ctx, "${ctx.packageName}.fileprovider", file)
val intent = Intent(Intent.ACTION_SEND).apply {
    type = "image/jpeg"
    putExtra(Intent.EXTRA_STREAM, uri)
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)   // ★ 임시 권한을 준다
}

왜 file:// 를 못 쓰나

  • Android 7.0(N) 부터 앱 밖으로 file:// URI 를 넘기면 FileUriExposedException
  • 받는 앱이 내 파일 시스템 경로를 알게 되는 것이 위험하기 때문

FileProvider 는 content:// 로 감싸고 FLAG_GRANT_READ_URI_PERMISSION 으로 '이 URI 만, 잠깐' 접근을 허용한다

만드는 쪽은 드물다

내 앱만 쓰는 데이터라면 ContentProvider 를 만들 이유가 없다

  • Room 이 더 낫다 (타입 안전 · 코루틴/Flow 통합)

만들어야 하는 경우

  • 다른 앱에 데이터를 공개한다
  • 시스템 기능에 연결한다 (검색 제안 · 위젯 · 동기화 어댑터)
  • 라이브러리가 초기화 훅으로 요구한다 (androidx.startup 이 이 방식이다)

보안

<provider
    android:name=".MyProvider"
    android:authorities="com.example.provider"
    android:exported="false" />   <!-- 기본을 닫아 둔다 -->

exported="true" 로 열면서 permission 을 안 걸면 아무 앱이나 내 데이터를 읽는다 — 실제로 흔한 취약점이다 Android 12+ 는 exported 명시를 강제한다

면접 함정

  • "앱 내부 DB 접근에도 ContentProvider를 쓴다" → IPC 오버헤드만 낸다. Room을 쓴다.
  • "query()는 백그라운드에서 알아서 돈다" → 동기 호출이다. 직접 IO 디스패처로 옮긴다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 4대 컴포넌트 — Intent·Service·Receiver·Provider