Вопрос по android, seekbar – MediaPlayer, ProgressBar

9

Это правильный способ обновления ProgressBar при воспроизведении Media? Я подумал, что в MediaPlayer будет обратный вызов, но я не смог его найти.

<code>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();
</code>

С наилучшими пожеланиями.

Ваш Ответ

3   ответа
10

Взгляни наandroid.widget.MediaController, у него есть индикатор выполнения.

Они используют обработчик, который при необходимости рекурсивно вызывает себя. Вы можете установить задержку на то, как часто вы хотите обновить индикатор выполнения.

Обратите внимание, что пользователь может показывать или скрывать контроллер, а также перетаскивать его, и, конечно же, видео может останавливаться. Это причины для различных проверок (!mDragging && mShowing && mVideoView.isPlaying()) перед очередным рекурсивным вызовом для обновления панели.

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;

             // ...
        }
    }
};

Для начала используйте:

mHandler.sendEmptyMessage(SHOW_PROGRESS);

Он остановится сам по себе, но вы должны отменить последний ожидающий запрос, используя:

mHandler.removeMessages(SHOW_PROGRESS);
Вторая ссылка исчезла из-за удаления DMCA:github.com/OESF/OHA-Android-4.0.1_r1.0
Спасибо, именно то, что я искал. pouzzler
@pouzzler - Добро пожаловать! Рассмотрение класса MediaController отлично подходит для того, чтобы дать вам идеи по созданию собственного контроллера.
2

Наиболее эффективный способ состоит в том, чтобы использовать ответ JRaymond и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 будет выглядеть примерно так:

public class ChangingEvent {
  private int position;

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

  public int getPosition() {
      return position;
  }
}

и в вашей деятельности или фрагменте все, что вам нужно сделать, это

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());
}
Мне нравится этот подход, но я думаю, что вы забыли добавить loop /, в то время как run () выполняется не раз
О, да, спасибо, что заметили это - я исправлю это сейчас.
18

Лично я начинаю с темы, которая проверяетgetCurrentPosition() каждые 200 мс или около того, покаonCompletion() событие запускается:

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();
}
ну не надо, я понял. Спасибо :) pouzzler
@pouzzler слишком поздно ... но добро пожаловать :)
@pouzzler Таймер обратного отсчета работает в другом потоке, единственное отличие состоит в том, что он не использует фактический прогресс. Я напишу пример с резьбой
Та же проблема, что и раньше, я использовал ваше предложение ... с CountDownTimer: progress.setProgress (mediaPlayer.getCurrentPosition ()); - до сих пор нет понятия, что лучше;) И спать для меня и мои философские вопросы. pouzzler
Таймер не блокирует пользовательский интерфейс, поэтому я предполагаю, что он находится в другом потоке. Поэтому я полагаю, что это то же самое. Я хотел бы быть достаточно умным, чтобы понять эти вещи. pouzzler

Похожие вопросы