18

我正在开发一个带有录音机和播放器的应用程序。我正在使用 mediaplayer 播放录制的 .wav 文件,同时我想更新到搜索栏。一切正常但我的问题是媒体播放器对搜索栏的进度更新并不顺利,如果我们正在播放一个小文件,搜索栏的拇指会在几秒钟内或之间跳跃。

任何人都可以帮助我解决问题,以使其顺利寻求搜索栏的进展。我的代码如下所示。我被困在这里。

    mediaPlayerIntiate();
    mediaPlayerSetSource();
    mMediaPlayer.start();
    task = new TimerTask() {
                @Override
                public void run() {
                    Graphbar.post(new Runnable() {
                        @Override
                        public void run() {

                            if (mMediaPlayer != null) {

                                if (playButtonState == MediaMode.PLAY) {
                                    if (mMediaPlayer.isPlaying()) {
                                        Graphbar.setProgress(mMediaPlayer
                                                .getCurrentPosition());
                                        mediaPlayerUpdateTimer(mMediaPlayer
                                                .getCurrentPosition());
                                        enableRewindandForward();
                                    }
                                }

                            }

                        }
                    });
                }
            };
            timer = new Timer();
            timer.schedule(task, 0, 8);
4

6 回答 6

21

mMediaPlayer.getCurrentPosition()以毫秒为单位返回当前时间,您将其更新为最大容量为 100 的 Seekbar。使用文件长度和 100 制作一个公式。试试这个函数

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

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

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

当媒体播放器开始播放时,应该调用这个过程。里面

    mediaPlayer.setOnPreparedListener(new OnPreparedListener(){

        @Override
        public void onPrepared(MediaPlayer mp) {
        **// call here**
        }
    });

更新

在几秒钟内更新 125 次不是你应该做的。请增加更新 SeekBar 的间隔。我在阅读 NullPointer 的评论后添加了这个

于 2013-07-30T09:20:36.403 回答
7

seekbar.setProgress() 只接受 int。因此,我们大多数人倾向于将经过的百分比传递给这种方法。但是,如果您需要更平滑的进程,则可以使用以毫秒为单位的持续时间作为 MAX。然后我们每毫秒更新搜索栏的进度。下面是一个示例,我每 15 毫秒更新一次,因为几乎每部 Android 手机都具有 60 fps(每秒帧数)的刷新率。

    try{
        mediaPlayer.start();
        seekbar.setProgress(0);
        seekbar.setMax(mediaPlayer.getDuration());

        // Updating progress bar
        seekHandler.postDelayed(updateSeekBar, 15);
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    }

/**
 * Background Runnable thread
 * */
private Runnable updateSeekBar = new Runnable() {
    public void run() {
        long totalDuration = mediaPlayer.getDuration();
        long currentDuration = mediaPlayer.getCurrentPosition();

        // Displaying Total Duration time
        remaining.setText(""+ milliSecondsToTimer(totalDuration-currentDuration));
        // Displaying time completed playing
        elapsed.setText(""+ milliSecondsToTimer(currentDuration));

        // Updating progress bar
        seekbar.setProgress((int)currentDuration);

        // Call this thread again after 15 milliseconds => ~ 1000/60fps
        seekHandler.postDelayed(this, 15);
    }
};

/**
 * Function to convert milliseconds time to
 * Timer Format
 * Hours:Minutes:Seconds
 * */
public String milliSecondsToTimer(long milliseconds){
    String finalTimerString = "";
    String secondsString = "";

    // Convert total duration into time
    int hours = (int)( milliseconds / (1000*60*60));
    int minutes = (int)(milliseconds % (1000*60*60)) / (1000*60);
    int seconds = (int) ((milliseconds % (1000*60*60)) % (1000*60) / 1000);
    // Add hours if there
    if(hours > 0){
        finalTimerString = hours + ":";
    }

    // Prepending 0 to seconds if it is one digit
    if(seconds < 10) {
        secondsString = "0" + seconds;
    }else {
        secondsString = "" + seconds;
    }

    finalTimerString = finalTimerString + minutes + ":" + secondsString;

    // return timer string
    return finalTimerString;
}
于 2015-05-28T04:58:27.717 回答
4

这是我处理搜索栏的方式;

        mediaPlayer.setOnPreparedListener(new OnPreparedListener(){

        @Override
        public void onPrepared(MediaPlayer mp) {
            mediaPlayer.start();
            new SeekBarHandler().execute();
    });

现在我有一个名为 SeekBarHandler 的异步任务,它像这样处理搜索栏:

    public class SeekBarHandler extends AsyncTask<Void, Void, Void> {

@Override
protected void onPostExecute(Void result) {
    Log.d("##########Seek Bar Handler ################","###################Destroyed##################");
    super.onPostExecute(result);
}

@Override
protected void onProgressUpdate(Void... values) {
    seekBar.setProgress(mediaPlayer.getCurrentPosition());
    super.onProgressUpdate(values);
}

@Override
protected Void doInBackground(Void... arg0) {
    while(mediaPlayer.isPlaying()&&isViewOn==true) {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    onProgressUpdate();
    }
    return null;
}

    }

现在在我的 onPause 中,我终止了 AsyncTask,因为当用户看不到搜索栏时保持线程继续运行是没有意义的

    protected void onPause() {
    isViewOn=false;
    super.onPause();
    }

在 onResume 我像这样启动 AsyncTaskAgain

    protected void onResume() {
    isViewOn=true;
    new SeekBarHandler().execute();
    super.onResume();
    }

如您所见,我使用布尔标志 isViewOn 来检查视图是否打开以处理搜索栏。

于 2013-07-27T01:03:23.173 回答
4
player.prepare(); // or start()

ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleWithFixedDelay(new Runnable()
{
  @Override
  public void run()
  {
    progressBar.setProgress(player.getCurrentPosition());
  }
}, 1, 1, TimeUnit.MICROSECONDS);
于 2015-06-05T09:40:01.793 回答
0

您遇到的问题与 Android 的 SeekBar 的设计/实现方式有关。虽然它运行得很好,但您会受到所使用的段(即seekbar.setMax(int))和处理程序延迟时间的组合的限制。

话虽如此,我将 SeekBar 子类化以制作我自己的 SmoothSeekBar,它使用 ViewPropertyAnimators 而不是 Handler。

在这里查看:https ://github.com/Indatus/Android-SmoothSeekBar

于 2013-10-09T01:48:33.173 回答
0
private void startPlaying() {
        mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.reset();
            mediaPlayer.setDataSource(audioPlayerName);
            mediaPlayer.prepare();
            mediaPlayer.start();

            setAudioProgress(); //call method

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


public void setAudioProgress() {
    total_duration = mediaPlayer.getDuration();

    binding.total.setText(timeConversion((long) total_duration));
    binding.current.setText(timeConversion((long) current_pos));
    binding.seekbar.setMax((int) total_duration);

    runnable = new Runnable() {
        @Override
        public void run() {
            try {
                current_pos = mediaPlayer.getCurrentPosition();
                binding.current.setText(timeConversion((long) current_pos));
                binding.seekbar.setProgress((int) current_pos);
                handlerProgressBar.postDelayed(this, 1000);

                Log.e(LOG_TAG, "11111");
            } catch (IllegalStateException ed) {
                ed.printStackTrace();
            }
        }
    };
    handlerProgressBar.postDelayed(runnable, 1000);
}
于 2020-10-26T14:43:31.640 回答