Mediaplayer中onCompletion的异常调用问题解决

onCompletion()正常情况下是在一首歌曲播放完之后会得到调用,但是现在发现有时候会异常调用,找了一些资料,发现如果在mediaplayer setDataSource之前就调用了类似 getDuration()的方法就会出错,onCompletion()就会被调用。
那么为什么会出现在在setDataSource之前就调用了类似getDuration()的方法呢?我的项目中是这样的情况:
我自定义了一个View显示播放的信息(就是最下面的那个)


Mediaplayer中onCompletion的异常调用问题解决_第1张图片
QQ图片20161217200457.png

下面的进度信息是通过新开了一个线程,不断地通过getDuration()来获取歌曲进度的,但是当我们快速点击list上面的歌曲的时候,歌曲在切换的瞬间(即当mediaplayer reset之后,setDataSource之前),那个线程来不及反应还没停止继续在getDuration(),所以会有很大的几率出现onCompletion()被异常调用的情况。
那么怎么解决?我们onCompletion()本身要完成的是切换下一首歌曲同时更新下面的自定义View信息,但是现在onCompletion()被异常调用,就会出现我明明点的是第一首歌,但是自定义View上显示的却是下一首歌的信息,这个就很尴尬了。
解决方法是:onCompletion()里面进行判断,如果当前状态是播放或者暂停情况下,onCompletion()被调用,就不更新View!因为我点击list上的歌曲之前我的mediaplayer只有2种可能性,要么播放started,要么paused,其他状态点击list上的歌曲不会出现异常调用onCompletion()的可能,而我们正常情况下一首歌播放完切换下一首歌的时候mediaplayer的状态不会是started或者paused,那么现在问题又来了,怎么获取当前mediaplayer状态,mediaplayer本身是没有这个方法的,只有isPlaying判断是否在播放,对于我们呢没有用,所以我们自己需要加一个状态码,在每次mediaplayer状态切换的时候对这个状态码进行修改

public int MEDIA_PLAYER_MODE=0; 
//播放模式:0——Idle  1——Initialized  3——Prepared   4——Started 5--Paused  6——Stopped

@Override
    public void onCompletion(MediaPlayer mp)
    {

        Log.d("sendError","MusicService.onCompletion()"+"mp.isPlaying()?"+mp.isPlaying());

        //歌曲在播放的时候调用到了这个方法,说明出了问题!不进行后续处理!
        if(!mp.isPlaying()&&(MEDIA_PLAYER_MODE==4||MEDIA_PLAYER_MODE==5))
        {
            switch (PLAY_MODE)
            {  
                //列表循环模式
                case 0:
                    //处理本身逻辑
                    if(curPos==songs.size()-1)  //到底了重新开始播放
                    {
                        curPos=0;
                    }
                    _toNextSong();
                    _sendToNextMessage();
                    break;
                //顺序播放模式  
                case 1:
                    //处理本身逻辑
                    if(curPos==songs.size()-1)  //到底了就停止播放
                    {
                        _realeaseMediaPlayer();
                        return;
                    }
                    _toNextSong();  //切换下一首歌
                    _sendToNextMessage();   //更新View
                    break;
                case 2:
                    break;
                case 3:
                    break;
                default:
                    break;
            }
        }
    }

这里的Idle Initialized 都是mnediaplayer的生命周期,这里附上mediaplayer生命周期图:


Mediaplayer中onCompletion的异常调用问题解决_第2张图片
Paste_Image.png

你可能感兴趣的:(Mediaplayer中onCompletion的异常调用问题解决)