媒体播放器、进度条

Posted

技术标签:

【中文标题】媒体播放器、进度条【英文标题】:MediaPlayer, ProgressBar 【发布时间】:2012-04-03 19:56:37 【问题描述】:

这是在播放媒体时更新 ProgressBar 的正确方法吗?我想在 MediaPlayer 中会有一个回调,但我找不到它。

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

最好的问候。

【问题讨论】:

【参考方案1】:

就个人而言,我开始一个线程,每 200 毫秒左右检查一次 getCurrentPosition(),直到 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 倒计时计时器在另一个线程中运行,唯一的区别是它不使用实际进度。我会写一个线程示例 啊不用了,我明白了。谢谢:) 和以前一样的问题,我用了你的建议...... CountDownTimer:progress.setProgress(mediaPlayer.getCurrentPosition()); - 仍然不知道哪个是最好的 ;) 为我和我的哲学问题上床睡觉。 抱歉,我标记了另一个答案,因为它对每个人都更有用,尽管我现在会继续使用我的非 ICS 内容。【参考方案2】:

看看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);

【讨论】:

谢谢,正是我要找的东西。 @pouzzler - 不客气!查看 MediaController 类非常适合为您提供有关制作自定义控制器的想法。 第二个链接因 DMCA 删除而消失:github.com/OESF/OHA-android-4.0.1_r1.0【参考方案3】:

最有效的方法是使用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;
  

在你的 Activity 或 Fragment 中你所要做的就是

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

【讨论】:

我喜欢这种方法,但我认为您忘记添加循环/while,这会使 run() 被多次执行 哦,是的,感谢您注意到这一点 - 我现在会更正它。

以上是关于媒体播放器、进度条的主要内容,如果未能解决你的问题,请参考以下文章

VS2008中Slider控件制作播放器的进度条,如何在视频播放时改变滑块位置

HTML5 视频播放器进度条准确提示

具有“双”进度条的视频播放器(视频加载/视频播放进度)

Mp3播放器进度条

第 11 章 进度条媒体对象和 Well 组件

用WPF如何制作QQ播放器那个音乐进度条(如下图:)