Search code examples
javaandroidandroid-mediaplayer

Android mediaplayer next song onButton Click


Button btnPlayPause, btnNext, btnPrevious;
Bundle b;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_song);

    btnPlayPause = (Button) findViewById(R.id.btnPlayPause);
    btnNext = (Button) findViewById(R.id.btnNext);
    btnPrevious = (Button) findViewById(R.id.btnPrevious);

    Intent currSong = getIntent();
    b = currSong.getExtras();

    btnPlayPause.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
                if (mediaPlayer != null) {
                    if (mediaPlayer.isPlaying()) {
                        mediaPlayer.pause();
                        btnPlayPause.setText("Play");
                    } else {
                        mediaPlayer.start();
                        btnPlayPause.setText("Stop");
                    }
                    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            btnPlayPause.setText("Play");
                        }
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    });
    btnNext.setOnClickListener(new View.OnClickListener() {
        int songIndex = (int) b.get("songIndex");
        @Override
        public void onClick(View v) {
            if (songIndex < songList.size() - 1) {
                songIndex = songIndex + 1;
                Toast.makeText(getApplicationContext(), "You Clicked " + songIndex , Toast.LENGTH_SHORT).show();
                try {
                    mediaPlayer.stop();
                    mediaPlayer.reset();
                    mediaPlayer.setDataSource(songList.get(songIndex).getData());
                    mediaPlayer.prepareAsync();
                    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            mp.start();
                        }
                    });

                } catch (Exception e) {

                    e.printStackTrace();

                }
            }else{
                songIndex=0;
            }
        }
    });

    btnPrevious.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (songIndex > 0){
                songIndex = songIndex-1;
                Toast.makeText(getApplicationContext(), "You Clicked " + songIndex , Toast.LENGTH_SHORT).show();
                try {
                    mediaPlayer.stop();
                    mediaPlayer.reset();
                    mediaPlayer.setDataSource(songList.get(songIndex).getData());
                    mediaPlayer.prepareAsync();
                    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            mp.start();
                        }
                    });

                } catch (Exception e) {

                    e.printStackTrace();

                }
            }else {
                songIndex = songList.size() - 1;
            }
        }
    });
}

}

So when i click on the next button, it plays the second song, but at the end of my songlist it skips the first song from the list stored in [0] and on second click it goes to [1] so there is always one song not playing. How can i solve this or is there an easier way too go to the next song?

Thanks, -Vince

EDIT;

Problem 2; when i choose a song, lets say with position 37, and i click on previous it goes to 36, but if i then click on next it goes to 38, so it skips the song i played first.

EDIT 2 ; Ok problems still persists, but i found out that when i click a few times on previous btn let's say i start from position 25 and go to 15 with the previous btn, and when i then click on next again it just starts to count from 25. How can i solve this? Thanks in advance, - vince


Solution

  • Ok, you have several problems here:

    i found out that when i click a few times on previous btn let's say i start from position 25 and go to 15 with the previous btn, and when i then click on next again it just starts to count from 25

    In PlayNext's first line, you reassign songIndex to the original songIndex passed to the activity. PlayPrevious uses another songIndex that I can't see where is defined. If you had followed Android guidelines to always prefix with an "m" the class properties vs local variables, you'd easily have realised it.

    So when i click on the next button, it plays the second song, but at the end of my songlist it skips the first song from the list stored in [0] and on second click it goes to [1]

    The edge cases where user plays the next after the last song, or the previous after the first are incorrectly coded. In those cases you correctly update songIndex, but do not call play.

    Besides the problems, what you should do is to rework your code a little using functions, to avoid repeating functionality. That is always prone to these kind of errors. I'd suggest something like this:

    int mCurrentIndex; // always prefix class properties with an "m"
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_song);
    
        Button  btnPlayPause = (Button) findViewById(R.id.btnPlayPause),
                btnNext = (Button) findViewById(R.id.btnNext),
                btnPrevious = (Button) findViewById(R.id.btnPrevious);
    
        Intent currSong = getIntent();
        Bundle b = currSong.getExtras();
    
        // load initial index only once
        mCurrentIndex = (int) b.get("songIndex");
    
        btnPrevious.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCurrentIndex = mCurrentIndex > 0 ? mCurrentIndex - 1 : mSongList.size() - 1;
                playSongNumber(mCurrentIndex);
            }
        }
    
        btnNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCurrentIndex++;
                mCurrentIndex %= mSongList.size();
                playSongNumber(mCurrentIndex);
            }
        }
    
    }
    
    private void playSongNumber(int index) {
    
        try {
            mMediaPlayer.stop();
            mMediaPlayer.reset();
            mMediaPlayer.setDataSource(mSongList.get(index).getData());
            mMediaPlayer.prepareAsync();
            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.start();
                }
            });
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    

    slightly cleaner, isn't it?