onCompletion()正常情況下是在一首歌曲播放完之后會得到調(diào)用安券,但是現(xiàn)在發(fā)現(xiàn)有時候會異常調(diào)用,找了一些資料壶冒,發(fā)現(xiàn)如果在mediaplayer setDataSource之前就調(diào)用了類似 getDuration()的方法就會出錯犹菱,onCompletion()就會被調(diào)用破托。
那么為什么會出現(xiàn)在在setDataSource之前就調(diào)用了類似getDuration()的方法呢?我的項目中是這樣的情況:
我自定義了一個View顯示播放的信息(就是最下面的那個)
下面的進(jìn)度信息是通過新開了一個線程寸宏,不斷地通過getDuration()來獲取歌曲進(jìn)度的宁炫,但是當(dāng)我們快速點擊list上面的歌曲的時候,歌曲在切換的瞬間(即當(dāng)mediaplayer reset之后氮凝,setDataSource之前)羔巢,那個線程來不及反應(yīng)還沒停止繼續(xù)在getDuration(),所以會有很大的幾率出現(xiàn)onCompletion()被異常調(diào)用的情況罩阵。
那么怎么解決竿秆?我們onCompletion()本身要完成的是切換下一首歌曲同時更新下面的自定義View信息,但是現(xiàn)在onCompletion()被異常調(diào)用永脓,就會出現(xiàn)我明明點的是第一首歌袍辞,但是自定義View上顯示的卻是下一首歌的信息,這個就很尷尬了常摧。
解決方法是:onCompletion()里面進(jìn)行判斷搅吁,如果當(dāng)前狀態(tài)是播放或者暫停情況下,onCompletion()被調(diào)用落午,就不更新View!因為我點擊list上的歌曲之前我的mediaplayer只有2種可能性谎懦,要么播放started,要么paused溃斋,其他狀態(tài)點擊list上的歌曲不會出現(xiàn)異常調(diào)用onCompletion()的可能界拦,而我們正常情況下一首歌播放完切換下一首歌的時候mediaplayer的狀態(tài)不會是started或者paused,那么現(xiàn)在問題又來了,怎么獲取當(dāng)前mediaplayer狀態(tài)梗劫,mediaplayer本身是沒有這個方法的享甸,只有isPlaying判斷是否在播放,對于我們呢沒有用梳侨,所以我們自己需要加一個狀態(tài)碼蛉威,在每次mediaplayer狀態(tài)切換的時候?qū)@個狀態(tài)碼進(jìn)行修改
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());
//歌曲在播放的時候調(diào)用到了這個方法,說明出了問題走哺!不進(jìn)行后續(xù)處理蚯嫌!
if(!mp.isPlaying()&&(MEDIA_PLAYER_MODE==4||MEDIA_PLAYER_MODE==5))
{
switch (PLAY_MODE)
{
//列表循環(huán)模式
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生命周期圖: