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
Related
I am playing mp3 file from url, but SeekBar is not updating while playing song.
It showing a buffering but not moving automatically when song starts.
When i am trying to move forcefully then also it working fine.
Below code i am using to play and update SeekBar.
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?
Please help me i am new in android.
public class XYZ extends Fragment implements MediaPlayer.OnBufferingUpdateListener,MediaPlayer.OnCompletionListener{
private SeekBar seekBar;
private MediaPlayer mediaPlayer;
private int mediaFileLength;
final Handler handler = new Handler();
private int realtimeLength;
Button b,b3,b4;
private double startTime = 0;
private double finalTime = 0;
public static int oneTimeOnly = 0;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_outside, container,
false);
rootView.setBackgroundResource(R.drawable.jotirling);
seekBar = rootView.findViewById(R.id.seekbar);
seekBar.setMax(99); // 100% (0~99)
seekBar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (mediaPlayer.isPlaying()) {
SeekBar seekBar = (SeekBar) v;
int playPosition = (mediaFileLength / 100) * seekBar.getProgress();
mediaPlayer.seekTo(playPosition);
}
return false;
}
});
b3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final ProgressDialog mDialog = new ProgressDialog(getActivity());
#SuppressLint("StaticFieldLeak") AsyncTask<String, String, String> mp3Play = new AsyncTask<String, String, String>() {
#Override
protected void onPreExecute() {
mDialog.setMessage("Please wait It will take time according to your network speed...!");
mDialog.show();
mDialog.setCancelable(false);
}
#Override
protected String doInBackground(String... params) {
try {
mediaPlayer.setDataSource(params[0]);
mediaPlayer.prepare();
} catch (Exception ignored) {
}
return "";
}
#Override
protected void onPostExecute(String s) {
mediaFileLength = mediaPlayer.getDuration();
realtimeLength = mediaFileLength;
if (!mediaPlayer.isPlaying()) {
p=1;
mediaPlayer.start();
Toast.makeText(getActivity(), "Playing sound", Toast.LENGTH_SHORT).show();
finalTime = mediaPlayer.getDuration();
startTime = mediaPlayer.getCurrentPosition();
b3.setBackgroundResource(R.drawable.pp);
if (oneTimeOnly == 0) {
oneTimeOnly = 1;
}
} else {
p=0;
mediaPlayer.pause();
Toast.makeText(getActivity(), "Pausing "+
"sound",Toast.LENGTH_SHORT).show();
b3.setBackgroundResource(R.drawable.p);
}
updateSeekBar();
mDialog.dismiss();
}
};
mp3Play.execute("URL"); // direct link mp3 file
}
});
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnCompletionListener(this);
return rootView;
}
private void updateSeekBar() {
seekBar.setProgress((int) (((float) mediaPlayer.getCurrentPosition() / mediaFileLength) * 100));
if (mediaPlayer.isPlaying()) {
Runnable updater = new Runnable() {
#Override
public void run() {
updateSeekBar();
}
};
}
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
seekBar.setSecondaryProgress(percent);
}
}
You should consider using setOnSeekbarChangeListener()
Reference : setOnSeekBarChangeListener()
Simple example would be
seekBar.setOnSeekBarChangeListener(new 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){
//do your things, like updating time durations etc.
}
}
});
Also if u a want working example, look at this link for code (i have just used circularSeekbar instead of regular one) https://github.com/iamSahdeep/Bop/blob/master/app/src/main/java/com/sahdeepsingh/Bop/Activities/PlayerView.java#L324
More Examples : https://www.javatips.net/api/android.widget.seekbar.onseekbarchangelistener
You can create use Timer for this:
seekBar.setMax(mediaPlayer.getDuration());
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
seekBar.setProgress(mediaPlayer.getCurrentPosition());
}
},0,1000);
You are defining Runnable updater but not calling it.
if (mediaPlayer.isPlaying()) {
Runnable updater = new Runnable() {
#Override
public void run() {
updateSeekBar();
}
};
seekBar.post(updater)
}
I am Playing a Audio from Uri Its Working Fine.
Clicking a Button from Each Listview item.
Problem :Audio is Playing in the Listview ,but still Seekbar is not Moving(Updating).
EDIT:1
1.Audio is Playing in the Each Listview Item Perfectly,But Seekbar is Not Working(Not Updating).
Please Help me top solve this Issue.
My Listview Array adapter Class:
Adapter.class
private static final int UPDATE_FREQUENCY = 500;
int progress=0;
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.audio_listview, null, true);
ListenAUdioButton = (Button) rowView.findViewById(R.id.ListenAudiobuttonxml);
seek_bar_view = (SeekBar) rowView.findViewById(R.id.seek_bar);
ListenAUdioButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// text_shown.setText("Playing...");
try {
try {
// get Internet status
isInternetPresent = cd1.isConnectingToInternet();
// check for Internet status
if (isInternetPresent) {
if (!itemname3_AUDIO_FILE[position].equals("") || !itemname3_AUDIO_FILE[position].equals("null")) {
System.out.println(" AUDIO FILE :-)" + itemname3_AUDIO_FILE[position]);
player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(context, Uri.parse(itemname3_AUDIO_FILE[position]));
player.prepareAsync();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
try {
mp.start();
seek_bar_view.setMax(player.getDuration());
updatePosition();
} catch (Exception e) {
e.printStackTrace();
}
}
});
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
stopPlay();
}
});
MediaPlayer.OnErrorListener onError = new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// returning false will call the OnCompletionListener
return false;
}
};
} else {
Toast.makeText(getContext(), "Audio Not Found..!", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getContext(), "Please Check Your Internet Connection..!", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getContext(), "Audio Not Found..!", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
return rowView;
}
private void stopPlay() {
player.stop();
player.reset();
// playButton.setImageResource(android.R.drawable.ic_media_play);
handler.removeCallbacks(updatePositionRunnable);
seek_bar_view.setProgress(0);
// isStarted = false;
}
private final Handler handler = new Handler();
private final Runnable updatePositionRunnable = new Runnable() {
public void run() {
updatePosition();
}
};
private void updatePosition()
{
handler.removeCallbacks(updatePositionRunnable);
seek_bar_view.setProgress(progress);
progress=getProgressPercentage(player.getCurrentPosition(),player.getDuration();
notifyDataSetChanged();
handler.postDelayed(updatePositionRunnable, UPDATE_FREQUENCY);
}
you need to update your seekbar position(value) at every second..
To set seekbar Max value..
seek_bar_view.setMax((int) player.getDuration());
and update it every second to show progress
Handler mHandler = new Handler();
runOnUiThread(new Runnable() {
#Override
public void run() {
seek_bar_view.setProgress((int) player.getCurrentPosition());
}
mHandler.postDelayed(this,1000);
}
);
See this:
seek_bar_view.setProgress(player.getCurrentPosition());
here player.getCurrentPosition() returns the time in millis , you need to convert this to int and then set the progress to seekBar.
Try this:
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();
}
and now get the percentage for your SeekBar like this:
int currentProgress=getProgressPercentage(player.getCurrentPosition(), player.getDuration());
seek_bar_view.setProgress(currentProgress);
Edited:
For your specific case, inside a ListView item:
You will need to notify the adapter each time you change the position of seekbar.
For this, the simplest approach would be to take a variable inside the POJO class you are using to set the adapter.
Inside your POJO class
int progress=0;
In your adapter,set the seekbar progress
seekbar.setProgress(progress);
In your adapter,change the value of progress and notifyadapter
progress=getProgressPercentage(player.getCurrentPosition(), player.getDuration());
notifyDataSetChanged()
//Re-Edited:
seekBar.setOnSeekBarChangeListener(new 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
notifyDataSetChanged();
}
});
I have been stuck with this problem for quite a while now. In the mediaPlayer i've created everything runs smooth in the initial playing stage but when the user selects the next or previous option, the application gives me a (0,-107) error along with the attempt to call getDuration without a valid mediaplayer
The code:
public void playPodCast(int index) {
try {
urlToSend = toGet.get(index).get("URL").toString();
mediaPlayer.reset();
mediaPlayer.setDataSource(urlToSend);
mediaPlayer.prepareAsync();
onPlayerLoad();
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnErrorListener(this);
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
here the onPlayerLoad() is just a method to hide all the views while the mediaPlayer is loading.
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
onPlayerLoaded();
updateProgressBar();
mediaPlayer.start();
}
the onPlayerLoaded() loads back on the view.
public void updateProgressBar() {
seekHandler.postDelayed(updateSeekTime, 100);
}
private Runnable updateSeekTime = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
long totalDuration = mediaPlayer.getDuration();
long currentDuration = mediaPlayer.getCurrentPosition();
// Displaying the total time duration
seekRight.setText("" + utils.milliSecondsToTimer(totalDuration));
// Displaying completed playing time
seekLeft.setText("" + utils.milliSecondsToTimer(currentDuration));
// Updating the SeekBar progress
int progress = (int) (utils.getProgressPercentage(currentDuration,
totalDuration));
seekBar.setProgress(progress);
seekHandler.postDelayed(this, 100);
}
};
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
}
// #Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
seekHandler.removeCallbacks(updateSeekTime);
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
seekHandler.removeCallbacks(updateSeekTime);
int totalDuration = mediaPlayer.getDuration();
int currentPosition = utils.progressToTimer(seekBar.getProgress(),
totalDuration);
// forward or backward to certain seconds
mediaPlayer.seekTo(currentPosition);
// update timer progress again
updateProgressBar();
}
Here, private Handler seekHandler = new Handler();
Like I said before, the initial call to playPodCast(index) does not give me any errors, it works very smoothly. But when the user clicks on the next and previous buttons, the error is generated. The next and previous methods do not give out any errors if implemented without the updateProgressBar(), everything runs unbuggyly. So why am I getting this error ? I have no clue why ... please do help.
Here's the implementation of the next button:
btnNext.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (getPosition == totalList - 1) {
getPosition = 0;
playPodCast(getPosition);
} else {
getPosition = getPosition + 1;
playPodCast(getPosition);
}
}
});
where getPosition is the position of the media file being referenced.
And I also did try
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mediaPlayer.start();
onPlayerLoaded();
updateProgressBar();
}
Update 1:
I found that the error occurs when using the prepareAsync(), the program works fine on prepare() but is super laggy.
The problem is getDuration is getting called by your updateSeekTask while the new media is preparing. This will error. What's the duration of an unprepared video?
The solution is to cancel any callbacks of the updateSeekTask when the user clicks next, and reinstate them once the media is ready.
public void onClick(View arg0) {
if (getPosition == totalList - 1) {
getPosition = 0;
seekHandler.removeCallbacks(updateSeekTime); // Cancel me!
playPodCast(getPosition);
} else {
getPosition = getPosition + 1;
seekHandler.removeCallbacks(updateSeekTime); // Cancel me!
playPodCast(getPosition);
}
}
Then in onPrepared restart the task as you do currently:
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
onPlayerLoaded();
updateProgressBar();
}
You should still use prepareAsync. If you just use prepare everything will wait until the media is prepared. This is the lag you experience. It will fix your problem (since even the task will wait) but it's not recommended.
Instead of calling the following:
int totalDuration = mediaPlayer.getDuration();
inside the Runnable updateSeekTime() make the totalDuration a global variable and refer initialize the value of the totalDuration inside the onPrepared(MediaPlayer mp) like this:
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
onPlayerLoaded();
totalDuration = mp.getDuration() // mp is the MediaPlayer instantiated by this method
updateProgressBar();
mediaPlayer.start();
}
and Presto you are done ... Hope this helps someone.
I have asked this question 2 times now still haven't got it to work. Any help would be awesome
My ProgressBar does not reset after audio is done, the bar just stays to the max blue line. I ask a question before on this and got it working but now just stopped working and not sure why it doesn't. Any help would be awesome.
All I want is it to chose a audio at random then play one and when finished you can press play again to listen to the same audio it chose at random.
Heres code:
public class player2 extends Activity implements Runnable {
private MediaPlayer mp;
private ProgressBar progressBar;
private ImageButton pauseicon;
private final int NUM_SOUND_FILES = 3; //*****REPLACE THIS WITH THE ACTUAL NUMBER OF SOUND FILES YOU HAVE*****
private int mfile[] = new int[NUM_SOUND_FILES];
private Random rnd = new Random();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.player_2);
pauseicon = (ImageButton) findViewById(R.id.pauseicon);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
getActionBar().setDisplayHomeAsUpEnabled(true);
mfile[0] = R.raw.sound04; //****REPLACE THESE WITH THE PROPER NAMES OF YOUR SOUND FILES
mfile[1] = R.raw.sound05; //PLACE THE SOUND FILES IN THE /res/raw/ FOLDER IN YOUR PROJECT*****
mfile[2] = R.raw.sound06;
// Listeners
/**
* Play button click event
* plays a song and changes button to pause image
* pauses a song and changes button to play image
* */
try{
mp = MediaPlayer.create(player2.this, mfile[rnd.nextInt(NUM_SOUND_FILES)]);
mp.seekTo(0);
mp.start(); ;
progressBar.setVisibility(ProgressBar.VISIBLE);
progressBar.setProgress(0);
progressBar.setMax(100);
new Thread(this).start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
pauseicon.setImageResource(R.drawable.playicon);
}
});
pauseicon.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
// No need to check if it is pauseicon
if(mp.isPlaying()){
mp.pause();
((ImageButton) v).setImageResource(R.drawable.playicon);
} else {
mp.start();
((ImageButton) v).setImageResource(R.drawable.pauseicon);
}}});
}
public void run() {
int currentPosition= 0;
int total = mp.getDuration();
while (mp!=null && currentPosition<=total) {
try {
Thread.sleep(1000);
currentPosition= mp.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
progressBar.setProgress(currentPosition);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
NavUtils.navigateUpFromSameTask(this);
if (mp != null)
if(mp.isPlaying())
mp.stop();
mp.release();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onBackPressed(){
if (mp != null){
if(mp.isPlaying())
mp.stop();
mp.release();
}
//there is no reason to call super.finish(); here
//call super.onBackPressed(); and it will finish that activity for you
super.onBackPressed();
}
}
I did not check all the code thoroughly, but at a quick glance I would guess that your thread (which updates the progress bar) is stopping at completion and you never start it again (ie. when the user clicks play again). Just try restarting the thread in your pauseicon.setOnClickListener (when playback is complete). Example:
pauseicon.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(mp.isPlaying()) {
mp.pause();
((ImageButton) v).setImageResource(R.drawable.playicon);
} else {
mp.start();
((ImageButton) v).setImageResource(R.drawable.pauseicon);
// RESTART THE UPDATE THREAD //
new Thread(this).start();
}
}
});
EDIT using a static variable to store thread so that it can be restarted from the view's onClick method:
// add this to your class as a member
static Thread progressThread = new Thread(this);
// add this to BOTH onCreate and onClick
progressThread.start();
If this does not work (I can't test it out right now), you can simply keep the thread running, for example:
// flag to set when thread should be actively running
static boolean runThread = true;
// change your run method to something as follows
public void run() {
while ( runThread ) {
if ( mp != null && currentPosition <= total ) {
int currentPosition= 0;
int total = mp.getDuration();
try {
Thread.sleep(1000);
currentPosition= mp.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
progressBar.setProgress(currentPosition);
}
else
Thread.sleep(1000);
}
}
// then when you no longer need to update the progress bar set the flag to false,
// which will cause your thread to finish. this can go anywhere, depending on
// your needs
runThread = false;
I have a simple player and recorder. Everything works great but have one problem. I want to add seek bar to see progress in playing record and use this seek bar to set the place from the player should play. I have onProgress but with no effect. This is the code:
package com.example.recorder;
import java.io.IOException;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class MainActivity extends Activity implements OnSeekBarChangeListener
{
private static final String LOG_TAG = "AudioRecordTest";
private static String mFileName = null;
private SeekBar seekBar;
private MediaRecorder mRecorder = null;
private Button startRecord, startPlaying, stopPlaying;
private MediaPlayer mPlayer = null;
private void onRecord(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void startPlaying() {
if(mPlayer != null && mPlayer.isPlaying()){
mPlayer.pause();
} else if(mPlayer != null){
mPlayer.start();
}else{
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
}
}
private void stopPlaying() {
mPlayer.release();
mPlayer = null;
startPlaying.setText("Start playing");
}
private void pausePlaying(){
if(mPlayer.isPlaying()){
mPlayer.pause();
} else {
mPlayer.start();
}
}
private void startRecording() {
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() failed");
}
mRecorder.start();
}
private void stopRecording() {
mRecorder.stop();
mRecorder.release();
mRecorder = null;
}
public MainActivity() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_main);
startPlaying = (Button) findViewById(R.id.buttonStartPlay);
stopPlaying = (Button) findViewById(R.id.buttonStopPlaying);
startRecord = (Button) findViewById(R.id.buttonStartRecord);
seekBar = (SeekBar) findViewById(R.id.seekBar);
startRecord.setOnClickListener(new OnClickListener() {
boolean mStartRecording = true;
#Override
public void onClick(View v) {
onRecord(mStartRecording);
if (mStartRecording) {
startRecord.setText("Stop recording");
} else {
startRecord.setText("Start recording");
}
mStartRecording = !mStartRecording;
}
});
startPlaying.setOnClickListener(new OnClickListener() {
boolean mStartPlaying = true;
#Override
public void onClick(View v) {
//onPlay(mStartPlaying);
startPlaying();
if (mStartPlaying) {
startPlaying.setText("Stop playing");
} else {
startPlaying.setText("Start playing");
}
mStartPlaying = !mStartPlaying;
}
});
stopPlaying.setOnClickListener(new OnClickListener() {
boolean mStartPlaying = true;
#Override
public void onClick(View v) {
stopPlaying();
}
});
}
#Override
public void onPause() {
super.onPause();
if (mRecorder != null) {
mRecorder.release();
mRecorder = null;
}
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(fromUser){
mPlayer.seekTo(progress);
seekBar.setProgress(progress);
}
else{
// the event was fired from code and you shouldn't call player.seekTo()
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
Any ideas on how to use seek bar to see progress and set place from the record should play?
To create a 'connection' between SeekBar and MediaPlayer you need first to get your current recording max duration and set it to your seek bar.
mSeekBar.setMax(mFileDuration/1000); // where mFileDuration is mMediaPlayer.getDuration();
After you initialise your MediaPlayer and for example press play button, you should create handler and post runnable so you can update your SeekBar (in the UI thread itself) with the current position of your MediaPlayer like this :
private Handler mHandler = new Handler();
//Make sure you update Seekbar on UI thread
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(mMediaPlayer != null){
int mCurrentPosition = mMediaPlayer.getCurrentPosition() / 1000;
mSeekBar.setProgress(mCurrentPosition);
}
mHandler.postDelayed(this, 1000);
}
});
and update that value every second.
If you need to update the MediaPlayer's position while user drag your SeekBar you should add OnSeekBarChangeListener to your SeekBar and do it there :
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(mMediaPlayer != null && fromUser){
mMediaPlayer.seekTo(progress * 1000);
}
}
});
And that should do the trick! : )
EDIT:
One thing which I've noticed in your code, don't do :
public MainActivity() {
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
}
make all initialisations in your onCreate(); , do not create constructors of your Activity.
I've used this tutorial with success, it's really simple to understand:
www.androidhive.info/2012/03/android-building-audio-player-tutorial/
This is the interesting part:
/**
* 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();
}
After you initialize your MediaPlayer and SeekBar, you can do this :
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
mSeekBar.setProgress(mMediaPlayer.getCurrentPosition());
}
},0,1000);
This updates SeekBar every second(1000ms)
And for updating MediaPlayer, if user drag SeekBar, you must add OnSeekBarChangeListener to your SeekBar :
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
mMediaPlayer.seekTo(i);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
HAPPY CODING!!!
Code in Kotlin:
var updateSongTime = object : Runnable {
override fun run() {
val getCurrent = mediaPlayer?.currentPosition
startTimeText?.setText(String.format("%d:%d",
TimeUnit.MILLISECONDS.toMinutes(getCurrent?.toLong() as Long),
TimeUnit.MILLISECONDS.toSeconds(getCurrent?.toLong()) -
TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(getCurrent?.toLong()))))
seekBar?.setProgress(getCurrent?.toInt() as Int)
Handler().postDelayed(this, 1000)
}
}
For changing media player audio file every second
If user drags the seek bar then following code snippet can be use
Statified.seekBar?.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
if(b && Statified.mediaPlayer != null){
Statified.mediaPlayer?.seekTo(i)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
check this, you should give arguments in msecs, Dont just send progress to seekTo(int)
and also check this getCurrentPostion() and getDuration().
You can do some calcuations, ie., convert progress in msec like msce = (progress/100)*getDuration() then do seekTo(msec)
Or else i have an easy idea, you don't need to change any code anywer else just add seekBar.setMax(mPlayer.getDuration()) once your media player is prepared.
and here is link exactly what you want seek bar update
The below code worked for me.
I've created a method for seekbar
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mp.start();
getDurationTimer();
getSeekBarStatus();
}
//Creating duration time method
public void getDurationTimer(){
final long minutes=(mSongDuration/1000)/60;
final int seconds= (int) ((mSongDuration/1000)%60);
SongMaxLength.setText(minutes+ ":"+seconds);
}
//creating a method for seekBar progress
public void getSeekBarStatus(){
new Thread(new Runnable() {
#Override
public void run() {
// mp is your MediaPlayer
// progress is your ProgressBar
int currentPosition = 0;
int total = mp.getDuration();
seekBar.setMax(total);
while (mp != null && currentPosition < total) {
try {
Thread.sleep(1000);
currentPosition = mp.getCurrentPosition();
} catch (InterruptedException e) {
return;
}
seekBar.setProgress(currentPosition);
}
}
}).start();
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int progress=0;
#Override
public void onProgressChanged(final SeekBar seekBar, int ProgressValue, boolean fromUser) {
if (fromUser) {
mp.seekTo(ProgressValue);//if user drags the seekbar, it gets the position and updates in textView.
}
final long mMinutes=(ProgressValue/1000)/60;//converting into minutes
final int mSeconds=((ProgressValue/1000)%60);//converting into seconds
SongProgress.setText(mMinutes+":"+mSeconds);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
SongProgress and SongMaxLength are the TextView to show song duration and song length.
My code snippet:
public class PlayerActivity extends AppCompatActivity {
private static final String TAG = "PlayerActivity";
private ActivityPlayerBinding binding;
private MediaPlayer mediaPlayer;
private boolean playingAudio = false;
Runnable runnable;
Handler handler;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityPlayerBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
);
try {
mediaPlayer.setDataSource(songUrl);
mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.setOnPreparedListener(mp -> {
binding.playBtn.setBackground(getDrawable(R.drawable.ic_pause));
binding.seekbarPlayer.setMax(mp.getDuration());
mediaPlayer.start();
playingAudio = true;
updateSeekbar();
});
mediaPlayer.setOnBufferingUpdateListener((mp, percent) -> {
double ratio = percent / 100.0;
int bufferingLevel = (int) (mp.getDuration() * ratio);
binding.seekbarPlayer.setSecondaryProgress(bufferingLevel);
});
binding.seekbarPlayer.setOnSeekBarChangeListener(seekBarChangeListener);
}
private SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
mediaPlayer.seekTo(progress);
seekBar.setProgress(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private void updateSeekbar() {
try {
if (mediaPlayer != null) {
int currentPos = mediaPlayer.getCurrentPosition();
binding.seekbarPlayer.setProgress(currentPos);
runnable = this::updateSeekbar;
handler.postDelayed(runnable, 1000);
}
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "updateSeekbar: " + e.getMessage());
}
}
}
int pos = 0;
yourSeekBar.setMax(mPlayer.getDuration());
After You start Your MediaPlayer i.e mplayer.start()
Try this code
while(mPlayer!=null){
try {
Thread.sleep(1000);
pos = mPlayer.getCurrentPosition();
} catch (Exception e) {
//show exception in LogCat
}
yourSeekBar.setProgress(pos);
}
Before you added this code you have to create xml resource for SeekBar and use it in Your Activity class of ur onCreate() method.
This works for me:
seekbarPlayer.setMax(mp.getDuration());
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if(mp != null){
seekbarPlayer.setProgress(mp.getCurrentPosition());
}
mHandler.postDelayed(this, 1000);
}
});
Given the answer hardartcore that worked for me with a small change and did not work before the change:
private Handler mHandler = new Handler();
MusicPlayer.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(player != null){
int mCurrentPosition = player.getCurrentPosition();//clear ' /1000 '
seekBar.setProgress(mCurrentPosition);
}
mHandler.postDelayed(this, 1000);
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(player != null && fromUser){
player.seekTo(progress); // clear ' * 1000 '
}
}
});
To add on to #hardartcore's answer.
Instead of calling postDelayed on a Handler, the best approach would be to get callbacks from the MediaPlayer during play-back and then accordingly update the seekBar with the progress.
Also, pause your MediaPlayer at onStartTrackingTouch(SeekBar seekBar) of the OnSeekBarChangeListener and then re-start it on onStopTrackingTouch(SeekBar seekBar).
Based on previous statements, for better performance, you can also add an if condition
if (player.isPlaying() {
handler.postDelayed(..., 1000);
}
Try this Code:
public class MainActivity extends AppCompatActivity {
MediaPlayer mplayer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//You create MediaPlayer variable ==> set the path and start the audio.
mplayer = MediaPlayer.create(this, R.raw.example);
mplayer.start();
//Find the seek bar by Id (which you have to create in layout)
// Set seekBar max with length of audio
// You need a Timer variable to set progress with position of audio
final SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar);
seekBar.setMax(mplayer.getDuration());
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
seekBar.setProgress(mplayer.getCurrentPosition());
}
}, 0, 1000);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// Update the progress depending on seek bar
mplayer.seekTo(progress);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}