SeekBar is not updating music is playing but the seekBar stay idle - android

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)
}

Related

Recyclerview scrolling when play audio with mediaplayer

I am developing a chat app, this application has the ability to send voice to chat
The sound is played correctly, but the problem
When I click on the play button, recyclerview scroll to top:
private void playVoice(Message message, final ImageView playBtn, final SeekBar seekBar, final CfTextView timer) {
isCurrentMediaPlayer = !isCurrentMediaPlayer;
if (isCurrentMediaPlayer) {
try {
if (mediaPlayer != null) {
playBtn.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_play, null));
seekBar.setProgress(0);
mediaPlayer.stop();
timerClass.purge();
timerClass.cancel();
}
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(message.getVoice().getUrl());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
if (mp.isPlaying()) {
mp.pause();
playBtn.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_play, null));
} else {
mp.start();
playBtn.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_pause, null));
}
timer.setText(formatDuration(0));
seekBar.setMax(mediaPlayer.getDuration());
if (mediaPlayer != null) {
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
mediaPlayer.seekTo(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
timerClass = new Timer();
timerClass.schedule(new MainTimer(timer, seekBar), 0, 1000);
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
//mediaPlayer = null;
//mp.release();
timerClass.purge();
timerClass.cancel();
playBtn.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.ic_play, null));
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class MainTimer extends TimerTask {
private CfTextView timer;
private SeekBar seekBar;
private MainTimer(CfTextView timer, SeekBar seekBar) {
this.timer = timer;
this.seekBar = seekBar;
}
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
seekBar.setProgress(mediaPlayer.getCurrentPosition());
timer.setText(formatDuration(mediaPlayer.getCurrentPosition()));
}
});
}
}
When you click on any play button, the following code runs:
CustomIncomingVoiceMessageViewHolder.Payload payload = new CustomIncomingVoiceMessageViewHolder.Payload();
payload.onPlayButtonClickListener = new CustomIncomingVoiceMessageViewHolder.onPlayButtonClickListener() {
#Override
public void onPlayButtonClick(Message message, final ImageView imageView, final CfTextView timer, final CfTextView time, final SeekBar seekBar) {
//isCurrentMediaPlayer = !isCurrentMediaPlayer;
playVoice(message, imageView, seekBar, timer);
}
};
my view holder code:
public class CustomIncomingVoiceMessageViewHolder extends MessageHolders.IncomingTextMessageViewHolder<Message> {
private ImageView playButton;
private SeekBar seekBar;
private CfTextView timer;
private CfTextView time;
public CustomIncomingVoiceMessageViewHolder(View itemView, Object payload) {
super(itemView, payload);
playButton = itemView.findViewById(R.id.playButton);
seekBar = itemView.findViewById(R.id.seekBar);
timer = itemView.findViewById(R.id.timerVoice);
time = itemView.findViewById(R.id.timeVoice);
}
#Override
public void onBind(final Message message) {
super.onBind(message);
final Payload payload = (Payload) this.payload;
playButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (payload != null && payload.onPlayButtonClickListener != null) {
payload.onPlayButtonClickListener.onPlayButtonClick(message, playButton, timer, time,seekBar);
}
}
});
}
public static class Payload {
public onPlayButtonClickListener onPlayButtonClickListener;
}
public interface onPlayButtonClickListener {
void onPlayButtonClick(Message message, ImageView imageView, CfTextView timer, CfTextView time,SeekBar seekBar);
}
}
i'm using library chatKit
enter image description here
The problem may be due to your layout where you have your "CfTextView timer." I had the same issue and fixed it by setting my Textview width property as follows:
<TextView
android:layout_width="match_parent" //This is what I changed
android:layout_height="wrap_content"/>
<SeekBar
android:layout_width="match_parent" //Check this as well
android:layout_height="wrap_content"/>
I can see that in your runnable you have this:
seekBar.setProgress(mediaPlayer.getCurrentPosition());
timer.setText(formatDuration(mediaPlayer.getCurrentPosition()));
Here you update the text of your timer to match the mediaPlayer's current position, so if you have the width of your textview to wrap_content it causes your Recyclerview to resize itself.
Try to apply these changes to your layout and see if it solves the scrolling issues.
Best of luck!

Audio Playing from URI Inside Listview , But Seekbar is not Updating in Android Listview item

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();
}
});

Can't pass an int from button if / else case to media player

how are you supposed to let the mediaplayer know what it is supposed to play?
wholeTextPlayer = MediaPlayer.create(Lesson1Reading.this, engAu);
It works fine if I declare the file in the top:
MediaPlayer wholeTextPlayer;
private int engAu = R.raw.l1r_en_l10;
Button btn_default_acc_whole;
It doesn't work from within a button click if / else statement wherever I try to put it with the following combination:
MediaPlayer wholeTextPlayer;
private int engAu;
Button btn_default_acc_whole;
The button click:
final Button btn_default_acc_whole = (Button) findViewById(R.id.btn_default_acc_whole);
btn_default_acc_whole.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
if (wholeTextPlayer.isPlaying()) {
wholeTextPlayer.pause();
} else {
wholeTextPlayer.start();
startPlayProgressUpdater();
}
setEngAu(R.raw.l1r_en_l10); //this line doesn't want to fit anywhere
}
});
The setter:
public void setEngAu(int engAu) {
this.engAu = engAu;
}
Of course they are separately placed in the activity, I just copied and pasted the relevant bits from it.
Thanks guys.
Here is the whole code:
'public class Lesson1Grammar extends Activity {
private SeekBar seekBar;
MediaPlayer wholeTextPlayer;
private int engAu;
private final Handler handler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lesson1grammar);
WholeDefAccPlayer();
final RelativeLayout playerScreen = (RelativeLayout)findViewById(R.id.playerScreen);
final ImageButton btn_player_screen = (ImageButton) findViewById(R.id.btn_player_screen);
btn_player_screen.setOnClickListener(new View.OnClickListener() {
//this hides/unhides the part of the layout in which the player is
#Override
public void onClick(View arg0) {
if (playerScreen.isShown()) {
playerScreen.setVisibility(View.GONE);
} else {
playerScreen.setVisibility(View.VISIBLE);
}
}
});
final Button btn_default_acc_whole = (Button) findViewById(R.id.btn_default_acc_whole);
btn_default_acc_whole.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
if (wholeTextPlayer.isPlaying()) {
wholeTextPlayer.pause();
} else {
setEngAu(R.raw.default_acc_audio);
wholeTextPlayer.start();
startPlayProgressUpdater();
}
}
});
}
public void setEngAu(int engAu) {
this.engAu = engAu;
}
private void WholeDefAccPlayer() {
wholeTextPlayer = MediaPlayer.create(Lesson1Grammar.this, engAu);
((TextView) findViewById(R.id.getTitleOfAccent)).setText(R.string.btn_lesson1reading);
seekBar = (SeekBar) findViewById(R.id.seekBar);
seekBar.setMax(wholeTextPlayer.getDuration());
seekBar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
seekChange(v);
return false;
}
});
}
public void startPlayProgressUpdater() {
seekBar.setProgress(wholeTextPlayer.getCurrentPosition());
if (wholeTextPlayer.isPlaying()) {
Runnable notification = new Runnable() {
public void run() {
startPlayProgressUpdater();
}
};
handler.postDelayed(notification, 1000);
}
else wholeTextPlayer.pause();
}
// This is event handler thumb moving event
private void seekChange(View v){
if(wholeTextPlayer.isPlaying()){
SeekBar sb = (SeekBar)v;
wholeTextPlayer.seekTo(sb.getProgress());
}
}
}
'
if your plan is to make the method setEngAu() is the controller as you mentioned in the comment. then you you need to use that method like this
public void setEngAu(int enAu)
{
this.EngAu = enAu;
wholeTextPlayer.setDataSource(engAu);
wholeTextPlayer.prepare();
}
you need to implement onPrepared listener from the media player
I do not know your classes but I assume where you say something like;
wholeTextPlayer = new MediaPlayer();
wholeTextPlayer.setOnPreparedListener(this);
here you start the player after it became prepared
public void onPrepared(MediaPlayer player)
{
player.start();
}
Remember to you will need to call wholeTextPlayer.release() if you do not want the player to hold on that resource anymore( think of it as memory issues - recommended if you check the documentation)
EDIT :
I adjusted your code a little, please take a look and let me know.
private SeekBar seekBar;
MediaPlayer wholeTextPlayer;
private int engAu;
final Handler handler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.lesson1grammar);
WholeDefAccPlayer();
final RelativeLayout playerScreen = (RelativeLayout) findViewById(R.id.playerScreen);
final ImageButton btn_player_screen = (ImageButton) findViewById(R.id.btn_player_screen);
btn_player_screen.setOnClickListener(new View.OnClickListener()
{
//this hides/unhides the part of the layout in which the player is
#Override
public void onClick(View arg0)
{
if(playerScreen.isShown())
{
playerScreen.setVisibility(View.GONE);
}
else
{
playerScreen.setVisibility(View.VISIBLE);
}
}
});
final Button btn_default_acc_whole = (Button) findViewById(R.id.btn_default_acc_whole);
btn_default_acc_whole.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{//problem here is
if(playerState == PlayerState_Playing)
{
wholeTextPlayer.pause();
setPlayerState(PlayerState_Paused);
}
else if(playerState == PlayerState_Paused)
{
wholeTextPlayer.start();
setPlayerState(PlayerState_Playing);
}
else
{
setEngAu(R.raw.default_acc_audio);
wholeTextPlayer.start();
startPlayProgressUpdater();
setPlayerState(PlayerState_Playing);
}
}
});
}
public void setEngAu(int engAu)
{
this.engAu = engAu;
if(wholeTextPlayer !=null)
{//just in case you call this method and player was not initialized yet
wholeTextPlayer.release();
}
setPlayerState(PlayerState_Preparing);
wholeTextPlayer = MediaPlayer.create(this, engAu);
}
private void WholeDefAccPlayer()
{
//this line probably will fail because engAu is not really initialized yet, unless you have default value for it
wholeTextPlayer = MediaPlayer.create(this, engAu);
((TextView) findViewById(R.id.getTitleOfAccent)).setText(R.string.btn_lesson1reading);
seekBar = (SeekBar) findViewById(R.id.seekBar);
//you can not call getDuration unless the player is prepared, so this might crash you
// seekBar.setMax(wholeTextPlayer.getDuration());
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b)
{
if(playerState != PlayerState_Preparing)
{//if player state is preparing it means we can not seek yet, player.start() must be called first
wholeTextPlayer.seekTo(i);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar)
{
}
#Override
public void onStopTrackingTouch(SeekBar seekBar)
{
}
});
}
public void startPlayProgressUpdater()
{
if(seekBar.getMax() != wholeTextPlayer.getDuration())
{//in case you change track later, this will check if the seek bar max value with track duration.
// if they are not the same, then it will adjust it for you
seekBar.setMax(wholeTextPlayer.getDuration());
}
seekBar.setProgress(wholeTextPlayer.getCurrentPosition());
if(wholeTextPlayer.isPlaying())
{
Runnable notification = new Runnable()
{
public void run()
{
startPlayProgressUpdater();
}
};
handler.postDelayed(notification, 1000);
}
else wholeTextPlayer.pause();
}
// This is event handler thumb moving event
private void seekChange(View v)
{
if(wholeTextPlayer.isPlaying())
{
SeekBar sb = (SeekBar) v;
wholeTextPlayer.seekTo(sb.getProgress());
}
}
private final int PlayerState_Preparing = 0;
private final int PlayerState_Playing = 1;
private final int PlayerState_Paused = 2;
private int playerState;
private void setPlayerState(int state)
{//this is used to track the player state, because wholeTextPlayer.isPlaying() can return false in many conditions ( too general )
//you can check in the media player documentation to know more details about this
playerState = state;
}

Android: SeekBar is not updated using a Handler on 4.1.2 Device

friends I am developing an application which is playing small mp3 soundtracks (podcasts). Now my code which I am showing below is working on Android 3.2 as it should. But on Android 4.1.2 the SeekBar is not being updated by the handler instance. I have read about a bug in the SeekBar causing this issue but it should be fixed since Android 3.2. Any help or advice would be appreciated. Here is my code:
public class PodcastDetailFragment extends BaseFragment {
private MediaPlayer mediaPlayer = null;
private Button playPauseButton = null;
private SeekBar seekBar = null;
private TextView timeView = null;
private int totalDuration = 0;
private Bundle data;
private Handler handler=new Handler();
private Runnable runnable = new Runnable() {
public void run() {
int progress = mediaPlayer.getCurrentPosition();
seekBar.setProgress(progress);
int hours = ((progress/1000)/60)/60;
int minutes = ((progress/1000)/60)%60;
int seconds = ((progress/1000)%60)%60;
String hoursString = (hours<10)?"0":"";
String minutesString = (minutes<10)?"0":"";
String secondsString = (seconds<10)?"0":"";
timeView.setText(hoursString+hours+":"+minutesString+minutes+":"+secondsString+seconds);
handler.postDelayed(this, 100);
}
};
public static PodcastDetailFragment newInstance(Bundle bundle) {
PodcastDetailFragment f = new PodcastDetailFragment();
f.setArguments(bundle);
return f;
}
/**
* When creating, retrieve this instance's number from its arguments.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
data = getArguments();
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
getView().findViewById(R.id.preparing_track_progress_bar).setVisibility(View.VISIBLE);
super.onActivityCreated(savedInstanceState);
}
#Override
public void onPause() {
super.onPause();
if (mediaPlayer != null) {
LogUtils.d("Podcast MediaPlayer", "stop() inside the onPause() was called");
mediaPlayer.stop();
}
}
#Override
public void onDestroy() {
LogUtils.d("Podcast MediaPlayer", "release() was called");
mediaPlayer.release();
super.onDestroy();
}
/**
* The Fragment's UI is just a simple text view showing its instance number.
*/
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.podcasts_details, container, false);
TextView dv = (TextView) v.findViewById(R.id.durationView);
dv.setText(data.getString("duration"));
timeView = (TextView) v.findViewById(R.id.timeView);
timeView.setText("00:00:00");
playPauseButton = (Button) v.findViewById(R.id.playPauseButtonView);
playPauseButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
playPauseButton.setText(getResources().getString(
R.string.play));
} else {
mediaPlayer.start();
playPauseButton.setText(getResources().getString(
R.string.pause));
}
}
});
seekBar = (SeekBar) v.findViewById(R.id.seekBarView);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onStopTrackingTouch(SeekBar seekBar) {
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (fromUser) {
mediaPlayer.seekTo(progress);
}
}
});
mediaPlayer =new MediaPlayer();
mediaPlayer
.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
totalDuration = mp.getDuration();
seekBar.setMax(totalDuration);
playPauseButton.setEnabled(true);
try{
getView().findViewById(R.id.preparing_track_progress_bar).setVisibility(View.INVISIBLE);
}catch(Exception ex){
ex.printStackTrace();
}
handler.postDelayed(runnable, 100);
}
});
mediaPlayer.setDataSource(Uri.parse(data.getString("podcast_url")).toString());
playPauseButton.setEnabled(false);
mediaPlayer.prepareAsync();
return v;
}
}
You should either use an AsyncTask or a Service (in case the music will play in background) instead of a Worker Thread with a Handler. The AsyncTask is extremely useful with it's onProgressUpdate method, you can use it to update the Bar based on the progress of the audio file.
Here's a basic example of an AsyncTask and how you should use it:
private class TestAsyncTask extends AsyncTask<Void, Integer, Void> {
#Override
protected Void doInBackground(Void... arg0) {
for(int i=0; i<songDuration; i++){
doSomething();
publishProgress(i);
}
return null;
}
#Override
protected void onProgressUpdate(Integer... progress) {
//UPDATE BAR
}
#Override
protected void onPostExecute(Void result) {
//DO SOMETHING WHEN FINISHED PLAYING
}
}
Anyway, here's the official doc: http://developer.android.com/reference/android/os/AsyncTask.html
I have solved this problem. The SeekBar was ok. It was just the issue that the lenght of a track is only given when you download the whole track. So to show the progress on a SeekBar properly you need to know the length of a track. So you take the length of a track and then call seekBar.setMax(lenghtOfTrack) and the progress is updated as it should by the method setProgress(progress).

SeekBar and media player in android

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) {
}
});
}

Categories

Resources