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 :-
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) {
}
});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();}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
How to Rotate a Bitmap 90 Degrees
Where/How to Getintent().Getextras() in an Android Fragment
Bluetooth Pairing Without User Confirmation
Whatsapp Message Layout - How to Get Time-View in the Same Row
Making a Https Request Using Android Volley
Android: Scrollview VS Nestedscrollview
Googleplayservicesutil VS Googleapiavailability
Surfaceview Flashes Black on Load
Ssl Certificate Is Not Trusted - on Mobile Only
How to Set the Focus (And Display the Keyboard) on My Edittext Programmatically
Error: File Path Too Long on Windows, Keep Below 240 Characters
How to Get App Install Time from Android
Event Onclick for a Button in a Custom Notification
Stop Asynctask Doinbackground Method
Can the Android Emulator Record and Play Back Audio Using Pc Hardware