Update Seekbar as it plays the audio

Asked

Viewed 226 times

3

I created a seekBar to see the progress of my audio running on MediaPlayer, but of all the methods I used to update the seekBar, the only one that worked was this below:

new Timer().schedule(new TimerTask() {
        @Override
        public void run() {
            mySeekBar.setProgress(mp.getCurrentPosition());
        }
    }, 0, 1000);

All the others, as for example, those I quote below, did not work.

Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            mySeekBar.setProgress(mp.getCurrentPosition());
        }
    }, 1000);

        new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                mySeekBar.setProgress(mp.getCurrentPosition());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

    new Thread(new TimerTask() {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                runOnUiThread(new TimerTask() {
                    @Override
                    public void run() {
                        mySeekBar.setProgress(mp.getCurrentPosition());
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

So I’d like to know why the others don’t work, because for me, they should all work. Here’s the full app code:

package com.gabrielm.testseekbar;

import android.media.MediaPlayer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;

import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    SeekBar mySeekBar;
    Button btnPlay;
    MediaPlayer mp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mySeekBar = (SeekBar) findViewById(R.id.mySeekBar);
        btnPlay = (Button) findViewById(R.id.btnPlay);
        mp = MediaPlayer.create(this, R.raw.sleep);

        mySeekBar.setMax(mp.getDuration());

        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                mySeekBar.setProgress(mp.getCurrentPosition());
            }
        }, 0, 1000);

        btnPlay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mp.start();
            }
        });



        mySeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                Log.i("Audio position", Integer.toString(progress));
                mp.seekTo(progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }
}

1 answer

1


Code 1:

Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            mySeekBar.setProgress(mp.getCurrentPosition());
        }
    }, 1000);

It does not do what you want because the Seekbar is only updated once, postDelayed(Runnable r, long delayMillis) executes the Runnable r once with a delay 1000-millisecond.

This can be solved by adding again the Runnable à Queue within the method run():

final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            mySeekBar.setProgress(mp.getCurrentPosition());
            handler.postDelayed(this, 1000);
        }
    }, 1000);

Code 2:

    new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
            mySeekBar.setProgress(mp.getCurrentPosition());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});

Does not work because the code is never executed: the method must be called start() of Thread. Solved this also would not work because it is only allowed to change Views in Uithread. On the other hand the method run() would only be called once.

Code 3:

new Thread(new TimerTask() {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
            runOnUiThread(new TimerTask() {
                @Override
                public void run() {
                    mySeekBar.setProgress(mp.getCurrentPosition());
                }
            });
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});

The code does not compile, the constructor of Thread gets a Runnable and not a Timertask.
As in code 2 missing call the method start(), besides which would also only work once, however, resolves the issue of Uithread, using the method runOnUiThread().

Browser other questions tagged

You are not signed in. Login or sign up in order to post.