상세 컨텐츠

본문 제목

[Kotlin] 컨텐트 리졸버(Content Resolver)

Mobile/Kotlin

by 클리엘 2021. 1. 11. 11:35

본문

728x90

어떤 앱에서 자신이 사용하는 데이터를 다른 앱에 제공하기 위해 컨텐트 프로바이더(Content Provider)를 사용할 수 있습니다. 컨텐트 프로바이더를 제공하는 앱이 있으면 다른 앱에서는 컨텐트 리졸버(Content Resolver)를 만들어 컨텐트 프로바이더에서 제공하는 데이터를 받아올 수 있게 됩니다.

 

굳이 특정 앱이 아니더라도 안드로이드에서는 기기의 사진이나 연락처, 음악 데이터 등 여러 가지 데이터를 컨텐트 프로바이더를 통해 제공하고 있으므로 컨텐트 리졸버를 통해 해당 데이터를 가져올 수 있습니다.

 

현재 휴대폰에 저장된 음악목록을 가져오는 예시를 통해 컨텐트 리졸버의 활용방법을 간단히 알아보도록 하겠습니다.

 

우선 app -> manifests -> AndroidManifest.xml 파일에 다음 태그를 추가합니다. 안드로이드에서는 사진, 음악 등의 데이터는 MediaStore에 저장하고 있고 MediaStore에서는 각 미디어 종류마다 별도의 컨텐트 프로바이더를 제공하고 있습니다. 그런데 이 MediaStore는 외부 저장소에 해당하므로 외부 저장소에 접근하기 위한 권한이 필요한 것입니다.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>

위에서 권한이 필요하다는 것을 명시하였으므로 해당 권한에 대한 처리를 구현합니다. 이를 위해 제일먼저 외부 저장소에 대한 권한이 있는지를 확인합니다.

fun checkPermission(view: View) {
    val storagePermission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE)

    if (storagePermission == PackageManager.PERMISSION_GRANTED) {
        // 권한있음
    }
    else {
        getPermission()
    }
}

만약 권한이 없는 경우 사용자로부터 권한을 요청합니다. 만약 권한요청이 거부되면 앱을 곧장 종료하도록 합니다. 권한에 관해서는 이미 언급된 적이 있으므로 자세한 설명은 생략하도록 하겠습니다.

fun getPermission()
{
    ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE), 1)
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    when (requestCode) {
        1 -> {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 권한 허용
            }
            else {
                finish()
            }
        }
    }
}

위에서 권한을 확인할때 권한이 주어져 있는 경우나 권한을 요청할 때 승인이 떨어진 경우 음악 목록을 가져오는 메서드를 작성합니다.

fun getMusicList()
{

}

이때 음악목록의 경우 MediaStore.Audio.Media.EXTERNAL_CONTENT_URI 상수를 통해 어디에서 데이터를 가져와야 하는지 지정할 수 있습니다.

fun getMusicList()
{
    val mediaMusicURI = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}

해당 위치에서 데이터를 가져올 때 어떤 데이터를 가져올지를 지정합니다. 데이터베이스에서 URI가 테이블이라면 테이블의 어떤 칼럼을 가져올지를 지정하는 것이라고 보면 되겠습니다. 아래 예제에서는 음악의 고유 ID값과 제목을 가져올 수 있도록 하였습니다.

fun getMusicList()
{
    val mediaMusicURI = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    val mediaMusicType = arrayOf(MediaStore.Audio.Media.ALBUM_ID, MediaStore.Audio.Media.TITLE)
}

어디서, 어떤 데이터를 가져올지가 정해졌으면 이를 컨텐트 리졸버를 통해 질의메서드에 실어 보내면 그 결과를 커서 형태로 반환하게 됩니다. 참고로 query메서드의 3번째 매개변수는 데이터 검색 시 검색 대상이 되는 칼럼을, 4번째는 3번째 매개변수에 지정한 칼럼에서 실제 검색 대상이 될 값을, 5번째는 데이터의 정렬순서를 지정합니다.

fun getMusicList()
{
    val mediaMusicURI = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    val mediaMusicType = arrayOf(MediaStore.Audio.Media.ALBUM_ID, MediaStore.Audio.Media.TITLE)

    val cursor = contentResolver.query(mediaMusicURI, mediaMusicType, null, null, null)
}

커서를 순회하면서 하나씩 데이터를 가져와 로그켓에 표시할 수 있도록 합니다. 이때 getColjumnIndex()는 지정한 값이 몇번째 칼럼인지에 대한 인텍스를 반환하며 getString()은 인덱스에 따른 실제 값을 반환합니다.

fun getMusicList()
{
    val mediaMusicURI = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
    val mediaMusicType = arrayOf(MediaStore.Audio.Media.ALBUM_ID, MediaStore.Audio.Media.TITLE)

    val cursor = contentResolver.query(mediaMusicURI, mediaMusicType, null, null, null)

    if (cursor != null) {
        while (cursor.moveToNext()) {
            var index = cursor.getColumnIndex(mediaMusicType[0])
            var id = cursor.getString(index)

            index = cursor.getColumnIndex(mediaMusicType[1])
            var title = cursor.getString(index)

            Log.i("test", "${id}--${title}")
        }
    }
}

이렇게 완성된 메서드를 위에서 선행한 권한처리관련 코드에 추가합니다.

fun checkPermission(view: View) {
    val storagePermission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE)

    if (storagePermission == PackageManager.PERMISSION_GRANTED) {
        getMusicList()
    }
    else {
        getPermission()
    }
}

fun getPermission()
{
    ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE), 1)
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    when (requestCode) {
        1 -> {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getMusicList()
            }
            else {
                finish()
            }
        }
    }
}

마지막으로 Activity에는 버튼 하나를 배치합니다. 그리고 속성 창에서 버튼의 onClick이벤트에 checkPermission() 메서드를 지정합니다. 위에서 checkPermission() 메서드 작성 시 view 매개변수를 지정한 것은 바로 이 때문입니다.

 

앱을 실행하고 버튼을 누르면 권한 요청이 표시되고 권한을 허용하면 정상적으로 음악의 목록이 표시됨을 확인할 수 있습니다.

 

 

728x90

'Mobile > Kotlin' 카테고리의 다른 글

[Kotlin] 권한의 이해  (0) 2021.02.24
[Kotlin] HttpURLConnection  (0) 2021.01.12
[Kotlin] 컨텐트 리졸버(Content Resolver)  (0) 2021.01.11
[Kotlin] 포어그라운드(Foreground) 서비스  (0) 2021.01.08
[Kotlin] 서비스(Service)  (0) 2021.01.07
[Kotlin] AsyncTask  (0) 2021.01.06

관련글 더보기

댓글 영역