Search code examples
androidkotlinexoplayer2.xvideo-player

Exoplayer2.x: Player.STATE_ENDED fires twice when a video ends ,how to implement exoplayer in android?


I'm using Exoplayer to play a video in a playlist. I want to auto play the next video when the current video end. To do this, I added an EventListener to my player. Here's a snippet:

private val videoPlayerListener = object: Player.EventListener {
    override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
        when(playbackState) {
            Player.STATE_IDLE -> showLoadingView()
            Player.STATE_READY -> hideLoadingView()
            Player.STATE_BUFFERING -> showVideoProgressWheel()
            Player.STATE_ENDED -> {
                Log.d(TAG, "fired")
                playNextVideo()
            }
        }
    }

    override fun onPlayerError(error: ExoPlaybackException?) {
        // handle error event
    }
}

The problem with this approach is that my logs show that Player.STATE_ENDED fires twice. The chain effect of this is that my playlist plays from

video 1 -> video 3 -> video 5 -> video 7...

instead of

video 1 -> video 2 -> video 3 -> video 4...

I did some research and I found this issue on Github. I checked my code and I realized I was actually calling a method that contains addListener(videoPlayerListener) in OnCreate(), OnStart(), OnPause(), OnResume() and OnStop(). To solve this problem, I added the following before the addListener line:

try {
    player.removeListener(videoPlayerListener)
    Log.d(TAG, "Listener temporarily deleted")
}
catch (e: Exception) {}

Kindly note that there is only one function in my code that contains addListener(...) and I put the removeListener() call directly before the addListener() line. Despite this, Player.STATE_ENDED still gets called twice every single time a video ends.

What do I do?


Solution

  • Use this code

    Take a variable like this globally

    var isVideoEnded=false
    

    then in your listener do this

    private val videoPlayerListener = object: Player.EventListener {
        override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
            when(playbackState) {
                Player.STATE_IDLE -> showLoadingView()
                Player.STATE_READY -> {
                        hideLoadingView()
                        isVideoEnded=false
                                    }
                Player.STATE_BUFFERING -> showVideoProgressWheel()
                Player.STATE_ENDED -> {
                       if(!isVideoEnded){
                          playNextVideo()
                          isVideoEnded=true
                      }
    
                    Log.d(TAG, "fired")
    
                }
            }
        }
    
        override fun onPlayerError(error: ExoPlaybackException?) {
            // handle error event
        }
    }