Android MediaPlayer 基礎簡介

本文連接: Android MediaPlayer 基礎簡介java

簡單介紹MediaPlayer的基本概念,狀態,經常使用的方法與監聽器。android

什麼是MediaPlayer

MediaPlayer類能夠用來播放音視頻文件,或者是音頻流。開發者能夠用它來播放本地音頻,或者是網絡在線音頻。編程

MediaPlayer屬於android.media包。網絡

MediaPlayer的狀態

播放控制由狀態機控制。在平常生活中,咱們常見的音頻狀態有播放中,暫停,中止,緩衝等等。 MediaPlayer的狀態有以下幾種:異步

  • Idle
  • End
  • Error
  • Initialized
  • Preparing
  • Prepared
  • Started
  • Stopped
  • Paused
  • PlaybackCompleted

狀態的切換參考官方圖例。 這裏稍微解釋一下狀態轉換圖片。橢圓表明MediaPlayer可能停留的狀態。橢圓之間的箭頭表示方法調用,狀態切換的方向。單箭頭表示方法同步調用,雙箭頭表示異步調用。ide

mediaplayer_state_diagram

從圖中咱們能夠看出狀態切換的路徑和涉及到的方法。oop

Idle與End狀態

當new一個MediaPlayer或者調用了reset方法,當前MediaPlayer會處於Idle狀態。調用release後,會處於End狀態。在這2個狀態之間的狀態能夠看作是MediaPlayer對象的生命週期。spa

在新建立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,不會回調 OnErrorListener.onError();但若是是reset後的MediaPlayer,會回調 OnErrorListener.onError()而且轉換到Error狀態。.net

若是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 onError(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 OnErrorListener at all, will
         * cause the OnCompletionListener to be called.
         */
        boolean onError(MediaPlayer mp, int what, int extra);
複製代碼

須要的權限

播放網絡音頻時須要Manifest.permission.INTERNET權限。

相關文章
相關標籤/搜索