I wanted to create a seekBar that track the progress of a mediaplayer but it doesnt work out quite well, the music is playing but the seekbar stay idle. Is there something that I left out?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
seekBar = (SeekBar) findViewById(R.id.seekBar1);
seekBar.setOnSeekBarChangeListener(this);
}
public void onClick(View v){
if(v == stopButton){
mediaPlayer.pause();
}else if(v == startButton){
mediaPlayer.start();
run();
}else if(v == quitButton ){
mediaPlayer.stop();
mediaPlayer.release();
}
}
public void run() {
int currentPosition= 0;
int total = mediaPlayer.getDuration();
while (mediaPlayer.isPlaying()) {
currentPosition= mediaPlayer.getCurrentPosition();
seekBar.setProgress(currentPosition);
}
}
In Android Building Audio Player Tutorial see section Updating SeekBar progress and Timer
/**
* Update timer on seekbar
* */
public void updateProgressBar() {
mHandler.postDelayed(mUpdateTimeTask, 100);
}
/**
* Background Runnable thread
* */
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
long totalDuration = mp.getDuration();
long currentDuration = mp.getCurrentPosition();
// Displaying Total Duration time
songTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDuration));
// Displaying time completed playing
songCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(currentDuration));
// Updating progress bar
int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration));
//Log.d("Progress", ""+progress);
songProgressBar.setProgress(progress);
// Running this thread after 100 milliseconds
mHandler.postDelayed(this, 100);
}
};
/**
*
* */
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
}
/**
* When user starts moving the progress handler
* */
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// remove message Handler from updating progress bar
mHandler.removeCallbacks(mUpdateTimeTask);
}
/**
* When user stops moving the progress hanlder
* */
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
mHandler.removeCallbacks(mUpdateTimeTask);
int totalDuration = mp.getDuration();
int currentPosition = utils.progressToTimer(seekBar.getProgress(), totalDuration);
// forward or backward to certain seconds
mp.seekTo(currentPosition);
// update timer progress again
updateProgressBar();
}
Related
I've just developed a simple media player that sounds a song and it has a seekbar that regulate the song volume.
That's my code:
public class MainActivity extends AppCompatActivity {
Button playBtn;
SeekBar positionBar;
SeekBar volumeBar;
TextView elapsedTimeLabel;
TextView remainingTimeLabel;
MediaPlayer mp;
int totalTime;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playBtn = (Button) findViewById(R.id.playBtn);
elapsedTimeLabel = (TextView) findViewById(R.id.elapsedTimeLabel);
remainingTimeLabel = (TextView) findViewById(R.id.remainingTimeLabel);
// Media Player
mp = MediaPlayer.create(this, R.raw.song);
mp.setLooping(true);
mp.seekTo(0);
mp.setVolume(0.5f, 0.5f);
totalTime = mp.getDuration();
// Position Bar
positionBar = (SeekBar) findViewById(R.id.positionBar);
positionBar.setMax(totalTime);
positionBar.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
mp.seekTo(progress);
positionBar.setProgress(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
);
// Volume Bar
volumeBar = (SeekBar) findViewById(R.id.volumeBar);
volumeBar.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float volumeNum = progress / 100f;
mp.setVolume(volumeNum, volumeNum);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
);
// Thread (Update positionBar & timeLabel)
new Thread(new Runnable() {
#Override
public void run() {
while (mp != null) {
try {
Message msg = new Message();
msg.what = mp.getCurrentPosition();
handler.sendMessage(msg);
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
}
}).start();
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
int currentPosition = msg.what;
// Update positionBar.
positionBar.setProgress(currentPosition);
// Update Labels.
String elapsedTime = createTimeLabel(currentPosition);
elapsedTimeLabel.setText(elapsedTime);
String remainingTime = createTimeLabel(totalTime-currentPosition);
remainingTimeLabel.setText("- " + remainingTime);
}
};
public String createTimeLabel(int time) {
String timeLabel = "";
int min = time / 1000 / 60;
int sec = time / 1000 % 60;
timeLabel = min + ":";
if (sec < 10) timeLabel += "0";
timeLabel += sec;
return timeLabel;
}
public void playBtnClick(View view) {
if (!mp.isPlaying()) {
// Stopping
mp.start();
playBtn.setBackgroundResource(R.drawable.ic_stop);
} else {
// Playing
mp.pause();
playBtn.setBackgroundResource(R.drawable.ic_play);
}
} }
Now, when I regulate the volume with the media player seekbar, the phone system volume didn't change and the other way around.
How can I syncronize the volume seekbar with the phone system volume so as to adjust the volume with both?
Using the Audio Manager to Raise and Down Volume.
AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
//Using volume control UI visibility
//To increase media player volume
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
//To decrease media player volume
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
//Without volume control UI
//To increase media player volume
audioManager.adjustVolume(AudioManager.ADJUST_RAISE, AudioManager.FLAG_PLAY_SOUND);
//To decrease media player volume
audioManager.adjustVolume(AudioManager.ADJUST_LOWER, AudioManager.FLAG_PLAY_SOUND);
I'm trying to animate the seekbar progress. It works fine when the progress update is not from user(which is what I want) but when the user drags the seekbar, I want the animation to stop. Right now what happens is when user drags the seekbar, the seekbar progress animates and there is delay because of the animation. I hope you guys get what I'm trying to say. I only want the animation when the input is not from user else animate.
Code:
circularSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
circularSeekBar.setEnabled(true);
if(fromUser) {
int seekprogress = (int) circularSeekBar.getProgress();
Intent io = new Intent(ConstantsForBroadCast.ACTION_PLAY_SEEKBAR);
io.putExtra("Progress", seekprogress);
getActivity().sendBroadcast(io);
}
}
public void Handler(final MediaPlayer mp){
currentSongLength= mp.getDuration();
final Handler mHandler = new Handler();
if((Activity)getActivity()!=null) {
((Activity) getActivity()).runOnUiThread(new Runnable() {
#Override
public void run() {
circularSeekBar.setMax((int) currentSongLength / 1000);
int mCurrentPosition = mp.getCurrentPosition() / 1000;
ObjectAnimator animation1 = ObjectAnimator.ofInt(circularSeekBar,"progress", mCurrentPosition);
animation1.setDuration(1000); // 0.5 second
animation1.setInterpolator(new DecelerateInterpolator());
animation1.start();
circularSeekBar.clearAnimation();
mHandler.postDelayed(this, 1000);
}
});
}
I am making a audio player but i'm not able to update the Seek bar without any lag. Kindly try this code and help me!
private void updateProgress() { //To update progress of seekbar
long currentPosition = mpintro.getCurrentPosition();
txtstart.setText(String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(mpintro.getCurrentPosition()),
TimeUnit.MILLISECONDS.toSeconds(mpintro.getCurrentPosition()) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long)
mpintro.getCurrentPosition()))));
seekBar.setProgress((int) currentPosition); //To set seekbar to current position
}
public void playpause()
{
final int delay = 1000; //milliseconds
h.postDelayed(new Runnable(){
public void run() {
updateProgress();
h.postDelayed(this, 1000);
};
}, delay);
}
Change the onProgressChanged function as:
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean fromUser) {
if(fromUser) {
mplayer.seekTo(i);
}
}
This is because when your updateProgress funtion updates the seekbar, it also triggers the on onProgressChanged function, which again alters the seekbar and the audio lags.
So, add the if statement to check if the seekbar is changed only from user.
This sort of question seems to have come up a here a lot, but they are all a slightly different case to mine and have just confused me. I am trying to get my SeekBar to synchronise with a single and specified mp3. With the code below, the audio plays and if you move the SeekBar the audio DOES seek, however the SeekBar does not move on its own to update with the music. Could someone please see if they can find the problem that is stopping the SeekBar from updating?
FIXED NOW but don't know why it fixed.
This is my FIXED Java code. Changes in bold:
MediaPlayer mediaPlayer;
Button buttonPlayPause;
ImageView Image;
SeekBar seekBar;
Handler handler;
private int stateMediaPlayer;
private final int stateMP_NotStarter = 0;
private final int stateMP_Playing = 1;
private final int stateMP_Pausing = 2;
private int mediaPos;
private int mediaMax;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.playerwere);
Image = (ImageView) findViewById(R.id.pdfview);
Image.setImageResource(R.drawable.wereim);
seekBar = (SeekBar) findViewById(R.id.seekBar);
buttonPlayPause = (Button) findViewById(R.id.playpause);
buttonPlayPause.setOnClickListener(buttonPlayPauseOnClickListener);
seekBar.setOnSeekBarChangeListener(seekBarOnSeekChangeListener);
initMediaPlayer();
mediaPos = mediaPlayer.getCurrentPosition();
mediaMax = mediaPlayer.getDuration();
seekBar.setMax(mediaMax); // Set the Maximum range of the
// seekBar.setProgress(mediaPos);// set
// current progress to song's
seekBar.setProgress(mediaPos);// set current progress to song's
handler.removeCallbacks(moveSeekBarThread);
handler.postDelayed(moveSeekBarThread, 100);
}
private Runnable moveSeekBarThread = new Runnable() {
public void run() {
if (mediaPlayer.isPlaying()) {
int mediaPos_new = mediaPlayer.getCurrentPosition();
int mediaMax_new = mediaPlayer.getDuration();
seekBar.setMax(mediaMax_new);
seekBar.setProgress(mediaPos_new);
handler.postDelayed(this, 100); // Looping the thread after 0.1
// seconds
} **else {
int mediaPos_new = mediaPlayer.getCurrentPosition();
int mediaMax_new = mediaPlayer.getDuration();
seekBar.setMax(mediaMax_new);
seekBar.setProgress(mediaPos_new);
handler.postDelayed(this, 100); // Looping the thread after 0.1
// seconds
}**
}
};
private void initMediaPlayer() {
handler = new Handler();
mediaPlayer = new MediaPlayer();
mediaPlayer = MediaPlayer.create(were.this, R.raw.were);
stateMediaPlayer = stateMP_NotStarter;
}
Button.OnClickListener buttonPlayPauseOnClickListener = new Button.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (stateMediaPlayer) {
case stateMP_NotStarter:
mediaPlayer.start();
buttonPlayPause
.setBackgroundResource(android.R.drawable.ic_media_pause);
stateMediaPlayer = stateMP_Playing;
break;
case stateMP_Playing:
mediaPlayer.pause();
buttonPlayPause
.setBackgroundResource(android.R.drawable.ic_media_play);
stateMediaPlayer = stateMP_Pausing;
break;
case stateMP_Pausing:
mediaPlayer.start();
buttonPlayPause
.setBackgroundResource(android.R.drawable.ic_media_pause);
stateMediaPlayer = stateMP_Playing;
break;
}
}
};
SeekBar.OnSeekBarChangeListener seekBarOnSeekChangeListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
if (fromUser) {
mediaPlayer.seekTo(progress);
seekBar.setProgress(progress);
}
}
};
}
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);
}
};
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) {
}
});
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);
}
});
I use this method to caluclate progress'
public static int getProgressPercentage(long currentDuration,
long totalDuration) {
Double percentage = (double) 0;
long currentSeconds = (int) (currentDuration / 1000);
long totalSeconds = (int) (totalDuration / 1000);
// calculating percentage
percentage = (((double) currentSeconds) / totalSeconds) * 100;
// return percentage
return percentage.intValue();
}
Note: mPlayer.getCurrentPosition() is not accurate. There are some bugs reported. I had problem that current position was higher than totalDuration.