Android

[안드로이드] 콘텐츠 제공자(ContentProvider) 와 콘텐츠 리졸버(ContentResolver)

나맘임 2023. 7. 16. 17:25

ContentProvider란?

앱이 자체적으로 저장한 데이터, 다른 앱이 저장한 데이터에 대한 액세스 권한을 관리하도록 돕고 다른 앱과 데이터를 공유할 수 있는 표준 인터페이스

특징

1. 데이터를 캡슐화하기 때문에 데이터의 보안을 유지할 수 있음

2. 1번의 영향으로 다른 앱의 데이터에 안전하게 액세스하여 이를 수정할 수 있음

3. 데이터 접근 권한이 세부적으로 나누어져있어 원하는 데이터만 공유할 수 있음

4. 앱의 여러 가지 데이터 소스들을 추상화하여 사용이 가능함

5. 데이터는 관계형 데이터베이스 테이블과 유사한 테이블로 표시 됨

6. 콘텐츠 제공자를 구현할 수 있지만 직접 구현할 일은 잘 없고 콘텐츠 제공자로부터 미리 만들어진 데이터를 가져오는 콘텐츠 리졸버(ContentResolver)를 주로 구현함

 

ContentResolver란?

콘텐츠 제공자가 미리 만들어둔 데이터를 가져오는 객체

 

작동방식

ContentResolver는 ContentProvider가 제공하는 데이터 테이블을 CRUD 할  수 있습니다.

본 글에선 검색 기능만 다룹니다.

 

검색을 하기 위해선 contentResolver.query() 메서드를 사용하며 이 메서드는 데이터 테이블에서 SQL 문에서의 select와 동일한 역할을 수행합니다.

 

 

Uri는 콘텐츠 제공자가 제시한 데이터 테이블을 나타내고, projection은 검색할 열을 나타냅니다.

selection은 SQL 문의 where와 동일한 조건을 거는 것이고, sortOrder은 정렬 순서입니다.

 

ContentResolver로 갤러리의 동영상 가져오기

안드로이드는 미디어 정보를 저장할 때 MediaStore를 사용함

미디어엔 동영상, 음악, 사진 등의 다양한 데이터들이 저장되어 있으며 이 각각의 종류마다 하나의 콘텐츠 제공자가 존재함

따라서 콘텐츠 리졸버를 통해 원하는 데이터의 콘텐츠 제공자에 접근하여 데이터를 가져옴

 

<!-- 이미지 가져오기 위한 권한 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

<!-- 비디오 가져오기 위한 권한 -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

<!-- 오디오 가져오기 위한 권한 -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />

<!-- 외부저장소 가져오기 위한 권한 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

 

 

//비디오 데이터를 저장할 데이터 클래스
data class Video(val uri: Uri,
    val name: String,
    val duration: Int,
    val size: Int
)
val videoList = mutableListOf<Video>()

//가져올 미디어의 URI (말 그대로 콜렉션)
val collection =
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        MediaStore.Video.Media.getContentUri(
            MediaStore.VOLUME_EXTERNAL
        )
    } else {
        MediaStore.Video.Media.EXTERNAL_CONTENT_URI
    }
// 가져올 미디어의 칼럼 값들 테이블에서 추출한다고 생각하면 됨
val projection = arrayOf(
    MediaStore.Video.Media._ID,
    MediaStore.Video.Media.DISPLAY_NAME,
    MediaStore.Video.Media.DURATION,
    MediaStore.Video.Media.SIZE
)

// 조건을 나타내며 공식 문서에선 5분 이상의 비디오만 검색되도록 제한을 둠
val selection = "${MediaStore.Video.Media.DURATION} >= ?"
val selectionArgs = arrayOf(
    TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES).toString()
)

// 데이터의 정렬 기준
val sortOrder = "${MediaStore.Video.Media.DISPLAY_NAME} ASC"


// 위에서 설정했던 값들에 따라 ContentResolver를 통해 검색을 진행
val query = ContentResolver.query(
    collection,
    projection,
    selection,
    selectionArgs,
    sortOrder
)
query?.use { cursor ->
    // 가져오기 전 데이터 검증
    val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
    val nameColumn =
            cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME)
    val durationColumn =
            cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)
    val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE)

    while (cursor.moveToNext()) {
        // 커서가 가리키는 값을 임시로 저장
        val id = cursor.getLong(idColumn)
        val name = cursor.getString(nameColumn)
        val duration = cursor.getInt(durationColumn)
        val size = cursor.getInt(sizeColumn)

        val contentUri: Uri = ContentUris.withAppendedId(
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
            id
        )
        //커서가 가리키는 값을 가져와 리스트에 추가
        videoList += Video(contentUri, name, duration, size)
    }
}

'Android' 카테고리의 다른 글

[안드로이드] CustomTextView  (0) 2023.07.30
[안드로이드] 서비스  (0) 2023.07.22
[안드로이드]FragmentManager  (0) 2023.07.09
[안드로이드]DataStore에 대하여  (0) 2023.07.02
[안드로이드]Intent에 관하여  (0) 2023.06.01