Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android MediaPlayer getCurrentPosition() causes audio stutter

I'm using a SeekBar to display the progress of an audio file and for seeking to a certain time. For updating I use a Runnable which calls getCurrentPosition() on a MediaPlayer every second or so. Every time that happens there is a small amount of lag in the audio. Since I call it often, I get very noticeable stuttering while playing something. If it's relevant, I'm using setAudioStreamType(AudioManager.STREAM_MUSIC) and the file format is mp4 whith AAC audio (no video) and I'm using Android 2.3.4. Is there a way to get good audio with getCurrentPosition(), or do I have to implement my own progress calculations?

The Runnable:

private Runnable mUpdateTask = new Runnable(){

    @Override
    public void run() {
        mSeekBar.setProgress((int) (mPlayer.getCurrentPosition() * 100 / mArrayAdapter.getRecording(mPlayingId).mDuration));
        mHandler.postDelayed(mUpdateTask, 999);
    }
};
like image 960
DariusL Avatar asked Sep 29 '12 09:09

DariusL


2 Answers

I had the same problem or something similar.

When I've used mMediapPlayer.getCurrentPosition() in a TimerTask to update the SeekBar, I heard sound problems like echo but actually the problem wasn't there..

The issue is that I've also used SeekBar OnSeekBarChangeListener for manual seek but what happened is that update the seekBar from the TimerTask also triggered the listener, which did mp.seekTo(progress) and this, caused the mp to return back to that position again..

I've fixed it by using the fromUser argument as suggested here to do seek only if the seekBar changed manually.

Here is my sample code:

The TimerTask:

public void initializeTimerTask() {

    mTimerTask = new TimerTask() {

        public void run() {

            int progress = mp.getCurrentPosition()/1000;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mSeekBar.setProgress(progress);
                    tvDuration.setText(DateUtils.formatElapsedTime(progress));
                }
            });

        }
    };
}

Listener:

 mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if(mp != null && fromUser){
                mp.seekTo(progress * 1000);
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });
like image 70
Moti Bartov Avatar answered Nov 15 '22 14:11

Moti Bartov


you can do something like this:

private Runnable mUpdateTask = new Runnable(){

    @Override
    public void run() 
  {
        mSeekBar.setProgress(mMediapPlayer.getCurrentPosition());       
        mHandler.postDelayed(mUpdateTask, 999);
    }
};

you can also apply seek bar progress change listener as follow:

mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() 
            {               
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) 
                {               
                }
                @Override
                public void onStartTrackingTouch(SeekBar seekBar)
                {                   
                }
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) 
                {
                    if (fromUser) 
                    {
                        int secProgress = seekBar.getSecondaryProgress();
                                if (secProgress> progress) 
                                {
                                    mMediapPlayer.seekTo(progress);
                                } 
                                else
                                {   
                                    seekBar.setProgress(mSeekBar.getProgress());
                                }
                    }

                }               
            });
            mMediapPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() 
            {

                    @Override
                    public void onBufferingUpdate(MediaPlayer mp, int percent) 
                    {
                        mSeekBar.setSecondaryProgress((mSeekBar.getMax()/100)*percent);

                    }
                });
like image 31
Shiva Avatar answered Nov 15 '22 12:11

Shiva