So the problem i have is when i drag my seekbar to the end of the song, it works from some songs and i goes to the next one, but sometimes it skips a song and stops playing. example;
Im at song "position 1" which is passed from my mainactivity to my songactivity when a song is clicked which is displayed in a recyclerview.
And when i drag my seekbar to the end, it goes to 2 and then 3 and 4, but then it skips to 6, so it didn't play the song at position 5.
This only occurs when i drag my seekbar to the end of a song, with my next and previous button it works.
This the code from my songActivity
mCurrentIndex = (int) b.get("songIndex");
if (mediaPlayer.isPlaying()){
mBtnPlayPause.setImageResource(R.drawable.ic_action_pause_white);
updateProgressBar();
}
tvSongListSize.setText((songIndex + 1) + "/" + songList.size());
mBtnShuffle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isShuffle){
isShuffle = false;
Toast.makeText(getApplicationContext(), "Shuffle is off", Toast.LENGTH_SHORT ).show();
mBtnShuffle.setImageResource(R.drawable.ic_action_shuffle);
}else{
isShuffle = true;
Toast.makeText(getApplicationContext(), "Shuffle is on", Toast.LENGTH_SHORT).show();
mBtnShuffle.setImageResource(R.drawable.ic_shuffle_on);
isRepeat = false;
mBtnRepeat.setImageResource(R.drawable.ic_action_repeat);
}
}
});
mBtnRepeat.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isRepeat){
isRepeat = false;
Toast.makeText(getApplicationContext(), "Repeat is off", Toast.LENGTH_SHORT).show();
mBtnRepeat.setImageResource(R.drawable.ic_action_repeat);
}else{
isRepeat = true;
Toast.makeText(getApplicationContext(), "Repeat is on", Toast.LENGTH_SHORT).show();
mBtnRepeat.setImageResource(R.drawable.ic_repeat_on);
isShuffle = false;
mBtnShuffle.setImageResource(R.drawable.ic_action_shuffle);
}
}
});
mBtnPlayPause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
mBtnPlayPause.setImageResource(R.drawable.ic_action_play);
} else {
mediaPlayer.start();
mBtnPlayPause.setImageResource(R.drawable.ic_action_pause_white);
}
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mBtnPlayPause.setImageResource(R.drawable.ic_action_play);
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
mBtnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
nextSong();
}
});
mBtnPrev.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
prevSong();
}
});
}
private void playSongNumber(int index) {
try{
mediaPlayer.reset();
mediaPlayer.setDataSource(songList.get(index).getData());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
seekBar.setProgress(0);
seekBar.setMax(100);
updateProgressBar();
}catch (Exception e){
e.printStackTrace();
}
}
private void nextSong(){
mCurrentIndex++;
mCurrentIndex %= songList.size();
playSongNumber(mCurrentIndex);
mBtnPlayPause.setImageResource(R.drawable.ic_action_pause_white);
tvSongListSize.setText((mCurrentIndex + 1) + "/" + songList.size());
Toast.makeText(getApplicationContext(), "You Clicked position: " + mCurrentIndex + " " + songList.get(mCurrentIndex).getData(), Toast.LENGTH_SHORT).show();
}
private void prevSong(){
mCurrentIndex = mCurrentIndex > 0 ? mCurrentIndex - 1 : songList.size() - 1;
playSongNumber(mCurrentIndex);
mBtnPlayPause.setImageResource(R.drawable.ic_action_pause_white);
tvSongListSize.setText((mCurrentIndex + 1) + "/" + songList.size());
Toast.makeText(getApplicationContext(), "You Clicked position: " + mCurrentIndex + " " + songList.get(mCurrentIndex).getData(), Toast.LENGTH_SHORT).show();
}
@Override
public void onCompletion(MediaPlayer mp) {
if (isRepeat){
playSongNumber(mCurrentIndex);
}else if(isShuffle){
Random random = new Random();
mCurrentIndex = random.nextInt((songList.size() - 1) + 1);
tvSongListSize.setText((mCurrentIndex + 1) + "/" + songList.size());
playSongNumber(mCurrentIndex);
}else if (mCurrentIndex < songList.size()-1){
nextSong();
tvSongListSize.setText((mCurrentIndex + 1) + "/" + songList.size());
}else{
playSongNumber(0);
tvSongListSize.setText((1) + "/" + songList.size());
}
}
public void updateProgressBar(){
mHandler.postDelayed(mUpdateTime, 100);
}
private Runnable mUpdateTime = new Runnable() {
@Override
public void run() {
long songCurrentTime = mediaPlayer.getCurrentPosition();
long songTotalTime = mediaPlayer.getDuration();
tvSongCurrentTime.setText(""+utilities.msToTimer(songCurrentTime));
tvSongTotalTime.setText(""+utilities.msToTimer(songTotalTime));
int progress = (int)(utilities.getProgressPercentage(songCurrentTime, songTotalTime));
seekBar.setProgress(progress);
mHandler.postDelayed(this, 100);
}
};
A toast also show that it skips a song (toast showing 2 times).
Second problem SOLVED
When i click on a song, it goes to the songActivity and the next song plays when onCompletion is called, but when i press the pause button, and then play again and after the song is completed it gets stuck and doesn't play the next song.
Third problem
When i go to the last song in my list and let it play out so OnCompletion is called, it goes back to the first song in my list, which is good, but when i then click the previous button to go back to the last song, it skips the last song. Example: Last song is at position [25], when completed it goes back to the song at position [0] (my first song), but when i click the back button it goes to [24] and skips [25] ( the last song).
This only occurs when oncompletion is called.
This is happening because some error is happening on runtime and You haven't implemented OnErrorListener
.
In the android documentation it is mentioned that if you don't implement OnErrorListener
on the MediaPlayer
object then on occurence of any error it would cause the OnCompletionListener
to be called.
So implement an 'OnErrorListener' and return true if error has been handled and false if it is not. Returning false will again call the OnCompletionListener
.
You can refer the android docs here: https://developer.android.com/reference/android/media/MediaPlayer.OnErrorListener.html
EDIT: One main problem that i've found in your code is that you are calling updateProgressBar()
inside playSongNumber()
method but it will be executed before onPrepared
gets called. That's what causing you problem. Move your updateProgressBar()
call inside onPrepared
and after mp.start()