MediaPlayer 簡介

GivemepasS
5 min readAug 29, 2019

--

如果你要使用 MediaPlayer,你必須很小心地去使用它,因為它存在非常多的細節必須注意。

一開始有兩個基本的類別

  • MediaPlayer
  • AudioManager

MediaPlayer 可以播放聲音以及影像,而AudioManager則是負責影像的部分。

我們今天來探討 MediaPlayer 的部分。

在使用 MediaPlayer 的時候,你必須在 Android Manifest 宣告兩個權限,分別是:

  • Intent Permission
  • Wake Lock Permission

而你在操作 MediaPlayer 的時候,可以使用三種來源,分別是:

  • Local resource
  • Content Resolver
  • External URL (Streaming)

在使用 MediaPlayer 的時候,首先你必須先使用 prepare 這個方法,而這個方法通常是用在抓取資料以及解碼的部分,它通常會需要比較長的處理時間,如果這時候你是在 UI Thread 執行它的時候,通常會得到一個比較不好的使用者體驗,甚至可能會造成 ANR 的錯誤,因此,建議你在使用這個方法的時候,是另外開一條 Thread 去處理它。

另外一點就是如果你使用了一個 Thread 去處理它的時候,你就必須監控它處理好的時候,能夠及時通知你做 UI 上面的更新,因此,你必須額外再去寫一監聽器來幫助你能夠得到比較好的回饋。

Android 在這部分提供了一個 prepareAsync 這個方法,讓你不用自己手動去開啟一個 Worker Thread 處理這部分,另外你可以透過 MediaPlayer.OnPreparedListener 來監控 prepare 的狀態。

管理狀態

MediaPlayer 有一整套的狀態圖,比如說 Prepare、Idle、Started、Error 、Pause…等等狀態,你在操作 MediaPlayer 的時候必須小心處理這些狀態,如果你不小心設定了一個錯誤的狀態,可能會造成一些非預期的錯誤。

舉個例子來說,當你建立了一個 MediaPlayer 的實體物件後,你就可以透過非同步的方式去呼叫 prepare 這個方法,接著你可以根據操作的狀態執行 start、pause 或者 seekTo 等方法,但是當你呼叫了 stop 這個方法以後,你就不能再執行 start 這個方法,直到你後來還有再呼叫一次 prepare 這個方法為止,所以你可以參照 MediaPlayer 的狀態圖來正確操作這個元件。

釋放資源

MediaPlayer 是一個容易消耗系統資源的工具,因此當你在使用它的時候要非常的注意資源的釋放,當你呼叫 stop 方法以後,請記住千萬一定要再呼叫 release 這個方法,否則它會佔著資源,即便使用者已經沒有操作畫面,它仍會在後面運作導致浪費資源。

舉個簡單的例子,假設你每次都沒有釋放資源,那麼當你在刷掉現有畫面或者橫向直向旋轉螢幕,每次都會產生新的 MediaPlayer 實體,此時資源的消耗就會變得非常嚴重。

非同步處理

當你想要讓 MediaPlayer 在背景進行運作,你可以寫進 Service 裡面,但是實際上 Service 是運作在 Main Thread,因此如果你需要讓他長期運作在背景,你必須自己開啟一條 Worker Thread 來執行,或者你直接在 Service 內部使用 prepareAsync 這個方法,並且透過實作 MediaPlayer.OnPreparedListener 這個方法來處理事件監聽,當它通知你準備完成以後,你就可以開始操作 start 這個方法了。

處理非同步錯誤

通常非同步錯誤的會發出對應的錯誤碼來告知你發生什麼錯誤,但是你必須適當的正確處理它,透過 MediaPlayer 你可以透過 MediaPlayer.OnErrorListener 來監聽相關事件,而當錯誤發生的時候,你必須自行更改 MediaPlayer 的錯誤狀態,畢竟正確的重啟你的 MediaPlayer。

使用螢幕鎖定

當我們的執行中的多媒體服務正在運作,也許你的螢幕被關閉了,Android 系統為了保護電池,會移除相關沒有用的資源,包含 CPU、WIFI 等相關硬體資源,但是你的服務正在播放你的串流,所以你必須透過 Playback 來維持你服務的運作。

為了確保讓你的服務能夠持續運作,你必須使用螢幕鎖定的功能,螢幕鎖定會跟系統表示我目前有服務在運行,請在手機停止運作的時候,繼續保持著我的服務以及功能。

你在初始化 MediaPlayer 的時候,你可以透過 setWakeMode 這個方法來幫你處理這件事情,如此一來無論是暫停或者停止的時候,系統都會幫你保留這個 MediaPlayer 的資源。

如果你的 Media 來源是來自雲端,那麼你也要透過 WifiLock 的設定幫你保留資源,但是記住,如果你不需要這些資源的時候,就得自己手動釋放它們,否則你的系統將會浪費許多無謂的資源。

清除的動作

除了先前所提到的要隨時注意釋放資源以後,其實在任何 Activity 結束的時候,也建議在 onDestory 裡面將沒有釋放到的資源給予釋放,另外也要注意,當你使用 MediaPlayer 的時候頻率很短暫時,不要頻繁的重新啟動跟建立 MediaPlayer,因為頻繁的啟動跟釋放也是一種資源浪費。

後面還有 DRM、加密以及從 ContentResolver 就不細說了,有興趣可以參考以下連結。

參考來源

https://developer.android.com/guide/topics/media/mediaplayer

--

--

No responses yet