MediaPlayer, ProgressBar

Go To StackoverFlow.com

9

Is this the correct way to update a ProgressBar when playing Media? I figured there would be a callback in MediaPlayer, but I couldn't find it.

mediaPlayer.start();
final SeekBar progress = (SeekBar) dialog.findViewById(R.id.seekBar1);
progress.setMax(mediaPlayer.getDuration());
new CountDownTimer(mediaPlayer.getDuration(), 250) {
  public void onTick(long millisUntilFinished) {
    progress.setProgress(progress.getProgress() + 250);
  }
  public void onFinish() {}
}.start();

Best regards.

2012-04-03 19:56
by pouzzler


10

Take a look at android.widget.MediaController, it has a progress bar.

They use a handler that recursively calls itself if appropriate. You can set the delay to however often you want the progress bar updated.

Note that the controller can be shown or hidden as well as dragged by the user, and - of course - the video can stop. These are the reasons for the various checks (!mDragging && mShowing && mVideoView.isPlaying()) before another recursive call to update the bar.

protected Handler mHandler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        int pos;
        switch (msg.what)
        {
            // ...

            case SHOW_PROGRESS:
                pos = setProgress();
                if (!mDragging && mShowing && mVideoView.isPlaying())
                {
                    msg = obtainMessage(SHOW_PROGRESS);
                    sendMessageDelayed(msg, 1000 - (pos % 1000));
                }
                break;

             // ...
        }
    }
};

To start it off use:

mHandler.sendEmptyMessage(SHOW_PROGRESS);

It will stop by itself, but you should cancel the last pending request using:

mHandler.removeMessages(SHOW_PROGRESS);
2012-04-03 20:39
by Peter Ajtai
Thanks, precisely, what I was looking for - pouzzler 2012-04-03 20:43
@pouzzler - You're welcome! Looking at the MediaController class is great for giving you ideas on making a custom controller - Peter Ajtai 2012-04-03 21:16
Second link is gone because of a DMCA takedown: https://github.com/OESF/OHA-Android-4.0.1_r1. - astromme 2017-03-19 19:23


18

Personally, I start off a Thread that checks getCurrentPosition() every 200ms or so until the onCompletion() event gets fired off:

private class MediaObserver implements Runnable {
  private AtomicBoolean stop = new AtomicBoolean(false);

  public void stop() {
    stop.set(true);
  }

  @Override
  public void run() {
    while (!stop.get()) {
      progress.setProgress(mediaPlayer.getCurrentPosition());
      Thread.sleep(200);
    }
  }
}

private MediaObserver observer = null;

public void runMedia() {
  mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener{
    @Override
    public void onCompletion(MediaPlayer mPlayer) {
      observer.stop();
      progress.setProgress(mPlayer.getCurrentPosition());
    }
  });
  observer = new MediaObserver();
  mediaPlayer.start();
  new Thread(observer).start();
}
2012-04-03 20:02
by JRaymond
The timer doesn't block the UI so I suppose it's in another thread. So I suppose it's the same. I wish I was intelligent enough to figure these things out - pouzzler 2012-04-03 20:08
@pouzzler Countdown timer runs in another thread, the only difference is that it doesn't use the actual progress. I'll write up a threaded exampl - JRaymond 2012-04-03 20:19
ah no need, I get it. Thanks : - pouzzler 2012-04-03 20:27
@pouzzler too late... but you're welcome : - JRaymond 2012-04-03 20:32
Same problem as before, I used your suggestion... with CountDownTimer: progress.setProgress(mediaPlayer.getCurrentPosition()); - still no clue which is best ;) And off to bed for me and my philosophical questions - pouzzler 2012-04-03 20:36
Sorry I flagged the other answer, since it is more useful for everyone, even though I will stay with my non-ICS stuff for now - pouzzler 2012-04-03 20:43
Why did you use an atomic operation for the bool in your example - tobi.b 2013-02-26 18:01
@tobi.b In this instance it's probably not necessary, since only the observer thread is manipulating the stop variable and it's using pure assignment. In general though, using atomic types prevents thread collisions where multiple threads are trying to manipulate a variable at the same time, so it's a habi - JRaymond 2013-02-26 19:06
For the sake of accuracy, MediaPlayer.OnCompletionListener's method is named onCompletion(), not onComplete( - matdev 2015-11-03 14:53


2

The most efficient way is to use JRaymond's answer and EventBus

private class MediaObserver implements Runnable {
    private AtomicBoolean stop = new AtomicBoolean(false);
    public void stop() {
        stop.set(true);
    }

    @Override public void run() {
        while (!stop.get()) {
            try {
              if (player.isPlaying())
                 sendMsgToUI(player.getCurrentPosition(),
                             player.getDuration());
            } catch (Exception e){e.printStackTrace();}
            try { 
              Thread.sleep(100);
            } catch (InterruptedException e) { e.printStackTrace(); }
        }
    }
}

private MediaObserver observer = null;

public void runMedia() {
    observer = new MediaObserver();
    new Thread(observer).start();
}

//handles all the background threads things for you
private void sendMsgToUI(int position) {
    ChangingEvent event = new ChangingEvent(position);
    EventBus.getDefault().post(event);
}

ChangingEvent class would look something like that:

public class ChangingEvent {
  private int position;

  public ChangingEvent(int position) {
      this.position= position;
  }

  public int getPosition() {
      return position;
  }
}

and in your Activity or Fragment all you have to do is

class YouClass extends Activity {
  private EventBus eventBus = EventBus.getDefault();
}

@Override protected void onCreate(Bundle savedInstanceState) {
    //your code
    eventBus.register(this);
}
//eventbus that updates UI
public void onEventMainThread(ChangingEvent event) {
    //seekbar or any other ui element
    seekBar.setProgress(event.getPosition());
}
2015-07-13 09:16
by Fedor Tsyganov
I like this approach but I think you forgot to add loop/while that makes run() being executed more than just onc - M Penades 2015-07-20 15:32
Oh, yes, thanks for noticing that - I'll correct it now - Fedor Tsyganov 2015-07-21 01:11