I'm curious how to play audio files synchronously (one at a time) in Kotlin, so there's no overlap during playback.
I do have an (updated) temporary solution listed below:
My current method works as follows:
- Create an audio queue for all pending sounds.
- Play each subsequent one when the onCompletionListener fires.
But I'm curious if there's a more optimal (read: less verbose) way to do this. Or — if there isn't — am I overlooking any flaws in my current method?
import android.content.Context
import android.media.MediaPlayer
//Note: Only Instantiate Once Per Activity
class ClassAudio {
//Create A MutableList Comprising Each Sound We Currently Have In The Queue
private var mvAudioBuffer: MutableList<MediaPlayer> = arrayListOf()
//Call This Function To Add Audio To The Queue And Play Them Sequentially
fun mmPlayAudioSynchronously(mvContext : Context, mvAudio: Int) {
mvAudioBuffer.also{it.add(MediaPlayer.create(mvContext, mvAudio))}.also{if (mvAudioBuffer.size == 1) mmPlayFirst()}
}
//Play The First Sound In The Queue If It Exists And It's Not Playing, "Remove" It From The Queue "onCompletion", Then Repeat The Process With The NEW First Sound
private fun mmPlayFirst() {
mvAudioBuffer.getOrNull(0)?.let{ if (it.isPlaying) null else it}?.also{it.start()}?.setOnCompletionListener{mvAudioBuffer.removeFirstOrNull()?.release().also{mmPlayFirst()}}
}
//Pause All Pending Audio, Release Alotted Resources, And "Clear" It From The Queue
fun mmStopAllPendingAudio() {
mvAudioBuffer.also{for (mvSound in it) {mvSound.also{it.pause()}.release()}}.clear()
}
}
Then to play the sounds sequentially:
val mvClassAudio : ClassAudio = ClassAudio()
mvClassAudio.mmPlayAudioSynchronously(this, R.raw.audio_file_1)
mvClassAudio.mmPlayAudioSynchronously(this, R.raw.audio_file_2)
mvClassAudio.mmPlayAudioSynchronously(this, R.raw.audio_file_3)
So again, this seems to work, but a less verbose or otherwise "best practices" approach is what I'm looking for.