This is the final of the 6 post series where we built a music player app from scratch. A quick recap of what we have done so far. We learned the basics of playing music using Media Player on Android. The Media Player is implemented in a Service so we can play music in the background. It also includes a notification, lock screen controls, and a foreground app UI. Finally, we learned how to create a mini toolbar that we can embed on all activities.
Now that we have everything set up, adding playlist support is going to be pretty simple. Let’s start by creating a Realm model for saving our playlists locally.
@Parcel(value = Parcel.Serialization.BEAN, analyze = arrayOf(Playlist::class))
open class Playlist : RealmObject() {
@Required
@PrimaryKey
open var objectID: String = UUID.randomUUID().toString()
@Required
open var title: String = ""
@Required
open var createdAt: Date = Date()
@Required
open var lastUpdatedAt: Date = Date()
open var files: RealmList<AlbumFile>? = null
@ParcelPropertyConverter(AlbumFile.AlbumFileListParcelConverter::class) set
}
Now, we need to allow users to add songs to the playlist. I will leave the UI implementation as an exercise for the reader. Let’s discuss the core logic of loading a list of songs the user can select from and actually adding these songs to the playlist.
val albums = realm?.where(Album::class.java)?.findAll() // Load all albums
// …
// Load all files in an album
fun getFilesForType(type: AlbumFile.AlbumContentType): List<AlbumFile> {
val files = this.files.let { it } ?: return ArrayList<AlbumFile>()
val typeFiles = ArrayList<AlbumFile>(files.size)
for (file in files) {
if (file.file != null && file.type == type) {
typeFiles.add(file)
}
}
return typeFiles
}
After the user has finished selecting all files to add to the playlist, we need to signal a result to the parent activity using setResult
.
data.putParcelableArrayListExtra(PlaylistEditActivity.EXTRA_FILES, ArrayList(mFiles.map { Parcels.wrap(AlbumFile::class.java, it) }))
setResult(RESULT_OK, data)
finish()
Finally, in the parent activity, handle the result in onActivityResult
and add the songs to the playlist.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode != Activity.RESULT_OK || data == null) {
return
}
when (requestCode) {
REQUEST_CODE_SONGS_PICKER -> {
if (mPlaylist?.files == null) {
mPlaylist?.files = RealmList()
} else {
mPlaylist?.files?.clear()
}
data.getParcelableArrayListExtra<Parcelable>(EXTRA_FILES).map { Parcels.unwrap<AlbumFile>(it) }.forEach { mPlaylist?.files?.add(it) }
// UI Update Adapter and clear any errors
}
}
}
That’ all you need to start saving your playlists in a Realm database. Once this is done, it is just basic UI to load your playlists and play the songs. Refer to Creating a Music Player UI on Android to check out how to play the songs saved in your playlist.
I have had far too many requests for the source code and the reason I am not putting it up is that as all source code, it requires constant maintenance and I don’t have enough time to manage this. Secondly, I have seen far too many people picking up the source code and putting it as is into the app which floods the already sub-par app market with low-quality apps aimed only for ad revenue. There is already a good, well-maintained music player source code maintained by Google if someone really needs it. Otherwise, if you need professional help, please feel free to shoot me an email.