本文鏈接: Android MediaPlayer 基礎簡介
簡單介紹MediaPlayer的基本概念,狀態,常用的方法與監聽器,
什么是MediaPlayer
MediaPlayer類可以用來播放音視頻檔案,或者是音頻流,開發者可以用它來播放本地音頻,或者是網路在線音頻,
MediaPlayer屬于android.media包,
MediaPlayer的狀態
播放控制由狀態機控制,在日常生活中,我們常見的音頻狀態有播放中,暫停,停止,緩沖等等,
MediaPlayer的狀態有如下幾種:
- Idle
- End
- Error
- Initialized
- Preparing
- Prepared
- Started
- Stopped
- Paused
- PlaybackCompleted
狀態的切換參考官方圖例,
這里稍微解釋一下狀態轉換圖片,橢圓代表MediaPlayer可能停留的狀態,橢圓之間的箭頭表示方法呼叫,狀態切換的方向,單箭頭表示方法同步呼叫,雙箭頭表示異步呼叫,

從圖中我們可以看出狀態切換的路徑和涉及到的方法,
Idle與End狀態
當new一個MediaPlayer或者呼叫了reset方法,當前MediaPlayer會處于Idle狀態,呼叫release后,會處于End狀態,在這2個狀態之間的狀態可以看做是MediaPlayer物件的生命周期,
在新創建MediaPlayer和呼叫reset的MediaPlayer之間有一些細微的差別,
這兩種情況都處于Idle狀態,呼叫 getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioAttributes(android.media.AudioAttributes), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(long, int), prepare() 或 prepareAsync()方法都會拋出錯誤,如果是新實體化的MediaPlayer,不會回呼 one rrorListener.onError();但如果是reset后的MediaPlayer,會回呼 one rrorListener.onError()并且轉換到Error狀態,
如果MediaPlayer物件不再使用了,立即呼叫release()方法,釋放內部播放器占用的資源,這些資源可能是唯一的,比如硬體加速組件,如果呼叫release失敗,可能會引起一連串的MediaPlayer實體失效,當MediaPlayer處于End狀態,它就不能再轉移到其它狀態了,
new一個MediaPlayer,處于Idle狀態,如果用create方法創建實體,當創建完成時處于Prepared狀態,
發生錯誤
一些情形可能會讓MediaPlayer操作失敗,比如不支持的音視頻格式,解析度過高,網路超時等等,
因此在這些情形下錯誤處理和恢復非常重要,有時候編程錯誤也會導致MediaPlayer操作錯誤,
開發者可以設定錯誤監聽器setOnErrorListener(android.media.MediaPlayer.OnErrorListener),當錯誤發生時,會呼叫用戶實作的OnErrorListener.onError()方法,
不管有沒有設定監聽器,錯誤發生時MediaPlayer會進入Error狀態,
為了重復使用同一個MediaPlayer物件,可以使用reset()方法把它從Error狀態恢復到Idle狀態,
設定錯誤監聽器OnErrorListener是一個好的編程習慣,開發者可以監聽到播放引擎的錯誤通知,
有時候會拋出IllegalStateException例外,比如在錯誤的狀態呼叫了prepare(), prepareAsync()方法,或是setDataSource方法,
設定音源 setDataSource
呼叫setDataSource(java.io.FileDescriptor), 或者 setDataSource(java.lang.String), 或者 setDataSource(android.content.Context, android.net.Uri), 或者 setDataSource(java.io.FileDescriptor, long, long), 或者 setDataSource(android.media.MediaDataSource) 可以將MediaPlayer的狀態從Idle轉到Initialized狀態,
如果在Idle狀態之外的狀態呼叫了setDataSource(),會拋出IllegalStateException例外,
開發者應該留意setDataSource方法拋出的IllegalArgumentException和IOException例外,
播放音頻前必須在Prepared狀態
MediaPlayer在開始播放音頻前必須處于Prepared狀態,
MediaPlayer有同步和異步2種方式來進入Prepared狀態,如果是異步的方式,會先轉到Preparing狀態,再轉到Prepared狀態,
當準備完成時,內部的播放引擎會回呼叫戶之前設定的OnPreparedListener的onPrepared()方法,
開發者必須注意的是,Preparing狀態是一個過渡狀態(transient state),
處于Prepared狀態時,可以通過相對應的方法設定音量,螢屏常亮,播放回圈等,
開始播放
播放音頻必須呼叫start()方法,呼叫start()回傳成功后,MediaPlayer處于Started狀態,
可以通過isPlaying()來判斷當前是否在Started狀態,
如果開發者設定了OnBufferingUpdateListener,Android內部播放器會向外傳遞buffer資訊,
如果當前處于Started狀態,再呼叫start()方法沒有效果,
暫停播放與繼續播放
音頻可以被暫停播放和繼續播放,也可以調整播放的位置,通過pause()方法來暫停音頻播放,
成功呼叫pause()方法后,MediaPlayer進入Paused狀態,
應當注意的是,MediaPlayer在Started狀態與Paused狀態之間切換是異步的,播放音頻流的時候,這個轉換程序可能會需要幾秒鐘,
MediaPlayer暫停時,start()方法可以從暫停的位置繼續播放,成功呼叫start方法后會進入Started狀態,
處于Paused狀態時,呼叫pause()方法沒有效果,
停止
呼叫stop()方法讓MediaPlayer從Started, Paused, Prepared 或 PlaybackCompleted 狀態進入 Stopped 狀態,
在Stopped狀態時,必須先呼叫prepare() 或 prepareAsync()進入Prepared狀態后,才能播放音頻,
處于Stopped狀態時,呼叫stop()方法沒有效果,
調整播放位置
呼叫seekTo(long, int)來調整播放位置,
seekTo(long, int)是一個異步方法,雖然它能立刻回傳,但實際的位置調整可能會消耗一段時間,特別是在播放音頻流的時候,當實際播放位置調整后,內部播放器會回呼開發者設定的OnSeekComplete.onSeekComplete(),
在Prepared, Paused 和 PlaybackCompleted狀態中,都可以呼叫seekTo方法,
可以通過getCurrentPosition()方法來獲取當前播放位置,開發者可以得知當前播放的進度等等,
播放完畢
音頻播放完成后,播放完畢,
如果呼叫setLooping(boolean)為true,MediaPlayer會停留在Started狀態,
如果setLooping為false,內部播放器會呼叫開發者設定的OnCompletion.onCompletion(),并且進入PlaybackCompleted狀態,
處于PlaybackCompleted狀態時,呼叫start()方法可以從頭開始播放音頻,
常用監聽器
開發者可以設定一些監聽器,監聽MediaPlayer的狀態,錯誤事件等等,開發者應在同一個執行緒中創建MediaPlayer與設定的監聽器,
setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)
監聽MediaPlayer準備完成,一般與prepareAsync配合使用,
setOnVideoSizeChangedListener(android.media.MediaPlayer.OnVideoSizeChangedListener)
獲知video大小或video大小改變時的監聽,
setOnSeekCompleteListener(android.media.MediaPlayer.OnSeekCompleteListener)
監聽調整位置完成,
setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener)
播放完成,
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
// 當前播放完畢
}
});
setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener)
監聽緩沖進度,在播放網路音頻時常用,
緩沖監聽器OnBufferingUpdateListener
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// 例如在這里更新UI
}
});
setOnInfoListener(android.media.MediaPlayer.OnInfoListener)
監聽普通資訊或者警告資訊,
setOnErrorListener(android.media.MediaPlayer.OnErrorListener)
監聽錯誤資訊,錯誤發生時,可以在這里處理錯誤,
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean one rror(MediaPlayer mediaPlayer, int i, int i1) {
LogUtil.e(TAG_PREFIX + " onERR i = " + i + " i1 = " + i1);
return true; // 回傳true表示在此處理錯誤,不會回呼onCompletion
}
});
注意onError的回傳值,可以選擇自己處理error,
* @return True if the method handled the error, false if it didn't.
* Returning false, or not having an one rrorListener at all, will
* cause the OnCompletionListener to be called.
*/
boolean one rror(MediaPlayer mp, int what, int extra);
需要的權限
播放網路音頻時需要Manifest.permission.INTERNET權限,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/58595.html
標籤:Android
下一篇:kotlin之變數的可空與非空
