I created my own player layout and used Youtube api to show the video content, however when the video starts, my seekbar doesn't update and remains fix. I think that the problem is inside mSeekBarChangeListener but i'm not sure.
Here's my code:
public class ItemDetails extends YouTubeBaseActivity implements YouTubePlayer.OnInitializedListener,View.OnClickListener {
private final static String TAG = "ItemDetails";
#BindView(R.id.item_title)TextView itemTitle;
#BindView(R.id.item_date)TextView itemDate;
#BindView(R.id.item_plot)TextView itemPlot;
#BindView(R.id.item_short_description)TextView itemShortDescription;
#BindView(R.id.backdop_image_details)ImageView imageBackdrop;
#BindView(R.id.tv_more)TextView tvSeeMore;
#BindView(R.id.trailer_video)YouTubePlayerView traileVideo;
#BindView(R.id.video_control)LinearLayout videoControlLayout;
#BindView(R.id.play_time)TextView mPlayTimeTextView;
#BindView(R.id.video_seekbar)SeekBar mSeekBar;
YouTubePlayer mPlayer;
private Handler mHandler = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_details);
ButterKnife.bind(this);
findViewById(R.id.play_video).setOnClickListener(this);
findViewById(R.id.pause_video).setOnClickListener(this);
mSeekBar.setMax(100);
mSeekBar.setProgress(0);
mSeekBar.setOnSeekBarChangeListener(mVideoSeekBarChangeListener);
mHandler = new Handler();
}
#OnClick(R.id.back_arrow_detail)void backArrowClick() {
onBackPressed();
}
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean b) {
if(youTubePlayer != null) {
mPlayer = youTubePlayer;
displayCurrentTime();
// start buffering
if(!b) {
youTubePlayer.cueVideo(trailerKey);
}
// set style and show control layout
youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.CHROMELESS);
videoControlLayout.setVisibility(View.VISIBLE);
youTubePlayer.setPlayerStateChangeListener(playerStateChangeListener);
youTubePlayer.setPlaybackEventListener(playbackEventListener);
}
}
private YouTubePlayer.PlaybackEventListener playbackEventListener = new YouTubePlayer.PlaybackEventListener() {
#Override
public void onPlaying() {
mHandler.postDelayed(runnable,100);
displayCurrentTime();
}
#Override
public void onPaused() {
mHandler.removeCallbacks(runnable);
}
#Override
public void onStopped() {
mHandler.removeCallbacks(runnable);
}
#Override
public void onBuffering(boolean b) {
}
#Override
public void onSeekTo(int i) {
mHandler.postDelayed(runnable,100);
}
};
private YouTubePlayer.PlayerStateChangeListener playerStateChangeListener = new YouTubePlayer.PlayerStateChangeListener() {
#Override
public void onLoading() {
}
#Override
public void onLoaded(String s) {
}
#Override
public void onAdStarted() {
}
#Override
public void onVideoStarted() {
displayCurrentTime();
}
#Override
public void onVideoEnded() {
}
#Override
public void onError(YouTubePlayer.ErrorReason errorReason) {
}
};
#Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
Log.d(TAG,youTubeInitializationResult.toString());
}
SeekBar.OnSeekBarChangeListener mVideoSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
long lengthPlayed = (mPlayer.getDurationMillis() * progress) / 100;
mPlayer.seekToMillis((int) lengthPlayed);
seekBar.setProgress(progress);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.play_video:
if(mPlayer != null && !mPlayer.isPlaying()) {
mPlayer.play();
}
break;
case R.id.pause_video:
if(mPlayer != null && mPlayer.isPlaying()) {
mPlayer.pause();;
}
break;
}
}
private void displayCurrentTime() {
if (null == mPlayer) return;
String formattedTime = formatTime(mPlayer.getDurationMillis() - mPlayer.getCurrentTimeMillis());
mPlayTimeTextView.setText(formattedTime);
}
private String formatTime(int millis) {
int seconds = millis / 1000;
int minutes = seconds / 60;
int hours = minutes / 60;
return (hours == 0 ? "--:" : hours + ":") + String.format("%02d:%02d", minutes % 60, seconds % 60);
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
displayCurrentTime();
mHandler.postDelayed(this, 100);
}
};
}
For all who are looking for a solution:
Set the seekbar progress in within the runnable:
private Runnable runnable = new Runnable() {
#Override
public void run() {
displayCurrentTime();
//Progress in percentage
int progress = mPlayer.getCurrentTimeMillis() * 100 / mPlayer.getDurationMillis();
mSeekBar.setProgress(progress);
mHandler.postDelayed(this, 100);
}
};
Since this will start the OnSeekBarChangeListener, you need to add an additional if:
SeekBar.OnSeekBarChangeListener mVideoSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//Only when the user change the progress
if(fromUser){
long lengthPlayed = (mPlayer.getDurationMillis() * progress) / 100;
mPlayer.seekToMillis((int) lengthPlayed);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
;)
Custom youtube player CHROMELESS style - set SeekBar Progress and Seek Bar TrackingTouch Forward/backward
mSeekBar = (SeekBar) findViewById(R.id.video_seekbar);
mSeekBar.setOnSeekBarChangeListener(mVideoSeekBarChangeListener)
SeekBar.OnSeekBarChangeListener mVideoSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
long lengthPlayed = (mYouTubePlayer.getDurationMillis() * seekBar.getProgress()) / 100;
mYouTubePlayer.seekToMillis((int) lengthPlayed);
}
};
private Runnable runnable = new Runnable() {
#Override
public void run(){
displayCurrentTime();
mHandler.postDelayed(this, 100);
}
};
private void displayCurrentTime() {
if (null == mYouTubePlayer) return;
String formattedTime = formatTime(mYouTubePlayer.getDurationMillis() - mYouTubePlayer.getCurrentTimeMillis());
play_timetv.setText(formattedTime);
playPercent = (int) (((float) mYouTubePlayer.getCurrentTimeMillis()/(float) mYouTubePlayer.getDurationMillis()) * 100);
System.out.println("get youtube displayTime 2 : "+playPercent);
// update live progress
mSeekBar.setProgress(playPercent, true);
}
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've implemented a youtube player (fragment) in my android project. I'm tryin' to play the video in chromeless player style, while implementing player control on my own. Play and pause buttons are working fine, however seekbar isn't moving as the video is progressing. Though, I'm able to skip video through it (play video ahead), but the seekbar isn't moving on it's own. Where did I go wrong?
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean b) {
if (!b) {
YPlayer = youTubePlayer;
displayCurrentTime(); // It displays current progress of video in --:-- format. It's working fine...
YPlayer.loadVideo(id); // id -> YouTube video id
YPlayer.play();
YPlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.CHROMELESS);
YPlayer.setPlayerStateChangeListener(new YouTubePlayer.PlayerStateChangeListener() {
#Override
public void onLoading() {
}
#Override
public void onLoaded(String s) {
}
#Override
public void onAdStarted() {
}
#Override
public void onVideoStarted() {
seekBar.setMax(YPlayer.getDurationMillis()/1000);
}
#Override
public void onVideoEnded() {
}
#Override
public void onError(YouTubePlayer.ErrorReason errorReason) {
}
});
YPlayer.setPlaybackEventListener(new YouTubePlayer.PlaybackEventListener() {
#Override
public void onPlaying() {
handler.postDelayed(runnable, 100); //Handler's instance initialized as instance variable
displayCurrentTime();
}
#Override
public void onPaused() {
handler.removeCallbacks(runnable);
}
#Override
public void onStopped() {
}
#Override
public void onBuffering(boolean b) {
handler.postDelayed(runnable, 1000);
}
#Override
public void onSeekTo(int i) {
handler.removeCallbacks(runnable);
}
});
playerControl.setVisibility(View.VISIBLE); //Layout with play (and pause) button, Seekbar (which isn't moving along with the video), and timer (string being returned by the above displayCurrentTime() method)
}
}
#Override
public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
long lengthPlayed = (YPlayer.getDurationMillis() * progress) / 100;
YPlayer.seekToMillis((int) lengthPlayed);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
runOnUiThread(new Runnable() {
#Override
public void run() {
while(YPlayer != null && seekBar.getMax() > YPlayer.getCurrentTimeMillis())
{
int videoProgressed = 0;
try
{
Thread.sleep(1000);
videoProgressed = YPlayer.getCurrentTimeMillis();
}
catch (Exception e)
{
e.printStackTrace();
}
seekBar.setProgress(videoProgressed);
}
}
});
private void displayCurrentTime() {
if (YPlayer != null) {
String formattedTime = formatTime(YPlayer.getCurrentTimeMillis());
playTime.setText(formattedTime);
}
}
private String formatTime(int millis) {
int seconds = millis / 1000;
int minutes = seconds / 60;
return String.format("%02d:%02d", minutes % 60, seconds % 60);
}
private Runnable runnable = new Runnable() {
#Override
public void run() {
if(YPlayer != null) {
displayCurrentTime();
}
handler.postDelayed(this, 1000);
}
};
USE THIS CODE
Custom youtube player CHROMELESS style - set SeekBar Progress and Seek Bar TrackingTouch Forward/backward,
mSeekBar = (SeekBar) findViewById(R.id.video_seekbar);
mSeekBar.setOnSeekBarChangeListener(mVideoSeekBarChangeListener)
SeekBar.OnSeekBarChangeListener mVideoSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
long lengthPlayed = (mYouTubePlayer.getDurationMillis() * seekBar.getProgress()) / 100;
mYouTubePlayer.seekToMillis((int) lengthPlayed);
}
};
private Runnable runnable = new Runnable() {
#Override
public void run(){
displayCurrentTime();
mHandler.postDelayed(this, 100);
}
};
private void displayCurrentTime() {
if (null == mYouTubePlayer) return;
String formattedTime = formatTime(mYouTubePlayer.getDurationMillis() - mYouTubePlayer.getCurrentTimeMillis());
play_timetv.setText(formattedTime);
playPercent = (int) (((float) mYouTubePlayer.getCurrentTimeMillis()/(float) mYouTubePlayer.getDurationMillis()) * 100);
System.out.println("get youtube displayTime 2 : "+playPercent);
// update live progress
mSeekBar.setProgress(playPercent, true);
}
Check this tutorial if it can help you. This tutorial is all about Android Building Audio Player. It discuss here on how to build a simple audio player with basic controls like play, pause, forward, backward, next, previous, playlist and seekbar.
Just check the code in where the tutorial explain on how to update progress bar timer implemented in a background thread which runs in background using a Handler. You can check here how the seekbar being implemented.
For more information, check this related SO question.
Add youtubeSeekBar.setProgress(yPlayer.getCurrentTimeMillis()/100); in on playing() event
YPlayer.setPlaybackEventListener(new YouTubePlayer.PlaybackEventListener() {
#Override
public void onPlaying() {
handler.postDelayed(runnable, 100); //Handler's instance initialized as instance variable
displayCurrentTime();
youtubeSeekBar.setProgress(yPlayer.getCurrentTimeMillis()/100); //this is your key of success
}
#Override
public void onPaused() {
handler.removeCallbacks(runnable);
}
#Override
public void onStopped() {
}
#Override
public void onBuffering(boolean b) {
handler.postDelayed(runnable, 1000);
}
#Override
public void onSeekTo(int i) {
handler.removeCallbacks(runnable);
}
});
playerControl.setVisibility(View.VISIBLE); //Layout with play (and pause) button, Seekbar (which isn't moving along with the video), and timer (string being returned by the above displayCurrentTime() method)
}
I have the problem with the seekbar thumb, although I have added every necessary codes for it to work. still the seekbar thumb doesn't play from the point dragged by the user. instead the thumb positioned itself back to the point it was last playing though. Any help will be appreciated.
plus = (ImageButton) findViewById(R.id.imageButton2);
minus = (ImageButton) findViewById(R.id.imageButton4);
player = MediaPlayer.create(this, R.raw.songnames);
player.setLooping(false);
im = (ImageButton) this.findViewById(R.id.imageButton3);
seekbar = (SeekBar) findViewById(R.id.mantraProgressBar);
seekbar.setVisibility(ProgressBar.VISIBLE);
seekbar.setProgress(0);
seekbar.setMax(player.getDuration());
new Thread(this).start();
im.setOnClickListener(this);
player.start();
im.setImageResource(R.drawable.pause_tran);
Toast.makeText(this, isPlaying, Toast.LENGTH_LONG).show();
plus.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int cu = player.getCurrentPosition();
player.seekTo(cu - 5000);
}
});
minus.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int cu = player.getCurrentPosition();
player.seekTo(cu + 5000);
}
});
}
#Override
public void onClick(View arg0) {
if (arg0.getId() == R.id.imageButton3) {
if (player.isPlaying()) {
player.pause();
Toast.makeText(this, notPlaying, Toast.LENGTH_LONG).show();
ImageButton img1 = (ImageButton) this.findViewById(R.id.imageButton3);
img1.setImageResource(R.drawable.play_tran);
} else {
player.start();
Toast.makeText(this, isPlaying, Toast.LENGTH_LONG).show();
ImageButton img1 = (ImageButton) this.findViewById(R.id.imageButton3);
img1.setImageResource(R.drawable.pause_tran);
}
}
}
#Override
public void run() {
int currentPosition = 0;
String s;
int total = player.getDuration();
while (player != null && currentPosition < total) {
try {
Thread.sleep(1000);
currentPosition = player.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
seekbar.setProgress(currentPosition);
}
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
player.seekTo(progress);
seekbar.setProgress(progress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
public class MainActivity extends AppCompatActivity {
private MyVideoView mVV;
private Handler mhandler;
private SeekBar seekbar;
private int duration;
private int backPositon = 0;
private int currentPosition;
private SharedPreferences sp;
private MediaController controller;
private TextView tv_curr;
private TextView tv_duration;
private Handler handler;
private boolean mExit;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mVV = (MyVideoView) findViewById(R.id.vv);
seekbar = (SeekBar) findViewById(R.id.seekbar);
tv_curr = (TextView) findViewById(R.id.tv_currtime);
tv_duration = (TextView) findViewById(R.id.tv_duration);
//get duration of video
getDuration();
//video start
playVideo();
//get current time
getCurrentDuration();
//listener
initEvent();
}
private void initHanlder() {
handler=new Handler(){
#Override
public void handleMessage(Message msg) {
if (msg.what==0x123){
tv_curr.setText(timeFormat(mVV.getCurrentPosition()));
seekbar.setProgress(mVV.getCurrentPosition());
}
if(msg.what==0x133){
int changedProgress = msg.arg1;
tv_curr.setText(timeFormat(changedProgress));
mVV.seekTo(changedProgress);
seekbar.setProgress(changedProgress);
mVV.start();
}
}
};
new Thread(new Runnable() {
#Override
public void run() {
while (mVV.getCurrentPosition()<duration){
Message message = Message.obtain();
message.what=0x123;
handler.sendMessage(message);
SystemClock.sleep(1000);
if(mExit){
break;
}
}
}
}).start();
}
private void getDuration() {
mVV.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
duration = mVV.getDuration();
timeFormat(duration);
Log.d("TAG", "---duration" + timeFormat(duration));
seekbar.setMax(duration);
//TextView time
tv_duration.setText(timeFormat(duration));
//init handler
initHanlder();
}
});
}
private String timeFormat(int time) {
StringBuilder mFormatBuilder;
Formatter mFormatter;
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
int totalSeconds = time / 1000;
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
mFormatBuilder.setLength(0);
if (hours > 0) {
return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
} else {
return mFormatter.format("%02d:%02d", minutes, seconds).toString();
}
}
private void playVideo() {
File file = new File(Environment.getExternalStorageDirectory(), "cgx_video/db.mp4");
if (!file.exists()) {
file.mkdir();
}
Log.d("TAG", file.toString());
mVV.setVideoPath(file.getPath());
mVV.start();
}
private void initEvent() {
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
currentPosition=progress;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
mVV.pause();
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
if(handler!=null){
Message message = Message.obtain();
message.what=0x133;
message.arg1=currentPosition;
handler.sendMessage(message);
}
}
});
}
#Override
protected void onPause() {
super.onPause();
Log.d("TAG", "---onPause");
mVV.pause();
backPositon = mVV.getCurrentPosition();
Log.d("TAG", "backPositon:" + backPositon);
}
#Override
protected void onStop() {
super.onStop();
Log.d("TAG", "---onStop");
}
#Override
protected void onResume() {
super.onResume();
Log.d("TAG", backPositon + "---backPositon");
mVV.seekTo(backPositon);
mVV.start();
}
#Override
protected void onDestroy() {
//in case of leak of memeroy
mExit=true;
super.onDestroy();
}
}
I was working in a very simple music player with a seek bar.
I could make it working but I got a problem with playing music, it doesn't work correctly every second - it backwards a while, then remain again like it's a buggy.
Here's full code:
private MediaPlayer mediaPlayer;
private Button button;
private TextView textView;
private SeekBar seek;
private Handler mHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button);
textView = (TextView)findViewById(R.id.text);
seek = (SeekBar)findViewById(R.id.seek);
mediaPlayer = new MediaPlayer();
mediaPlayer = MediaPlayer.create(getApplicationContext(),R.raw.threedays);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
if(mediaPlayer != null){
int mCurrentPosition = mediaPlayer.getCurrentPosition() / 1000;
seek.setProgress(mCurrentPosition);
}
mHandler.postDelayed(this, 1000);
}
});
seek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
seekBar.setMax(mediaPlayer.getDuration() / 1000);
textView.setText(progress + "/" + seekBar.getMax());
mediaPlayer.seekTo(progress*1000);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
pause();
}
});
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mediaPlayer.isPlaying()) {
pause();
} else {
start();
}
}
});
}
public void start(){
if(mediaPlayer!=null) {
mediaPlayer.start();
button.setText("Pause");
}
}
public void pause(){
if(mediaPlayer!=null) {
mediaPlayer.pause();
button.setText("Play");
}
}
#Override
protected void onDestroy() {
if(mediaPlayer!=null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
mediaPlayer.release();
mediaPlayer = null;
}
super.onDestroy();
}
Try this code on seek.setOnSeekBarChangeListener
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
seekBar.setMax(mediaPlayer.getDuration() / 1000);
textView.setText(progress + "/" + seekBar.getMax());
if(fromUser)
{
mediaPlayer.seekTo(progress*1000);
}
}
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) {
}
});
}