Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to efficiently extract album art from any music file using Kotlin Coroutines

In my app I'm trying to extract album arts from all music files in phone storage and then I populate them into my RecyclerView. I'm successfully getting everything but still it's taking a lot of time for all tracks to get rendered into my RecyclerView. All I want to do is as soon as my app is launched all tracks should be filled up in RecyclerView instantly with appropriate album art without any delay. I tried to put my code into coroutines but still it is taking a lot of delay. Any help will be appreciated.

fun getSongList() = GlobalScope.launch(Dispatchers.IO)
    {
        async {
         realm = Realm.getDefaultInstance()
        val iterator = FileUtils.iterateFiles(
                Environment.getExternalStorageDirectory(),
                FileFilterUtils.suffixFileFilter("m4a"),
                TrueFileFilter.INSTANCE)
        while (iterator.hasNext()) {
            try {
                val fileINeed = iterator.next()
                val thisurls = fileINeed.canonicalPath
                val mmr = MediaMetadataRetriever()
                mmr.setDataSource(thisurls)
                var thisTitle = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
                var thisArtist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
                if (thisTitle.isNullOrEmpty()) {
                    thisTitle = fileINeed.name
                }
                if (thisArtist.isNullOrEmpty()) {
                    thisArtist = "Unknown Artist"
                }
                val query = realm!!.where(Songdetails::class.java).equalTo("songname",thisTitle).findFirst()
                if(query == null)
                {
                    val retriever = MediaMetadataRetriever()
                    retriever.setDataSource(thisurls)
                    val art = retriever.embeddedPicture
                    if (art != null) {
                        var bitmap = BitmapFactory.decodeByteArray(art, 0, art.size)
                        ImageSaver(MainActivity.getInstance()!!)
                                .setFileName(thisTitle)
                                .setDirectoryName("images")
                                .save(bitmap)
                         realm = Realm.getDefaultInstance()
                        realm!!.executeTransaction(object : Realm.Transaction {

                            override fun execute(realm: Realm) {
                                // increment index
                                var num = realm.where(Songdetails::class.java).max("id")
                                var nextID: Int
                                if (num == null) {
                                    nextID = 1
                                } else {
                                    nextID = num.toInt() + 1
                                }
                                var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                songitem.songname = thisTitle
                                songitem.songartist = thisArtist
                                songitem.songurl = thisurls
                                songitem.songimage = thisTitle
                                EventBus.getDefault().post("update")
                            }
                        })
                    }
                    else{
                         realm = Realm.getDefaultInstance()
                        realm!!.executeTransaction(object : Realm.Transaction {

                            override fun execute(realm: Realm) {
                                // increment index
                                var num = realm.where(Songdetails::class.java).max("id")
                                var nextID: Int
                                if (num == null) {
                                    nextID = 1
                                } else {
                                    nextID = num.toInt() + 1
                                }
                                var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                songitem.songname = thisTitle
                                songitem.songartist = thisArtist
                                songitem.songurl = thisurls
                                songitem.songimage = "custom"
                                EventBus.getDefault().post("update")
                            }
                        })
                    }
                }
            }catch (ex:Exception)
            {

            }
        }
         realm = Realm.getDefaultInstance()
        val mp3iterator = FileUtils.iterateFiles(
                Environment.getExternalStorageDirectory(),
                FileFilterUtils.suffixFileFilter("mp3"),
                TrueFileFilter.INSTANCE)
        while (mp3iterator.hasNext()) {
            try {
                val fileINeed = mp3iterator.next()
                val thisurls = fileINeed.canonicalPath
                val mmr = MediaMetadataRetriever()
                mmr.setDataSource(thisurls)
                var thisTitle = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
                var thisArtist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
                if (!thisTitle.isNullOrEmpty()) {
                    val query = realm!!.where(Songdetails::class.java).equalTo("songname", thisTitle).findFirst()
                    if (query == null) {
                        val retriever = MediaMetadataRetriever()
                        retriever.setDataSource(thisurls)
                        val art = retriever.embeddedPicture
                        if (art != null) {
                            var bitmap = BitmapFactory.decodeByteArray(art, 0, art.size)
                            ImageSaver(MainActivity.getInstance()!!)
                                    .setFileName(thisTitle)
                                    .setDirectoryName("images")
                                    .save(bitmap)
                            realm = Realm.getDefaultInstance()
                           realm!!.executeTransaction(object : Realm.Transaction {

                                override fun execute(realm: Realm) {
                                    // increment index
                                    var num = realm.where(Songdetails::class.java).max("id")
                                    var nextID: Int
                                    if (num == null) {
                                        nextID = 1
                                    } else {
                                        nextID = num.toInt() + 1
                                    }
                                    var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                    songitem.songname = thisTitle
                                    songitem.songartist = thisArtist
                                    songitem.songurl = thisurls
                                    songitem.songimage = thisTitle
                                    EventBus.getDefault().post("update")
                                }
                            })
                        }
                        else{
                             realm = Realm.getDefaultInstance()
                           realm!!.executeTransaction(object : Realm.Transaction {

                                override fun execute(realm: Realm) {
                                    // increment index
                                    var num = realm.where(Songdetails::class.java).max("id")
                                    var nextID: Int
                                    if (num == null) {
                                        nextID = 1
                                    } else {
                                        nextID = num.toInt() + 1
                                    }
                                    var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                    songitem.songname = thisTitle
                                    songitem.songartist = thisArtist
                                    songitem.songurl = thisurls
                                    songitem.songimage = "custom"
                                    EventBus.getDefault().post("update")
                                }
                            })
                        }
                    }

                }
            }catch (ex:Exception)
            {

            }
        }
        realm = Realm.getDefaultInstance()
        val waviterator = FileUtils.iterateFiles(
                Environment.getExternalStorageDirectory(),
                FileFilterUtils.suffixFileFilter("wav"),
                TrueFileFilter.INSTANCE)
        while (waviterator.hasNext()) {
            try {
                val fileINeed = waviterator.next()
                val thisurls = fileINeed.canonicalPath
                val mmr = MediaMetadataRetriever()
                mmr.setDataSource(thisurls)
                var thisTitle = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE)
                var thisArtist = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST)
                if (thisTitle.isNullOrEmpty()) {
                    thisTitle = fileINeed.name
                }
                if (thisArtist.isNullOrEmpty()) {
                    thisArtist = "Unknown Artist"
                }
                val query = realm!!.where(Songdetails::class.java).equalTo("songname", thisTitle).findFirst()
                if (query == null) {
                    val retriever = MediaMetadataRetriever()
                    retriever.setDataSource(thisurls)
                    val art = retriever.embeddedPicture
                    if (art != null) {
                        var bitmap = BitmapFactory.decodeByteArray(art, 0, art.size)
                        ImageSaver(MainActivity.getInstance()!!)
                                .setFileName(thisTitle)
                                .setDirectoryName("images")
                                .save(bitmap)
                         realm = Realm.getDefaultInstance()
                       realm!!.executeTransaction(object : Realm.Transaction {

                            override fun execute(realm: Realm) {
                                // increment index
                                var num = realm.where(Songdetails::class.java).max("id")
                                var nextID: Int
                                if (num == null) {
                                    nextID = 1
                                } else {
                                    nextID = num.toInt() + 1
                                }
                                var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                songitem.songname = thisTitle
                                songitem.songartist = thisArtist
                                songitem.songurl = thisurls
                                songitem.songimage = thisTitle
                                EventBus.getDefault().post("update")
                            }
                        })
                    } else {
                         realm = Realm.getDefaultInstance()
                        realm!!.executeTransaction(object : Realm.Transaction {

                            override fun execute(realm: Realm) {
                                // increment index
                                var num = realm.where(Songdetails::class.java).max("id")
                                var nextID: Int
                                if (num == null) {
                                    nextID = 1
                                } else {
                                    nextID = num.toInt() + 1
                                }
                                var songitem = realm!!.createObject(Songdetails::class.java, nextID)
                                songitem.songname = thisTitle
                                songitem.songartist = thisArtist
                                songitem.songurl = thisurls
                                songitem.songimage = "custom"
                                EventBus.getDefault().post("update")
                            }
                        })
                    }

                }

            } catch (ex: Exception) {

            }
        }
        }
}
like image 849
ruchit patel Avatar asked Dec 28 '25 15:12

ruchit patel


1 Answers

You might be able to take advantage of Coil or Picasso to better cache the bitmaps for subsequent launches. The initial one is going to take some time regardless of the method used due to the a variety of variables (number of tracks, size of image tracks, etc.)

like image 88
Brandon McAnsh Avatar answered Dec 31 '25 17:12

Brandon McAnsh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!