Question

I am playing audio file of different sizes in my application and while audio is playing the progress bar should progress smoothly but progress bar is taking random size steps.

I am using following code :

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

Is there any way to smoothly increase progressbar?

Was it helpful?

Solution

Please check this steps

Step 1: Get audio duration with MediaPlayer.getDuration()

Step 2: Set ProgressBar progress max. value to value from step 1

Step 3:

Update progress bar periodically from MediaPlayer.getCurrentPosition(), while media playing using Handler.

So the code will be like this

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

I followed this link for the code

OTHER TIPS

Set the Max size of progress bar to a high range... If u set the progress bar to increment between 1 to maximum 100, then rather than using 100 as max use 1000 in place..This is a suggestion from me. Coz i found your code working ok.

This is my mediaplayer creation , just check it out .

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

   }

You can make it smoother by using following logic.

  1. Store current value of progress bar and latest progress value as members.

  2. Update latter when onProgressUpdate method is called.

  3. In a timer, put this logic to be executed periodically.

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

    Note that it will slowly march towards it's target value.

Hope this helps.

Although the suggestion of using Handler to track the current position of Audio while playing is the only correct way. However, MediaPlayer.getCurrentPosition() not super precise for short audio (saying, about 1 second); and to make life easier I wrote a Utils class to support this purpose by using CountDownTimer

Link demo: https://github.com/mttdat/utils

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top