【问题标题】:Play next song oncompletion完成后播放下一首歌曲
【发布时间】:2017-12-10 15:25:10
【问题描述】:

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

我在歌曲“位置 1”,当点击显示在回收视图中的歌曲时,它从我的 mainactivity 传递到我的 songactivity。

当我将搜索栏拖到最后时,它会转到 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 时发生。

【问题讨论】:

  • 错误出现在我的 onCompletion 中,但我没有看到。

标签: android listener android-mediaplayer


【解决方案1】:

发生这种情况是因为运行时发生了一些错误并且您尚未实现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() 调用移至 onPreparedmp.start() 之后

【讨论】:

  • 好的,所以我实现了 OnErrorListener,但是我在该方法中添加了什么?
  • 问题依然存在,当一首歌曲结束时,它会跳过一首歌曲。
  • 好的,当出现错误时,我的媒体播放器现在停止播放,我怎样才能摆脱错误并让我的媒体播放器继续播放下一首歌曲而不跳过一首歌曲?
  • 你得到了你的 mediaPlayer 对象,int what 和 int extra onError。使用它们来检查您遇到的错误类型,并基于此您可以决定恢复播放并返回 true,或者如果错误是无法解决的问题,则返回 false 以跳过当前歌曲。
  • 我已经更新了答案。请检查一下。如果有帮助,请将答案标记为已接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 2021-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多