本頁面說明如何建立 DefaultPreloadManager,根據您選擇的策略為應用程式預先載入媒體內容。
以 BasePreloadManager 抽象類別為基礎的預先載入管理工具,可讓您依據所選條件為內容排名。本文說明如何使用衍生類別 DefaultPreloadManager,其中每個媒體項目都會以整數排名,代表其在清單中的位置 (例如在影片輪轉介面中的位置)。預先載入管理工具會根據項目與使用者目前播放項目的距離,優先載入項目。這樣一來,如果使用者移至其他項目,新項目就能立即開始播放。
建立 DefaultPreloadManager 例項的步驟有三個:
- 定義
TargetPreloadStatusControl,預先載入管理工具可查詢該項目,瞭解媒體項目是否已準備好載入,以及要載入多少內容。 - 建立建構工具,用於建立預先載入管理工具和應用程式的
ExoPlayer物件。 - 呼叫建構工具的
build()方法,使用建構工具建立預先載入管理工具。
建立目標預先載入狀態控制項
建立 DefaultPreloadManager.Builder 時,您需要傳遞自行定義的目標預先載入狀態控制項物件。這個物件會實作 TargetPreloadStatusControl 介面。預先載入管理工具準備預先載入媒體時,會呼叫狀態控制項的 getTargetPreloadStatus() 方法,判斷是否要準備、載入或快取媒體項目的內容。載入功能會直接將媒體資料預先載入播放器的記憶體內緩衝區,以便立即播放,而快取功能則會將媒體資料儲存至永久磁碟快取,節省播放器記憶體。狀態控制項可回覆下列其中一個狀態碼:
STAGE_SPECIFIED_RANGE_LOADED:預先載入管理工具應從指定的開始位置,將指定時間長度 (以毫秒為單位) 的內容載入播放器的記憶體緩衝區。STAGE_SPECIFIED_RANGE_CACHED:預先載入管理工具應從指定的開始位置,將指定時間長度 (以毫秒為單位) 的內容快取到磁碟快取。STAGE_TRACKS_SELECTED:預先載入管理工具應載入及處理內容軌的資訊,並選取音軌。預先載入管理工具不應開始載入內容。STAGE_SOURCE_PREPARED:預先載入管理工具應準備內容來源。舉例來說,如果內容的中繼資料位於獨立的資訊清單檔案中,預先載入管理工具可能會擷取並剖析該資訊清單。null:預先載入管理工具不應載入該媒體項目的任何內容或中繼資料。
您必須制定策略,決定要為每個媒體項目載入多少內容。在這個範例中,系統會為最接近目前播放項目的項目載入更多內容。如果使用者播放索引為 n 的內容,控制器會傳回下列程式碼:
- 索引 n+1 (下一個媒體項目):從預設起始位置載入 3000 毫秒 (3 秒)
- 索引 n-1 (上一個媒體項目):從預設起始位置載入 1000 毫秒 (1 秒)
- 範圍 n-2 至 n+2 內的其他媒體項目:傳回
PreloadStatus.TRACKS_SELECTED - n-4 到 n+4 範圍內的其他媒體項目:傳回
PreloadStatus.SOURCE_PREPARED - 如果是其他媒體項目,則傳回
null
class MyTargetPreloadStatusControl(var currentPlayingIndex: Int = 0) : TargetPreloadStatusControl<Int, DefaultPreloadManager.PreloadStatus> { override fun getTargetPreloadStatus(index: Int): DefaultPreloadManager.PreloadStatus { if (index - currentPlayingIndex == 1) { // next track // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and // suggest loading 3000ms from the default start position return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L) } else if (index - currentPlayingIndex == -1) { // previous track // return a PreloadStatus that is labelled by STAGE_SPECIFIED_RANGE_LOADED and // suggest loading 3000ms from the default start position return DefaultPreloadManager.PreloadStatus.specifiedRangeLoaded(3000L) } else if (abs(index - currentPlayingIndex) == 2) { // return a PreloadStatus that is labelled by STAGE_TRACKS_SELECTED return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_TRACKS_SELECTED } else if (abs(index - currentPlayingIndex) <= 4) { // return a PreloadStatus that is labelled by STAGE_SOURCE_PREPARED return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_SOURCE_PREPARED } return DefaultPreloadManager.PreloadStatus.PRELOAD_STATUS_NOT_PRELOADED } }
程式碼重點
- 建立預先載入管理工具建構工具時,您會將
MyTargetPreloadStatusControl的例項傳遞給該建構工具。 currentPlayingIndex會保留目前播放的媒體項目索引。應用程式會負責更新這個值。- 預先載入管理工具準備好載入內容時,會呼叫
getTargetPreloadStatus,並傳遞您為該媒體項目指定的排名資訊。以DefaultPreloadManager為例,排名資訊是整數,用於指定項目在輪轉介面中的位置。這個方法會比較該索引與目前所選項目的索引,選擇要傳回的程式碼。
建立預先載入管理工具
如要建立預先載入管理工具,您需要 DefaultPreloadManager.Builder。該建構工具會使用目前的背景資訊和應用程式的目標預先載入狀態控制項進行設定。您可以使用所有預設設定建立預先載入管理工具。
val targetPreloadStatusControl = MyTargetPreloadStatusControl() val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl) val preloadManager = preloadManagerBuilder.build()
建構工具也提供 setter 方法,可用於設定預先載入管理工具的自訂元件。
舉例來說,您可以在 DefaultPreloadManager 中自訂所有預先載入媒體來源的目標緩衝區總位元組數,這樣預先載入的資料就不會超過該限制。您可以在播放器名稱為 "preload" 的自訂 DefaultLoadControl.Builder 上,使用 setPlayerTargetBufferBytes(String, int) 設定這項限制,並將該執行個體傳遞至預先載入管理工具建構工具:
val targetPreloadStatusControl = MyTargetPreloadStatusControl() val preloadManagerBuilder = DefaultPreloadManager.Builder(context, targetPreloadStatusControl) preloadManagerBuilder.setLoadControl( DefaultLoadControl.Builder() .setPlayerTargetBufferBytes("preload", 128 * 1024 * 1024) // 128 MiB .build() ) val preloadManager = preloadManagerBuilder.build()
雖然建構工具的 setter 方法基本上可視需要自訂,但如果您想將任何媒體項目快取至磁碟,就必須呼叫 setCache(),使用 Cache 設定建構工具。如果未設定快取,嘗試快取媒體項目會導致 IllegalStateException。
建立 ExoPlayer 來播放預先載入的媒體項目
除了使用建構工具建立預先載入管理工具外,您還可以使用建構工具建立應用程式用來播放內容的 ExoPlayer 物件,讓 ExoPlayer 正確與預先載入管理工具共用元件。您仍可傳遞已設定這些設定的 ExoPlayer.Builder 執行個體,為 ExoPlayer 設定播放專屬設定。
// Direct creation val exoPlayer = preloadManagerBuilder.buildExoPlayer() // Creation with custom playback specific configurations val skipSilenceExoPlayerBuilder = ExoPlayer.Builder(context).setSkipSilenceEnabled(true) val skipSilenceExoPlayer = preloadManagerBuilder.buildExoPlayer(skipSilenceExoPlayerBuilder)