I have the following for loop.
for (song in songArray){
playSong(song)
}
and playSong as below:
fun playSong(song){
mediaPlayer.create(context, R.raw.song)
mediaPlayer.start
mediaPlayer?.setOnCompletionListener {
mediaPlayer!!.release()
mediaPlayer = null
}
}
The for loop does not wait for the entire playSong function to complete, and just immediately starts the next song. I want the the listener to be heard and the song to complete before iterating to the next song. If you could give me some guidance on this, I would appreciate it.
CodePudding user response:
Instead of using for loop play songs from array when the previous one finishes
fun playSongArray(songArray: IntArray) {
var i = 0
mediaPlayer.create(context, R.raw.songArray[0])
mediaPlayer.start
mediaPlayer?.setOnCompletionListener {
if (i < songArray.size) {
mediaPlayer.create(context, R.raw.songArray[1])
mediaPlayer.start
i
} else {
mediaPlayer!!.release()
mediaPlayer = null
}
}
}
CodePudding user response:
Play the next song when the current one completed..
var currentSongIndex = 0;
var nextSong = songArray.elementAt(currentSongIndex)
mediaPlayer.create(context, nextSong)
mediaPlayer.start()
mediaPlayer?.setOnCompletionListener {
currentSongIndex
if (currentSongIndex >= songArray.length){
mediaPlayer!!.release()
mediaPlayer = null
return
}
var nextSong = songArray.elementAt(playlistPos)
mediaPlayer.create(context, nextSong)
mediaPlayer.start()
}
}
CodePudding user response:
Here's how it could be done with coroutines. First, you need to create a suspend function version of playing media and waiting for it to finish. Since a completion listener is not a one-shot callback, I think it is more appropriate to use callbackFlow
instead of suspendCoroutine
.
suspend fun MediaPlayer.startAndAwait() {
callbackFlow {
setOnCompletionListener {
trySendBlocking(Unit)
}
awaitClose { setOnCompletionListener(null) }
}.first()
start()
}
Then you can use this function in a coroutine, so you can loop sequentially:
suspend fun playSong(song: Int){
MediaPlayer.create(context, song).apply {
mediaPlayer = this // so you can cancel playback from elsewhere
startAndAwait()
release()
mediaPlayer = null
}
}
//In a coroutine:
for (song in songArray){
playSong(song)
}