TheBigBadBoy
TheBigBadBoy

Reputation: 863

contentResolver album art does not exists but cannot insert it to MediaStore

My device is an Android 11 (API level 29).

I am trying to get album arts (for queried songs) from the contentResolver, and if they do not exist, I want to insert one.

This is my code so far:

val folders = mutableSetOf<File>()
if (relPath.path.isNotEmpty())
    folders.add(File(relPath.path, ".."))
val audioFiles = mutableListOf<AudioFile>()
val currentDir = File("")
val projection = arrayOf(
    MediaStore.Audio.Media._ID,
    MediaStore.Audio.Media.TITLE,
    MediaStore.Audio.Media.ALBUM,
    MediaStore.Audio.Media.ALBUM_ID,
    MediaStore.Audio.Media.ARTIST,
    MediaStore.Audio.Media.DURATION,
    MediaStore.Audio.Media.RELATIVE_PATH,
    MediaStore.Audio.Media.DISPLAY_NAME
)
val sortOrder = MediaStore.Audio.Media.TITLE
contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, null, null, sortOrder)?.use {
    val idIdx = it.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)
    val titleIdx = it.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE)
    val albumIdx = it.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM)
    val albumIdIdx = it.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM_ID)
    val artistIdx = it.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)
    val durationIdx = it.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION)
    val fileRelPathIdx = it.getColumnIndexOrThrow(MediaStore.Audio.Media.RELATIVE_PATH)
    val displayNameIdx = it.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)
    while (it.moveToNext()) {
        val fileRelPath = File(it.getString(fileRelPathIdx).let { if (it == "/") "" else it })

        if (currentDir == fileRelPath) {  // only fetch songs if they are in this directory
            val id = it.getLong(idIdx)  // TODO getColumnIndexOrThrow
            val title = it.getString(titleIdx)
            val album = it.getString(albumIdx)
            val albumId = it.getLong(albumIdIdx)
            val artist = it.getString(artistIdx)
            val duration = it.getLong(durationIdx)
            val displayName = it.getString(displayNameIdx)

//////////////////////// fetch cover art
            val albumArtUri = ContentUris.withAppendedId(Uri.parse("content://media/external/audio/albumart"), albumId)
            var coverArt: Bitmap? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {try {
                contentResolver.loadThumbnail(albumArtUri, android.util.Size(100, 100), null)
            } catch (e: IOException) {
                null
            }} else {
                var albumArtPath: String? = null
                contentResolver.query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, arrayOf(MediaStore.Audio.Albums.ALBUM_ART), "${MediaStore.Audio.Albums._ID} = ?", arrayOf(albumId.toString()), null)?.use {
                    if (it.moveToFirst())
                        albumArtPath = it.getString(it.getColumnIndexOrThrow(MediaStore.Audio.Albums.ALBUM_ART))
                 }
                BitmapFactory.decodeFile(albumArtPath)
            }
////////////////////// end fetch cover art
            audioFiles.add(AudioFile(id, title, album, artist, coverArt, duration))
        }


        // 
        fileRelPath.toRelativeString(relPath).substringBefore('/').takeIf(String::isNotEmpty)?.let { folders.add(if (relPath.path.isEmpty()) File(it) else File(relPath.path, it)) }

    }

}

In the end, to my surprise, none of my songs have an album art (using contentResolver).

$ adb shell content query --uri "content://media/external/audio/albumart"
No result found.
$ adb shell content query --uri "content://media/external/audio/albums" | grep -vc album_art=NULL
0

So currently I am using MediaMetadataRetriever() to fetch the album art:

val retriever = MediaMetadataRetriever()
retriever.setDataSource(File(File("/sdcard", fileRelPath.path), displayName).path)
val data = retriever.embeddedPicture
retriever.release()
if (data != null) {
    coverArt = BitmapFactory.decodeByteArray(data, 0, data.size)
}

Apparently I should insert album arts myself in MediaStore: How can I update the album art path using contentResolver? This is my attempt for a single album art:

val albumArtUri = Uri.parse("content://media/external/audio/albumart")
val values = ContentValues().apply {
    put("album_id", albumId)
    put("_data", "/sdcard/cover.jpg")  // this image does exist
}
contentResolver.insert(albumArtUri, values)

But I get the Error:

android.database.sqlite.SQLiteException: table album_art has no column named _id (code 1 SQLITE_ERROR): , while compiling: INSERT INTO album_art (_data,_id) VALUES (?,_GET_ID( '/storage/emulated/0/Music/_.thumbnails/1730630794351.jpg' ))

I have 3 questions:

I have these in my Manifest:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

So it should be fine(?)

Upvotes: 0

Views: 31

Answers (0)

Related Questions