Vince VD
Vince VD

Reputation: 1581

Play next song oncompletion

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.

Upvotes: 1

Views: 1074

Answers (2)

Will Shaw
Will Shaw

Reputation: 52

In my oncompletionlistener, I put my void playNext, to play next song, then I call go, to start the mediaplayer, this is how I go to next song, I put oncompletionlistener inside my method, to play new song, eg. reset, prepare, method, by calling player, I do this, and my mediaplayer advances to the next song, example below, hope I helped. Also below is how I shuffle songs, in oncompletion, and shuffle code, put musicsrv.setshuffle in your main activity class, and then button to use shuffle on off.

musicSrv.setShuffle(); 
  public void setShuffle(){
            if(shuffle) shuffle=false;
            else shuffle=true;
            //metadata();
            //playbackstate();
            //nots(context);
    }







  player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                            if (currrentsongindex == +1) {
                                    mp.release();
                                    mp = null;     // either set counter to 0 and start again or call end of list
                                    mp.start();
                                

                                    
                            } else {

                                    playNext();
                                    go();
                                    
                            }
                    }
            });

Upvotes: 0

Rahul Kumar
Rahul Kumar

Reputation: 348

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

Upvotes: 1

Related Questions