Android

[Cursor : 커서] java.lang.IllegalArgumentException: Invalid token LOCALIZED 오류 해결하기

2020-11-20 19:47:30.300 23340-23340/sample.test.musicplayer E/TAG: HI
2020-11-20 19:47:30.311 23340-23340/sample.test.musicplayer E/AndroidRuntime: FATAL EXCEPTION: main
    Process: sample.test.musicplayer, PID: 23340
    java.lang.RuntimeException: Unable to start activity ComponentInfo{sample.test.musicplayer/sample.test.musicplayer.MainActivity}: java.lang.IllegalArgumentException: Invalid token LOCALIZED
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3449)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.IllegalArgumentException: Invalid token LOCALIZED
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:172)
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
        at android.content.ContentProviderProxy.query(ContentProviderNative.java:472)
        at android.content.ContentResolver.query(ContentResolver.java:1183)
        at android.content.ContentResolver.query(ContentResolver.java:1115)
        at android.content.ContentResolver.query(ContentResolver.java:1071)
        at sample.test.musicplayer.common.SongLib$Companion.getMediaSongList(SongLib.kt:147)
        at sample.test.musicplayer.common.SongLib.<init>(SongLib.kt:17)
        at sample.test.musicplayer.MainActivity.onCreate(MainActivity.kt:124)
        at android.app.Activity.performCreate(Activity.java:8000)
        at android.app.Activity.performCreate(Activity.java:7984)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7656) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

[오류가 발생한 코드 스니펫] 오류 원인은 COLLATE LOCALIZED ASC가 문제이다.

            val selection = MediaStore.Audio.Media.IS_MUSIC + " = 1"
            val sortOrder = MediaStore.Audio.Media.TITLE + " COLLATE LOCALIZED ASC"
            
            var cur =  context.contentResolver.query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                mCursorCols,
                selection,
                null,
                sortOrder
            )
fun getMediaSongList(context: Context) : ArrayList<MusicViewModel> {

            val mCursorCols = arrayOf(
                MediaStore.Audio.Media._ID,
                MediaStore.Audio.Media.ARTIST,
                MediaStore.Audio.Media.TITLE,
                MediaStore.Audio.Media.ALBUM,
                MediaStore.Audio.Media.DATA,
                MediaStore.Audio.Media.ALBUM_ID,
                MediaStore.Audio.Media.DURATION,
                MediaStore.Audio.Media.TRACK
            )

            val selection = MediaStore.Audio.Media.IS_MUSIC + " = 1"
            val sortOrder = MediaStore.Audio.Media.TITLE + " COLLATE LOCALIZED ASC"

            var cur =  context.contentResolver.query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                mCursorCols,
                selection,
                null,
                sortOrder
            )

            //cursor = context.contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, "title")



            if (cur != null && cur.moveToFirst()) {
                lateinit var title: String
                lateinit var artist: String
                lateinit var album: String
                var idTruck: Int
    //            - MediaStore.Audio.Albums
    //                    - MediaStore.Audio.Artists
    //                    - MediaStore.Audio.Genres
    //                    - MediaStore.Audio.Playlists
    //                    - MediaStore.Audio.Media
    //
    //                    * Nested Inteface
    //                    - MediaStore.Audio.AlbumColumns      : 앨범을 나타내는 컬럼
    //                    - MediaStore.Audio.ArtistColumns        : 연주자를 나타내는 컬럼
    //                    - MediaStore.Audio.GenresColumns     : 쟝르를 나타내는 컬럼
    //                    - MediaStore.Audio.PlaylistsColumns   : 곡목록을 나타내는 컬럼
    //                    - MediaStore.Audio.AudioColumns       : 여러개의 테이블에서 나타나는 audio file을 위한 컬럼

                idTruck = cur.getColumnIndex(MediaStore.Audio.Media.TRACK)

                // val yearColumn = cursor.getColumnIndex(MediaStore.Audio.Media.YEAR)
                try {
                    do {
                        title = cur.getString(cur.getColumnIndex(MediaStore.Audio.AudioColumns.TITLE))
                        artist = cur.getString(cur.getColumnIndex(MediaStore.Audio.AudioColumns.ARTIST))
                        album = cur.getString(cur.getColumnIndex(MediaStore.Audio.AudioColumns.ALBUM));
                        val albumIds = cur.getLong(cur.getColumnIndex(MediaStore.Audio.AudioColumns.ALBUM_ID))
                        //Log.e("TAG", "title = $title albumIds=$albumIds]    duration: $duration")
                        val audioId = cur.getLong( cur.getColumnIndex(MediaStore.Audio.AudioColumns._ID) )

                        val sArtworkUri = Uri.parse("content://media/external/audio/albumart")
                        val sAlbumArtUri = ContentUris.withAppendedId(sArtworkUri, albumIds)
                        //android.util.Log.i("TAG", "sAlbumArtUri = " + sAlbumArtUri + "]");
                        val externalUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                        val contentUri = ContentUris.withAppendedId(externalUri, audioId)
                        val duration = cur.getLong(cur.getColumnIndex(MediaStore.Audio.AudioColumns.DURATION))


                        val musicVo = MusicViewModel(
                            audioId,
                            title,
                            "서브타이틀",
                            artist,
                            sAlbumArtUri,
                            contentUri,
                            album,
                            duration
                        )
                        musicList.add(musicVo)

                    } while (cur.moveToNext())
                } catch (ee: IllegalStateException) {
                    ee.printStackTrace()
                } catch (se: SecurityException) {
                    se.printStackTrace()
                    //songsList = java.util.ArrayList<MusicVo>()
                } catch (e: Exception) {
                    e.printStackTrace()
                } finally {
                    cur?.close()
                }
            }
            return musicList
        }

[해결방법] 안드로이드 11이 설치된 휴대폰에서 발생하는 오류이다. 안드로이드 10에서는 발생하지 않았다. ” COLLATE LOCALIZED”를 제거하거나 SDK버전를 체크하는 분기문을 작성하면 된다.

            val selection = MediaStore.Audio.Media.IS_MUSIC + " = 1"
            val sortOrder = MediaStore.Audio.Media.TITLE + " ASC"

            var cur =  context.contentResolver.query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                mCursorCols,
                selection,
                null,
                sortOrder
            )
            var sortOrder: String? = null
            sortOrder = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
                MediaStore.Audio.Media.TITLE + " ASC"
            }else{
                MediaStore.Audio.Media.TITLE + " COLLATE LOCALIZED ASC"
            }

Leave a Reply

error: Content is protected !!