android - 完成后播放下一首歌曲

标签 android listener android-mediaplayer

所以我遇到的问题是,当我将我的搜索栏拖到歌曲的末尾时,它可以从一些歌曲开始工作,然后我转到下一首,但有时它会跳过一首歌曲并停止播放。 例子;

我在歌曲“位置 1”,当点击一首显示在回收 View 中的歌曲时,它从我的主要 Activity 传递到我的歌曲 Activity 。

当我将我的搜索栏拖到最后时,它转到 2,然后是 3 和 4,但随后它跳到 6,所以它没有播放位置 5 的歌曲。

只有当我将我的搜索栏拖到一首歌曲的末尾时才会发生这种情况,而我的下一首和上一首按钮会起作用。

这是我的 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);
    }
};

toast 还显示它跳过了一首歌曲(toast 显示 2 次)。

第二个问题 已解决

当我点击一首歌曲时,它会转到 songActivity 并在调用 onCompletion 时播放下一首歌曲,但是当我按下暂停按钮并再次播放时,歌曲播放完毕后它会卡住并且不会播放播放下一首歌曲。

第三个问题

当我转到列表中的最后一首歌曲并让它播放以便调用 OnCompletion 时,它会返回到列表中的第一首歌曲,这很好,但是当我单击上一首按钮返回到最后一首歌,它会跳过最后一首歌。 示例:最后一首歌曲位于位置 [25],完成后它会返回到位置 [0] 的歌曲(我的第一首歌曲),但是当我单击后退按钮时它会转到 [24] 并跳过 [25](最后一首歌)。

这仅在调用 oncompletion 时发生。

最佳答案

发生这种情况是因为在运行时发生了一些错误,并且您还没有实现 OnErrorListener

在 android 文档中提到,如果您没有在 MediaPlayer 对象上实现 OnErrorListener,那么在发生任何错误时都会导致 OnCompletionListener 被调用。

因此,实现一个“OnErrorListener”,如果错误已被处理则返回 true,否则返回 false。返回 false 将再次调用 OnCompletionListener

您可以在此处引用 android 文档:https://developer.android.com/reference/android/media/MediaPlayer.OnErrorListener.html

编辑:我在您的代码中发现的一个主要问题是您在 playSongNumber() 方法中调用了 updateProgressBar() 但它将在 onPrepared 被调用。这就是导致你出现问题的原因。将您的 updateProgressBar() 调用移到 onPrepared 内并在 mp.start()

之后

关于android - 完成后播放下一首歌曲,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47740291/

相关文章:

java 。如何重新定义 MediaPlayer 实例的 onCompletion 方法

java - 有没有办法在 Android Studio 中将代码从 Java 转换为 Kotlin,而不使用复制/粘贴方法?

java - 如何在android本地数据库中存储intent?

android - Gradle 2.3.0-alpha1 无法进行数据绑定(bind)

java - XMPP Smack API RosterListener + 数据库更改

java - 从数据库端进行更改时不会调用 Hibernate 事件监听器

AndroidId MediaPlayer prepareAsync 方法

android - 加载器没有获得更新 ListFragment 的回调

javascript - id为 X 的 QBWebRTC 目前正忙? QB.webrtc.onRemoteStreamListener 未触发。 Quickblox Javascript SDK + Angular + WebRTC

android - 需要有关 Android 声音处理的帮助/建议