onCompletion()正常情况下是在一首歌曲播放完之后会得到调用,但是现在发现有时候会异常调用,找了一些资料,发现如果在mediaplayer setDataSource之前就调用了类似 getDuration()的方法就会出错,onCompletion()就会被调用。
那么为什么会出现在在setDataSource之前就调用了类似getDuration()的方法呢?我的项目中是这样的情况:
我自定义了一个View显示播放的信息(就是最下面的那个)
![](https://img.haomeiwen.com/i3234377/49b51da8c4a2af30.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生命周期图:
![](https://img.haomeiwen.com/i3234377/cd7651c65fea6685.png)
网友评论