Reputation: 703
I am trying to play videos in the form of a playlist one after another. I am using android ExoPlayer to play my files, but there are no listeners in ExoPlayer to listen to an end of a media file.
Is there a way to listen to the end of media files using ExoPlayer?
Upvotes: 57
Views: 49800
Reputation: 57
Use this for latest updates:
addListener(object : Player.Listener{
override fun onPlaybackStateChanged(playbackState: Int) {
super.onPlaybackStateChanged(playbackState)
if (playbackState == Player.STATE_ENDED){
//do something
}
}
})
Upvotes: 0
Reputation: 40878
Is there a way to listen to the end of media file using exoplayer.
The new Media3 ExoPlayer API provides onMediaItemTransition()
callback for the transition between media items:
Whenever the player changes to a new media item in the playlist onMediaItemTransition(MediaItem mediaItem, @MediaItemTransitionReason int reason) is called on registered Player.Listener objects. The reason indicates whether this was an automatic transition, a seek (for example after calling player.next()), a repetition of the same item, or caused by a playlist change (for example, if the currently playing item is removed).
Demo use:
val mediaTransitionListener = object : Player.Listener {
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
super.onMediaItemTransition(mediaItem, reason)
// Media Transition
}
}
// register the listener
exoPlayer.addListener(mediaTransitionListener)
And don't forget to remove the listener when you cleanup things to avoid memory leaks:
exoPlayer.removeListener(mediaTransitionListener)
Upvotes: 0
Reputation: 111
Use this
exoPlayer.addListener(new Player.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == Player.STATE_ENDED) {
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
}
@Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
}
@Override
public void onPositionDiscontinuity(int reason) {
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
@Override
public void onSeekProcessed() {
}
});
Upvotes: 0
Reputation: 2465
Google has deprecate ExoPlayer.STATE_ENDED
and has replaced with Player.STATE_ENDED
.
Since this post has been a while, I will write a Kotlin
version of the listener down below.
this.simpleExoPlayer?.addListener(object : Player.DefaultEventListener() {
override fun onPlayerStateChanged(playWhenReady: Boolean,playbackState: Int) {
when (playbackState) {
Player.STATE_IDLE -> {}
Player.STATE_BUFFERING -> {}
Player.STATE_READY -> {}
Player.STATE_ENDED -> {}
}
}
})
UPDATE: 05-2020
Since DefaultEventListener
and onPlayerStateChanged()
are deprecated.
player.addListener(object : Player.EventListener {
override fun onPlaybackStateChanged(state: Int) {
if (state == Player.STATE_ENDED) {
// your code
}
}
})
Upvotes: 37
Reputation: 175
Since DefaultEventListener
and onPlayerStateChanged()
are deprecated.
Use Player.EventListener
and onPlaybackStateChanged()
Kotlin code:
player!!.addListener(object : Player.EventListener {
override fun onPlaybackStateChanged(state: Int) {
if (state == Player.STATE_ENDED) {
// your code here
}
}
})
Upvotes: 1
Reputation: 823
For non-concatenated MediaSource (representing whatever individual piece of media you want to play), you'll receive STATE_ENDED when the piece of media has finished playing.
For a ConcatenatingMediaSource it occurs when the entire concatenation has finished playing (i.e. you've played up to the end of the final item in the concatenation). So, STATE_ENDED occurs when the entire MediaSource has finished playing.
For a ConcatenatingMediaSource, the best callback to detect end of current media and start of next media playback is "onPositionDiscontinuity" You should use onPositionDiscontinuity() to figure out when transitions occur. Please note, onPositionDiscontinuity is invoked for some other cases too, but you can call getCurrentWindowIndex() and compare it to what window you think you're in to determine whether a transition has occurred. You can do something like below:
public void onPositionDiscontinuity() {
int newIndex = player.getCurrentWindowIndex();
if (newIndex != currentIndex) {
// The index has changed ==> last media has ended and next media playback is started.
currentIndex = newIndex;
}
}
Please note: onPositionDiscontinuity() is not gets called for the 1st item in the playlist unless we explicitly call player.seekTo(position,0). So to handle anything you are doing for all media playback in the playlist you have to handle separately for the 1st item in the playlist.
Upvotes: 4
Reputation: 426
Google has deprecate ExoPlayer.STATE_ENDED. Use Player.STATE_ENDED instead. See the code below.
player.addListener(new Player.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playWhenReady && playbackState == Player.STATE_READY) {
// Active playback.
} else if (playbackState == Player.STATE_ENDED) {
//The player finished playing all media
//Add your code here
} else if (playWhenReady) {
// Not playing because playback ended, the player is buffering, stopped or
// failed. Check playbackState and player.getPlaybackError for details.
} else {
// Paused by app.
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
}
@Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
}
@Override
public void onPositionDiscontinuity(int reason) {
//THIS METHOD GETS CALLED FOR EVERY NEW SOURCE THAT IS PLAYED
// int latestWindowIndex = player.getCurrentWindowIndex();
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
@Override
public void onSeekProcessed() {
}
});
You can check ExoPlayer Developer page for more information.
Upvotes: 4
Reputation: 466
I was using playlist with exoplayer and I wanted to stop the media after it was complete.
For me the Player.STATE_ENDED was being called when the playlist ended for me inside
So to fulfill my use case I first set this in exoplayer
simpleExoPlayer.setRepeatMode(Player.REPEAT_MODE_ONE);
So instead of using EventListener, I had used the AnalyticsListener which gives the onPositionDiscontinuity to override with eventTime parameter and just add a simple code to know whether the media has restarted.
@Override
public void onPositionDiscontinuity(EventTime eventTime, int reason) {
if (eventTime.currentPlaybackPositionMs / 1000 < 1) {
exoPlayer.setPlayWhenReady(false);
tvReplay.setVisibility(View.VISIBLE);
}
}
Hope this helps your usecase
Upvotes: 1
Reputation: 15336
Exoplayer offer advance implementation which media player do not.
in Advance example of Exoplayer by Android, in FullPlayerActivity.java they have implemented onStateChanged, which offers STATE_ENDED
You can download example from the right hand section of this page under term RELATED SAMPLES
Upvotes: 46
Reputation: 500
You have to implement the interface Player.EventLister and add to your exoPlayer.
Just write your code on the method onPlayerStateChanged. See the code.
exoPlayer.addListener( new Player.EventListener() {
@Override
public void onTimelineChanged(Timeline timeline, @Nullable Object manifest, int reason) {
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
}
@Override
public void onLoadingChanged(boolean isLoading) {
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch(playbackState) {
case Player.STATE_BUFFERING:
break;
case Player.STATE_ENDED:
//Here you do what you want
break;
case Player.STATE_IDLE:
break;
case Player.STATE_READY:
break;
default:
break;
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
}
@Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
}
@Override
public void onPositionDiscontinuity(int reason) {
}
@Override
public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
}
@Override
public void onSeekProcessed() {
}
});
Upvotes: 11
Reputation: 1695
ExoPlayer.STATE_ENDED is depreciated. Use Player.STATE_ENDED instead. Example:
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if(playbackState == Player.STATE_ENDED){
// your brain put here
}
}
Upvotes: 2
Reputation: 1106
You can do this:
playerExo.addListener(new ExoPlayer.Listener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
switch(playbackState) {
case ExoPlayer.STATE_BUFFERING:
break;
case ExoPlayer.STATE_ENDED:
//do what you want
break;
case ExoPlayer.STATE_IDLE:
break;
case ExoPlayer.STATE_PREPARING:
break;
case ExoPlayer.STATE_READY:
break;
default:
break;
}
}
@Override
public void onPlayWhenReadyCommitted() {
}
@Override
public void onPlayerError(ExoPlaybackException error) {
}
});
playerExo.seekTo(0);
playerExo.setPlayWhenReady(true);
But @Murtaza Khursheed Hussain answer is right! Have a nice code day! Let me know if you need something else!
Upvotes: 14
Reputation: 5460
I know this is old, but just to expand on the accepted answer:
exoPlayer.addListener(this);
.....
@Override
public void onPlayerStateChanged(boolean playWhenReady, int state) {
if (state == ExoPlayer.STATE_ENDED){
//player back ended
}
}
Upvotes: 66