Android Exoplayer Onprogresschanged
Solution 1:
I know this question is very old. But, I landed on this while implementing ExoPlayer
. This is to help the others who do the same later on:)
So, I have followed the following methods to track progress of the playback. This is the way it is done in the ExoPlayer
Google Docs. It works as needed.
Checkout PlayerControlView.java
in Google ExoPlayer repository
updateProgressBar()
is the function to update the SeekBar
progress:
privatevoidupdateProgressBar() {
longduration= player == null ? 0 : player.getDuration();
longposition= player == null ? 0 : player.getCurrentPosition();
if (!dragging) {
mSeekBar.setProgress(progressBarValue(position));
}
longbufferedPosition= player == null ? 0 : player.getBufferedPosition();
mSeekBar.setSecondaryProgress(progressBarValue(bufferedPosition));
// Remove scheduled updates.
handler.removeCallbacks(updateProgressAction);
// Schedule an update if necessary.intplaybackState= player == null ? Player.STATE_IDLE : player.getPlaybackState();
if (playbackState != Player.STATE_IDLE && playbackState != Player.STATE_ENDED) {
long delayMs;
if (player.getPlayWhenReady() && playbackState == Player.STATE_READY) {
delayMs = 1000 - (position % 1000);
if (delayMs < 200) {
delayMs += 1000;
}
} else {
delayMs = 1000;
}
handler.postDelayed(updateProgressAction, delayMs);
}
}
privatefinalRunnableupdateProgressAction=newRunnable() {
@Overridepublicvoidrun() {
updateProgressBar();
}
};
We call updateProgressBar()
within updateProgressAction
repeatedly until the playback stops.
The function is called the first time whenever there is a state change. We use removeCallbacks(Runnable runnable)
so that there is always one updateProgressAction
to care about.
@OverridepublicvoidonPlayerStateChanged(boolean playWhenReady, int playbackState) {
updateProgressBar();
}
Hope this helps!
Solution 2:
Just try this, its working for me :
handler = new Handler();
runnable = new Runnable() {
@Override
publicvoidrun() {
progressbar.setProgress((int) ((exoPlayer.getCurrentPosition()*100)/exoPlayer.getDuration()));
handler.postDelayed(runnable, 1000);
}
};
handler.postDelayed(runnable, 0);
Here,
getCurrentPosition()
: return The current playback position in milliseconds.getDuration()
: The duration of the track in millisecond.
Solution 3:
I've found a pretty elegant solution using RxJava. This involves a polling pattern as well, but we make sure to use an interval to poll every 1 second.
public Observable<Long> playbackProgressObservable =
Observable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
The logic here is we create an Observable that will emit a sequential number every second. We then use the map
operator to transform the number into the current playback position.
public Observable<Long> playbackProgressObservable =
Observable.interval(1, TimeUnit.SECONDS)
.map( { exoPlayer.getCurrentPosition() } );
To finally hooked this together, just call subscribe, ad the progress updates will be emitted every second:
playbackProgressObservable.subscribe( { progress ->// Update logic here } )
Note: Observable.interval
runs on a default Scheduler
of Schedulers.computation()
. Therefore, you'll probably need to add an observeOn()
operator to make sure the results are sent to the right thread.
playbackProgressObservable
.observeOn(AndroidSchedulers.mainThread())
.subscribe(progress -> {}) // Update logic here
The above statement will give you a Disposable which must be disposed when you are done observing. You can do something like this ->
private var playbackDisposable: Disposable? = null
playbackDisposable = playbackProgressObservable
.observeOn(AndroidSchedulers.mainThead())
.subscribe(progress -> {}) // Update logic here
then to dispose the resource ->
playbackDisposable?.dispose()
Solution 4:
Not sure it is the best way, but I achieved this by overloading the TrackRenderer
.
I'm using videoPlayer.getBufferedPercentage()
, but you might be able to compute the percentage yourself as well, by just using TrackRenderer
's getBufferedPositionUs()
and getDurationUs()
publicinterfaceProgressListener {
publicvoidonProgressChange(long progress);
}
publicclassCustomVideoRendererextendsMediaCodecVideoTrackRenderer {
longprogress=0;
privatefinal CopyOnWriteArraySet<ProgressListener> progressListeners = newCopyOnWriteArraySet();
// [...]// Skipped constructors// [...]publicvoiddoSomeWork(long positionUs, long elapsedRealtimeUs)throws ExoPlaybackException {
super.doSomeWork(positionUs, elapsedRealtimeUs);
longtmpProgress= videoPlayer.getBufferedPercentage();
if (tmpProgress != this.progress) {
this.progress = tmpProgress;
for (ProgressListener progressListener : this.progressListeners) {
progressListener.onProgressChange(progress);
}
}
}
publicvoidaddProgressListener(ProgressListener listener) {
this.progressListeners.add(listener);
}
}
Solution 5:
To make it clear,there isn't a build in EventListener for the progress event, but you can call Handler.postDelayed inside you updateProgress() function to get the current progress
privatevoidupdateProgress(){
//get current progress longposition= player == null ? 0 : player.getCurrentPosition();
//updateProgress() will be called repeatedly, you can check //player state to end it
handler.postDelayed(updateProgressAction,1000)
}
privatefinalRunnableupdateProgressAction=newRunnable() {
@Overridepublicvoidrun() {
updateProgress();
}
};
for more details, see the source of PlaybackControlView.java inside Exoplayer
Post a Comment for "Android Exoplayer Onprogresschanged"