Originally, I had a MediaPlayer mPlayers to play/pause/stop my Audio file. Now, I'm trying to add a seek bar for my media. I tried using Threads and this is what I came up with:
In onCreate() :
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
mPlayer.seekTo(progress);
}
////........Omitted Code..........\\\\
//At the very end of the method:
seekThread = new Thread(this); //My Activity implements:Runnable
seekThread.start();
Then, I implemented a method run() to update my seek bar every 1 sec:
public void run() {
try {
while(mPlayer != null){
int currentPosition = mPlayer.getCurrentPosition();
Message msg = new Message();
msg.what = currentPosition;
threadHandler.sendMessage(msg);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private Handler threadHandler = new Handler(){
public void handleMessage(Message msg){
seekBar.setProgress(msg.what);
}
};
However, In my HTC Magic, the audio run inefficiently. Some words are repeated. It seems like the seek bar is going back a little bit every some time.
To make you understand the problem well, Let's say this: if the audio says that: abcdefghijklmn , then it will be like this: abccdeffghijjklmnn.
Any improvement you suggest to my thread ? Am I doing it right?
Not sure this will help, but try:
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (fromUser) {
mPlayer.seekTo(progress);
}
}
Without this condition, mPlayer.seekTo(progress); is called every time you call seekBar.setProgress(msg.what);
Related
I have looked everywhere to fix my problem but i just cant seem to get it going.
How do i make seekbar automatically with voice recorder ?
I have checked these links but did not find any solution
Move Seekbar not smooth
how to get seekbar to automatically move on song play?
lstfile.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
player = new MediaPlayer();
try {
player.setDataSource(listFiles[i].toString());
player.prepare();
player.start();
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
int videoduration=player.getDuration();
float progress=i/100.0f;
float time=videoduration*progress;
player.seekTo((int) time);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
You can use Handler with delay of 500ms or whatever you wish and update the seekbar inside the runnable method.
Refer below code,
Handler seekBarHandler = new Handler();
private final Runnable updateSeekBarPosRunnable = new Runnable() {
#Override
public void run() {
updateSeekPosition();
}
};
//UPDATE_FREQUENCY = 500ms or reduce/increase it as per your requirement
private void updateSeekPosition() {
seekBarHandler.removeCallbacks(updateSeekBarPosRunnable);
seekBarMusic.setProgress(mediaPlayer.getCurrentPosition());
seekBarHandler.postDelayed(updateSeekBarPosRunnable, UPDATE_FREQUENCY);
}
Now when you start recording start handler,
seekBarHandler.postDelayed(updateSeekBarPosRunnable, UPDATE_FREQUENCY);
when you stop the recorder remove the callback,
seekBarHandler.removeCallbacks(updateSeekBarPosRunnable);
I hope this may help you.
I'm working with an Android service which is managing a seekbar.
Here is the code (I just put the code concerning the seekbar):
public class MediaPlayerService extends Service implements
Runnable,
SeekBar.OnSeekBarChangeListener {
private MediaPlayer mediaPlayer = null;
private AudioManager audioManager;
private SeekBar seekBarTime;
#Override
public void onCreate() {
//SET SEEKBAR
LayoutInflater inflater = ( LayoutInflater ) getSystemService( LAYOUT_INFLATER_SERVICE );
View layout = inflater.inflate( R.layout.play_song , null);
seekBarTime = (SeekBar) layout.findViewById(R.id.seekBarTime);
seekBarTime.setOnSeekBarChangeListener(this);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
if(mediaPlayer != null) {
int currentPosition = 0;
int total = mediaPlayer.getDuration();
seekBarTime.setMax(total);
while (currentPosition < total && mediaPlayer != null ) {
try {
Thread.sleep(1000);
currentPosition = mediaPlayer.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
seekBarTime.setProgress(currentPosition);
}
}
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
Log.w("disgustingapps", "seekbar");
if (fromUser == true) {
mediaPlayer.seekTo(progress);
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
The problems are two. I will try to explain that with my bad English:
1) I want the seekbar to be automatically updated by the service in order to show the current time of the song ( mediaPlayer.getCurrentPosition() )
2) I want the user to be allowed to move the seekbar in order to move among the time of the song
Both things don't work. It seems that seekbar is completely "indipendent" from the code. I mean: the cursor doesn't move at all and also if the user move it the song go on without doing nothing.
Please, help me
Thank you in advance
You can't use SeekBar (or any UI control) in Android Service
I am trying to write a new feature for a flashlight app. I am pretty sure I need a new Thread to do this. HOWEVER, I am new to Threads and do not know how to do it at all. What I am trying to do is on the change of a SeekBar, I want the strobe to get faster/ slower. If it is 0 or 1 resume to constant light.
This is wrong, but this is what I have. Whenever I move the SeekBar it correctly strobes, but you cannot make it stop..
In onCreate():
mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
final int myInt = progress;
new Thread (new Runnable() {
public void run() {
if (myInt>1)
strobeLight(myInt);
else {}
// Stop Strobe
} }).start();
}
public void onStartTrackingTouch(SeekBar seekBar) {}
public void onStopTrackingTouch(SeekBar seekBar) {}
});
strobeLight() method:
public void strobeLight(int myInt){
do {
if (myInt>1){
if (strobe){
processOffClick();
try { Thread.sleep(300/myInt); }
catch (InterruptedException e) {}
strobe=false;
strobeActivated=true;}
else{
processOnClick();
try { Thread.sleep(300/myInt); }
catch (InterruptedException e) {}
strobe=true; }
}
else{
processOnClick();
strobe=false;
Thread.currentThread().interrupt();
strobeActivated=false;}
} while (strobeActivated);
}
I am unsure about the need of creating a new thread every time the progress changes, a better approach might be to create a final runnable in which you change the integer value:
onProgressChange:
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
toRun.interval = progress;
}
A runnable-implementation:
class StrobeRunnable implements Runnable {
volatile boolean running;
volatile int interval = 0;
private boolean lightIsOn = false;
#Override
public void run() {
while(running){
if (interval > 1){
Thread.sleep(300/interval);
lightIsOn = !lightIsOn;
switchLight(lightIsOn);
}
else{
Thread.sleep(600/interval);
if( !lightIsOn ){
lightIsOn = true;
switchLight(lightIsOn);
}
}
}
}
};
Note that I created new names for some methods,
switchLight(boolean isLightOn) is what I believe your processXClick did before, namely switch the light on or of.
And interval used to be called myInt.
To start a thread I prefer to use Executors:
StrobeRunnable toRun = new StrobeRunnable();
Executor exec = Executors.newSingleThreadExecutor();
exec.execute(toRun);
To completely stop the thread from running, set the toRun.running to false, and this will stop the running loop.
I haven't tested this but it should work. It also depends a bit on how your processClick-method looks.
In my Android application I am facing issue with seekbar of MediaController that I am using for Videoview.
I would like to know if the user seeks to a position greater than the buffered position,I need to show a dialog and then dismiss the dialogue on seek completed.
Please let me know if I can have this solved.
mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar arg0) {
// you can check for the current buffer state and where the use seek using mSeekBar.getProgress() and then open up a dialog.
if(condition to match buffering and seek position)
openDialog();
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
}
#Override
public void onProgressChanged(SeekBar arg0, int progress, boolean arg2) {
}
});
...
public void openDialog()
{
...
// check for buffer level to match your seek position
// when it meets the codition,cancel the dialog.
...
}
Couple ways of doing this.
Option 1: Just use the OnInfoListener from the media player.
This will send you info when the buffering has started and stopped.
mPlayer.setOnInfoListener(OnInfo);
Then create your listener code.
// info from player sent.
OnInfoListener OnInfo =
new OnInfoListener() {
public boolean onInfo(MediaPlayer mp, int what, int extra) {
Log.d(TAG,"media info what:"+what+" extra:"+extra);
// check about buffering status.
if(what==MediaPlayer.MEDIA_INFO_BUFFERING_START) {
// note: we are assuming _progressDialog was created already
_progressDialog.setMessage("Buffering...");
_progressDialog.show();
} else if(what==MediaPlayer.MEDIA_INFO_BUFFERING_END) {
if(_progressDialog.isShowing())
_progressDialog.dismiss();
}
return false;
}
};
Option 2: use the OnBufferingUpdateListener to keep track of how much has been buffered.
mPlayer.setOnBufferingListener(OnBufferingUpdate);
Then create the actual listen code.
// buffering update
OnBufferingUpdateListener OnBufferingUpdate =
new OnBufferingUpdateListener() {
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
Log.d(TAG,"BUFFERING: "+ String.valueOf(percent));
// store the percent value and check it in onStopTrackingTouch()
// which is in your setOnSeekBarChangeListener
}
};
I intend to write a custom media controller for my app. I was planning to use seekbar to do both seeking and showing progress. Trying to implement this.
Does anyone have such implementation or am I on the wrong path ?
Finally I figured it out!!
The solution that I came up with was something like this :
First of all set the max progress for seekbar as the duration of the video
videoView.setOnPreparedListener(new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
seekBar.setMax(videoView.getDuration());
seekBar.postDelayed(onEverySecond, 1000);
}
});
This runnable will keep on updating the progressbar :
private Runnable onEverySecond=new Runnable() {
#Override
public void run() {
if(seekBar != null) {
seekBar.setProgress(videoView.getCurrentPosition());
}
if(videoView.isPlaying()) {
seekBar.postDelayed(onEverySecond, 1000);
}
}
};
And then the setOnSeekBarChangeListener for the seekbar can be used to take the user seeks on the media. By using the fromUser boolean we can make out whether it was a call back due to user's interaction or the
seekBar.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) {
// this is when actually seekbar has been seeked to a new position
videoView.seekTo(progress);
}
}
});
You set the seconday progress.
No, you're on the right track. It is very good for displaying stuff like download progress and current location for streams (media).