Seekbar and Media Player in Android

SeekBar and media player in android

To create a 'connection' between SeekBar and MediaPlayer you need first to get your current recording max duration and set it to your seek bar.

mSeekBar.setMax(mFileDuration/1000); // where mFileDuration is mMediaPlayer.getDuration();

After you initialise your MediaPlayer and for example press play button, you should create handler and post runnable so you can update your SeekBar (in the UI thread itself) with the current position of your MediaPlayer like this :

private Handler mHandler = new Handler();
//Make sure you update Seekbar on UI thread
MainActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
if(mMediaPlayer != null){
int mCurrentPosition = mMediaPlayer.getCurrentPosition() / 1000;
mSeekBar.setProgress(mCurrentPosition);
}
mHandler.postDelayed(this, 1000);
}
});

and update that value every second.

If you need to update the MediaPlayer's position while user drag your SeekBar you should add OnSeekBarChangeListener to your SeekBar and do it there :

        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

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

And that should do the trick! : )

EDIT:
One thing which I've noticed in your code, don't do :

public MainActivity() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}

make all initialisations in your onCreate(); , do not create constructors of your Activity.

Android - SeekBar and MediaPlayer

You need to define separate Runnable and trigger it every x miliseconds (depends on you) once MediaPlayer starts.

Define a function updateSeekbar like,

private void updateSeekBar() {
audioSeek.setProgress(player.getCurrentPosition());
txtCurrentTime.setText(milliSecondsToTimer(player.getCurrentPosition()));
seekHandler.postDelayed(runnable, 50);
}

And Runnable

Runnable runnable = new Runnable() {
@Override
public void run() {
updateSeekBar();
}
};

Now you just have to call updateSeekbar once when playing starts. In your case:

public void onPlayButtonClicked(View v) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
pb.setImageResource(R.drawable.pause);

updateSeekBar();

} else {
mediaPlayer.pause();
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
}

FYI

Function milliSecondsToTimer works as follows

private 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;
}

UPDATE

You have called setMax at the wrong place. Update setup() function as follows

private void setup() {
/* the song has been select setup the interface */
/* displays song name in title */
TextView titleView = (TextView) findViewById(R.id.song_appbar_title);
String songName;

ContentResolver contentResolver = this.getContentResolver();
Cursor cursor = contentResolver.query(song, null, null, null, null);

if (cursor != null && cursor.moveToFirst()) {
songName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
titleView.setText(songName);
}

/* removes the notSelected String */
selectSong.setVisibility(View.GONE);

/* setup media player */
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(getApplicationContext(), song);
mediaPlayer.prepareAsync();
} catch (IOException e) {
Toast.makeText(this, "file not found", Toast.LENGTH_SHORT).show();
}

mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
/* show media player layout */
seekBar.setMax(mediaPlayer.getDuration());

RelativeLayout mpl = (RelativeLayout) findViewById(R.id.media_player_layout);
mpl.setVisibility(View.VISIBLE);
mediaPlayer.start();

updateSeekBar();

ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.pause);

}
});

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
});

}

Android communication between MediaPlayer and SeekBar in MediaSession Architecuture

You can post your MediaPlayer's position updates in MediaSessionCompat on service side and then in your fragment you will receive Playback state updates in MediaControllerCompat.Callback's onPlaybackStateChanged(PlaybackStateCompat state) method.
Use a handler to post MediaPlayer update at regular intervals. Something like this:

public void onPlay() {
if (!mMediaPlayer.isPlaying()) {
mMediaPlayer.start();
updateCurrentPosition();
}
}

public void onPause() {
super.onPause();
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder()
.setActions(PAUSE_ACTIONS)
.setState(PlaybackStateCompat.STATE_PAUSED, mMediaPlayer.getCurrentPosition()
, 0)
.build();
stopPlaybackStateUpdate();
}
}

private void updateCurrentPosition() {
if (mMediaPlayer == null) {
return;
}
handler.postDelayed(new Runnable() {
@Override
public void run() {
int currentPosition = mMediaPlayer.getCurrentPosition();
PlaybackStateCompat playbackState = new PlaybackStateCompat.Builder()
.setActions(PLAYING_ACTIONS)
.setState(PlaybackStateCompat.STATE_PLAYING, currentPosition, 1)
.build();
mMediaSession.setPlaybackState(playbackState);
updateCurrentPosition();
}
}, 1000);
}

private void stopPlaybackStateUpdate() {
if (handler != null) {
handler.removeCallbacksAndMessages(null);
}
}

You can set the total duration of Media file using MediaSessionCompat.setMetadata(Metadata).

MediaMetadataCompat mediaMetadata = new MediaMetadataCompat.Builder()
.putString(MediaMetadata.METADATA_KEY_TITLE, "XYZ"))
.putLong(MediaMetadata.METADATA_KEY_DURATION, mMediaPlayer.getDuration())
.build();

In your your Fragment/Activity, you can then set the progress(i.e Seekbar.setProgress()) of current position of MediaPlayer using the Position update that are received in MediaController.Callback. Also set the Seekbar.setMax using the total duration of currently playing media.

    private MediaControllerCompat.Callback mMediaControllerCallback =

new MediaControllerCompat.Callback() {
@Override
public void onMetadataChanged(MediaMetadataCompat metadata) {
super.onMetadataChanged(metadata);
int totalDuration = (int) metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION);
mSeekBar.setMax(totalDuration);
}

@Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
mSeekBar.setMax(state.getPosition()); //You will receive MediaPlayer's current position every 1 second here.
}

};

Android SeekBar to control MediaPlayer progress

The problem is seekBar.setOnSeekBarChangeListener(this); So put it in Your AudioControl() Method.....
You dont set oncheckchangedlistner to your seekbar....

Android MediaPlayer seekBar not working correctly

The max value for progress is 100. The seekTo function takes time in milliseconds. This is why it seeks to the start (almost) of the audio.

So instead of mediaPlayer.seekTo(progress);, you need to do:

long newTime = (progress/100.0) * total_audio_duration_in_millisecond; 
mediaPlayer.seekTo(newTime);

Media Player - Seek bar and Time lable is not progressing

So well why should threads sleep 1000000000 milliseconds.
In that case your thread does its tasks every 1000000 seconds.

1000000000 ms => 1000000 sec => 16666 min => 277 hour

So your thread does its task every 277 hours.
The param of sleep is millisecond so put st like 1000(1 second) or something like that which is a lot shorter.
If this wasn't solution let me know.

Fixing a seekbar on my Android music player

Its easy. Follow these steps :-

  1. Add a seek bar change Listener.

    seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {         
    int seeked_progess;

    @Override
    public void onProgressChanged(final SeekBar seekBar, int progress, boolean fromUser) {

    seeked_progess = progress;
    seeked_progess = seeked_progess * 1000;

    if (fromUser) {
    }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }
    });
  2. Now in if(fromUser), U need to add the implementation.

      if (fromUser) {

    Runnable mRunnable = new Runnable() {

    @Override
    public void run() {
    int min, sec;

    if (mediaPlayer != null /*Checking if the
    music player is null or not otherwise it
    may throw an exception*/) {
    int mCurrentPosition = seekBar.getProgress();

    min = mCurrentPosition / 60;
    sec = mCurrentPosition % 60;

    Log.e("Music Player Activity", "Minutes : "+min +" Seconds : " + sec);

    /*currentime_mm.setText("" + min);
    currentime_ss.setText("" + sec);*/
    }
    mHandler.postDelayed(this, 1000);
    }
    };
    mRunnable.run();}
  3. At last add this in onStopTrackingTouch()

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    mediaPlayer.seekTo(seeked_progess);
    }
    });

Note :-

mHandler in a global variable.
Initialize it as follows.

Handler mHandler = new Handler();

Secondly currentime_mm and currentime_ss are text views which display the current seek time of the seek bar.

and most Important,
dont forgot to add these when a song starts

seekBar.setProgress(0);// To set initial progress, i.e zero in starting of the song
seekBar.setMax(mediaDuration);// To set the max progress, i.e duration of the song


Related Topics



Leave a reply



Submit