I'm trying to create a simple audio player, but when i'm applying a timer to a seekbar for updating it a song starting to lag. Here's the code:
final SeekBar playProgress = findViewById(R.id.playProgress);
playProgress.setMax(mPlayer.getDuration());
//++++++++Lagging++++++++++++
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run () {
playProgress.setProgress(mPlayer.getCurrentPosition());
}
},0,1000);
//+++++++++++++++++++++++++++
playProgress.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
#Override
public void onProgressChanged (SeekBar seekBar,int i, boolean b){
mPlayer.seekTo(i);
});
Your timer is running every 1000 milliseconds, and changing the progress of the playProgress to the current position. Everytime the progress is changed (onProgressChanged) you are executing a seekTo() to the seekbar's new position, which could induce the lag.
The onProgressChanged signature looks like this: onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) - try only executing the seekTo method if the fromUser variable is true, which would mean that you did not set the progress programmatically (which you are doing in your timer).
Replace:
mPlayer.seekTo(i);
By:
if(b){
mPlayer.seekTo(i);
}// so that this codes executes only when the user is changing it
Try this, it has worked for me.
myViewHolder.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// Update the progress depending on seek bar
if (fromUser) {
mediaPlayer.seekTo(progress);//if user drags the seekbar, it gets the position and updates in textView.
}
final long mMinutes = (progress / 1000) / 60;//converting into minutes
final int mSeconds = ((progress / 1000) % 60);//converting into seconds
myViewHolder.desc.setText(mMinutes + ":" + mSeconds);
}
Related
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've implemented a list of seekbars. According to my functionality, I want the sum of all seekbar not to exceed 100% for example if I drag first seekbar to 60% the next one will not exceed 40%.
I have made it work but whenever I drag the first one to some value (let's say 60 %) and then the second one to let's say 40% and then again when I try to drag the first one to decrease its value resets to 0. What is the problem with my code?
holder.shelfShareSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
remainingShelfShare = 100 - shelfShareSum;
holder.percentTextView.setText(String.valueOf(progress));
productShelfShareMap.get(((Products)list.get(position)).getProductID());
if(progress > remainingShelfShare){
holder.shelfShareSeekbar.setProgress(remainingShelfShare);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
list.get(position).setSetSlider(seekBar.getProgress());
shelfShareSum = 0;
productShelfShareMap.put(((Products)list.get(position)).getProductID(), Integer.parseInt(holder.percentTextView.getText().toString()));
for (HashMap.Entry<Integer, Integer> entry : productShelfShareMap.entrySet()){
shelfShareSum += entry.getValue();
}
}
});
Use SetMax function of seekbar to setvalue in SecondSeekbar.
int step = 1; // set it accordingly if you want data in 3.1,3.2 range
int max = 100;
int min; // if you want to set min criteria too.
shelfShareSeekbar.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)
{
// Ex :
// And finally set value of next seekbar based on firstone
secondseekbar.setMax((max - progress) / step);
}
}
);
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.
I have used four seekbars and placed one after another horizontally. Now if I start changing progress of first seekbar, the progress of first seekbar should change. And as soon as the first seekbar reaches at progress of 100, second seekbar should start change. The same flow applies for second and third seekbar also.
Is this possible ? Can someone help me out ?
here is a quick snippet, if i did understand your question correctly then the solution would be like below:
SeekBar seekBar = new SeekBar(this);
final SeekBar seekBar2 = new SeekBar(this);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (progress >= 100) seekBar2.setProgress(progress); // do the same for the other seekbars.
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
as soon as the first seekbar reaches 100, seekrBar2 will change its current progress following the first progress.
P.S this is a snippet code, you might need to follow it up and reflect your code accordingly.
A small change on Kosh's code :)
SeekBar seekBar1 = new SeekBar(this);
SeekBar seekBar2 = new SeekBar(this);
SeekBar seekBar3 = new SeekBar(this);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (progress > 100) seekBar2.setProgress(progress-100); // do the same for the other seekbars.
}
});
seekBar2.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (progress > 100) seekBar3.setProgress(progress-100); // do the same for the other seekbars.
}
});
This will help you :)
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.