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);
}
});
}
Related
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);
}
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 an ImageButton and I want to make it fade in randomly and fade out after some time.
How can I do this?
With a thread? with a service? with something else?
Sorry if it is a very novice question. Thank you
This will fade in/out the imageButton in random interval of 1-5 seconds.
private boolean fadeIn = false;
private final Random rand = new Random();
...
final Handler handler = new Handler(Looper.getMainLooper());
final Runnable runnable = new Runnable() {
#Override
public void run() {
imageButton.animate().alpha(fadeIn ? 1.0f : 0.0f).setDuration(500).withEndAction(new Runnable() {
#Override
public void run() {
fadeIn = !fadeIn;
}
});
handler.postDelayed(this, randInt(1000, 5000));
}
};
handler.post(runnable);
...
public int randInt(int min, int max) {
return rand.nextInt((max - min) + 1) + min;
}
#Override
protected void onDestroy() {
handler.removeCallbacks(runnable);
super.onDestroy();
}
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();
}
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.