【问题标题】:Smoothly increase progress bar while playing audio file播放音频文件时平滑增加进度条
【发布时间】:2014-03-18 10:27:41
【问题描述】:

我正在我的应用程序中播放不同大小的音频文件,并且在播放音频时进度条应该会顺利进行,但进度条会采用随机大小的步骤。

我正在使用以下代码:

 mp = new MediaPlayer(); 
 mp.setDataSource("audio file path");
 mp.prepare();
 mp.start();
 pb.setMax(mp.getDuration());
            new AsyncTask<Void, Integer, Void>() {
                @Override
                protected Void doInBackground(Void... params) {
                    while(mp.isPlaying())
                    {
                     publishProgress(mp.getCurrentPosition);
                    }
                    return null;
                }
                 protected void onProgressUpdate(Integer... progress) {
                     pb.setProgress(progress[0]);
                 }
                @Override
                protected void onPostExecute(Void result) {
                    super.onPostExecute(result);
                    mp.stop();
                    mp.release();
                }
            }.execute();

有什么办法可以平滑地增加进度条吗?

【问题讨论】:

  • 平滑增加进度条的关键是将其值增加1直到播放音频,并且不依赖于MediaPlayer.getCurrentPosition()方法。

标签: android android-progressbar


【解决方案1】:

请检查此步骤

第 1 步: 使用MediaPlayer.getDuration()获取音频时长

第 2 步: 设置 ProgressBar 进度最大值。从第 1 步开始的价值到价值

第 3 步:

MediaPlayer.getCurrentPosition() 定期更新进度条,同时使用 Handler 播放媒体。

所以代码会是这样的

MediaPlayer mMediaPlayer = new MediaPlayer();
    final SeekBar mSeelBar = new SeekBar(this);
    final int duration = mMediaPlayer.getDuration();
    final int amountToUpdate = duration / 100;
    Timer mTimer = new Timer();
    mTimer.schedule(new TimerTask() {

        @Override
        public void run() {
            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    if (!(amountToUpdate * mSeelBar.getProgress() >= duration)) {
                        int p = mSeelBar.getProgress();
                        p += 1;
                        mSeelBar.setProgress(p);
                    }
                }
            });
        };
    }, amountToUpdate);

我关注了this 链接获取代码

【讨论】:

  • 是的......这就是我现在正在做的......但是进度条正在逐步增加而不是顺利......
  • 检查编辑过的答案 1 在我的实施过程中对我有帮助
  • 更好的实现:ScheduledExecutorService service = Executors.newScheduledThreadPool(1); service.scheduleWithFixedDelay(new Runnable() { @Override public void run() { progressBar.setProgress(player.getCurrentPosition()); } }, 1, 1, TimeUnit.MICROSECONDS);
【解决方案2】:

将进度条的最大大小设置为一个高范围...如果您将进度条设置为在 1 到最大 100 之间递增,那么不要使用 100 作为最大使用 1000 ..这是我的建议.因为我发现你的代码工作正常。

【讨论】:

    【解决方案3】:

    这是我创建的媒体播放器,请查看。

      public TextView songName,startTimeField,endTimeField;
       private MediaPlayer mediaPlayer;
       private double startTime = 0;
       private double finalTime = 0;
       private Handler myHandler = new Handler();;
       private int forwardTime = 5000; 
       private int backwardTime = 5000;
       private SeekBar seekbar;
       private ImageButton playButton,pauseButton;
       public static int oneTimeOnly = 0;
       @Override
       protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          songName = (TextView)findViewById(R.id.textView4);
          startTimeField =(TextView)findViewById(R.id.textView1);
          endTimeField =(TextView)findViewById(R.id.textView2);
          seekbar = (SeekBar)findViewById(R.id.seekBar1);
          playButton = (ImageButton)findViewById(R.id.imageButton1);
          pauseButton = (ImageButton)findViewById(R.id.imageButton2);
          songName.setText("song.mp3");
          mediaPlayer = MediaPlayer.create(this, R.raw.song);
          seekbar.setClickable(false);
          pauseButton.setEnabled(false);
    
       }
    
       @TargetApi(Build.VERSION_CODES.GINGERBREAD) public void play(View view){
       Toast.makeText(getApplicationContext(), "Playing sound", 
       Toast.LENGTH_SHORT).show();
          mediaPlayer.start();
          finalTime = mediaPlayer.getDuration();
          startTime = mediaPlayer.getCurrentPosition();
          if(oneTimeOnly == 0){
             seekbar.setMax((int) finalTime);
             oneTimeOnly = 1;
          } 
    
          endTimeField.setText(String.format("%d min, %d sec", 
             TimeUnit.MILLISECONDS.toMinutes((long) finalTime),
             TimeUnit.MILLISECONDS.toSeconds((long) finalTime) - 
             TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
             toMinutes((long) finalTime)))
          );
          startTimeField.setText(String.format("%d min, %d sec", 
             TimeUnit.MILLISECONDS.toMinutes((long) startTime),
             TimeUnit.MILLISECONDS.toSeconds((long) startTime) - 
             TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
             toMinutes((long) startTime)))
          );
          seekbar.setProgress((int)startTime);
          myHandler.postDelayed(UpdateSongTime,100);
          pauseButton.setEnabled(true);
          playButton.setEnabled(false);
       }
    
       private Runnable UpdateSongTime = new Runnable() {
          @TargetApi(Build.VERSION_CODES.GINGERBREAD) public void run() {
             startTime = mediaPlayer.getCurrentPosition();
             startTimeField.setText(String.format("%d min, %d sec", 
                TimeUnit.MILLISECONDS.toMinutes((long) startTime),
                TimeUnit.MILLISECONDS.toSeconds((long) startTime) - 
                TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
                toMinutes((long) startTime)))
             );
             seekbar.setProgress((int)startTime);
             myHandler.postDelayed(this, 100);
          }
       };
       public void pause(View view){
          Toast.makeText(getApplicationContext(), "Pausing sound", 
          Toast.LENGTH_SHORT).show();
    
          mediaPlayer.pause();
          pauseButton.setEnabled(false);
          playButton.setEnabled(true);
       }    
       public void forward(View view){
          int temp = (int)startTime;
          if((temp+forwardTime)<=finalTime){
             startTime = startTime + forwardTime;
             mediaPlayer.seekTo((int) startTime);
          }
          else{
             Toast.makeText(getApplicationContext(), 
             "Cannot jump forward 5 seconds", 
             Toast.LENGTH_SHORT).show();
          }
    
       }
       public void rewind(View view){
          int temp = (int)startTime;
          if((temp-backwardTime)>0){
             startTime = startTime - backwardTime;
             mediaPlayer.seekTo((int) startTime);
          }
          else{
             Toast.makeText(getApplicationContext(), 
             "Cannot jump backward 5 seconds",
             Toast.LENGTH_SHORT).show();
          }
    
       }
    

    【讨论】:

    • 正如 rashmi 所说,这是使用进度条的方式。
    【解决方案4】:

    您可以使用以下逻辑使其更流畅。

    1. 将进度条的当前值和最新的进度值存储为成员。

    2. 在调用onProgressUpdate 方法时更新后者。

    3. 在定时器中,把这个逻辑周期性地执行。

      if (currentValue < latestProgress) {
          currentValue++;
          pb.setProgress(currentValue);
      }
      

      请注意,它会慢慢向目标值前进。

    希望这会有所帮助。

    【讨论】:

    • 通过在 LogCat 中打印 mp.getCurrentPosition 的值,我发现这些值不是线性的.. 在某些时候它会保持恒定一段时间然后随机跳跃.. 我已经尝试过平滑进度通过添加到当前进度条值直到 getCurrentPosition() 返回不同的值..但它没有按预期工作..
    • 您是否使用计时器将时间间隔放入当前值的连续相加中?
    • 以 50 毫秒或 200 毫秒等小时间间隔将每个更新分开会给您带来平滑效果。定时器很容易实现,你可以看看这里的例子。 stackoverflow.com/questions/4597690/android-timer-how
    【解决方案5】:

    虽然建议使用 Handler 在播放时跟踪音频的当前位置是唯一正确的方法。但是,MediaPlayer.getCurrentPosition() 对于短音频(比如说,大约 1 秒)不是超级精确;为了让生活更轻松,我编写了一个 Utils 类来支持这个目的,使用 CountDownTimer

    链接演示: https://github.com/mttdat/utils

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-07
      • 1970-01-01
      相关资源
      最近更新 更多