Skip to content Skip to sidebar Skip to footer

Android Exoplayer Onprogresschanged

How can I monitor progress changes on ExoPlayer? I tried to implement a hidden MediaController and overriding setOnSeekBarChangeListener methods, but for now without success. I'm w

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"