播放器是應用程式中的元件,可協助播放媒體項目。Media3 Player
介面會概述播放器一般處理的功能。包括:
- 影響播放控制項,例如播放、暫停和跳轉
- 查詢目前播放媒體的屬性,例如播放位置
- 管理媒體項目的播放清單/佇列
- 設定播放屬性,例如隨機播放、重複播放、速度和音量
- 正在將影片轉譯至螢幕
Media3 也提供 Player
介面 (稱為 ExoPlayer
) 的實作。
元件之間的共通介面
Media3 中有多個元件實作播放器介面,例如:
元件 | 說明與行為注意事項 |
---|---|
ExoPlayer |
媒體播放器 API,以及 Player 介面的預設實作方式。 |
MediaController |
與 MediaSession 互動以傳送播放指令。如果您的 Player 和 MediaSession 與玩家 UI 所在的 Activity 或 Fragment 不同,您可以將 MediaController 指派為 PlayerView UI 的玩家。Service 播放和播放清單方法的呼叫會透過 MediaSession 傳送至 Player 。 |
MediaBrowser |
除了 MediaController 提供的功能之外,也可以與 MediaLibrarySession 互動以瀏覽可用的媒體內容。 |
ForwardingPlayer |
將方法呼叫轉送至其他 Player 的 Player 實作。請使用這個類別,透過覆寫個別方法來隱藏或修改特定作業。 |
SimpleBasePlayer |
可減少實作方法數量的 Player 實作。如果您想將自訂播放器連結至 MediaSession ,這就非常實用。 |
CastPlayer |
與 Cast 接收器應用程式通訊的 Player 實作。實際行為取決於基礎的投放工作階段。 |
雖然 MediaSession
不會實作 Player
介面,但建立介面時需要有 Player
。其目的是從其他程序或執行緒提供 Player
的存取權。
Media3 播放架構
如果您可以存取 Player
,應直接呼叫其方法以發出播放指令。您可以實作 MediaSession
來通告播放,並授予外部來源播放控制項。這些外部來源會實作 MediaController
,以便連線至媒體工作階段並發出播放指令要求。
在背景播放媒體時,您需要將媒體工作階段和播放器存放在以前景服務的 MediaSessionService
或 MediaLibraryService
中。如此一來,您就可以將播放器與包含播放控制項 UI 的應用程式內活動分開。您可能需要使用媒體控制器。
播放器狀態
導入 Player
介面的媒體播放器狀態主要包含以下 4 種資訊:
- 播放狀態
- 使用
getPlaybackState()
擷取。 - 介面定義的狀態值包括
STATE_IDLE
、STATE_BUFFERING
、STATE_READY
和STATE_ENDED
。
- 使用
- 媒體項目的播放清單
- 用於播放的
MediaItem
例項序列。 - 使用
getCurrentTimeline()
擷取 Player
執行個體可提供播放清單作業方法,例如新增或移除MediaItem
,以及便利的方法 (例如getCurrentMediaItem()
)。
- 用於播放的
- 播放/暫停屬性,例如:
playWhenReady
:表示使用者希望在可行或保持暫停狀態時播放媒體- 播放抑制原因:在適用情況下,抑製播放的原因 (即使
playWhenReady
為true
也一樣) isPlaying
:指示播放器是否正在播放。只有在播放狀態為STATE_READY
、playWhenReady
為true
且未抑製播放時,這個指標才會為true
- 播放位置,包括:
- 目前的媒體項目索引:播放清單中目前
MediaItem
的索引。 isPlayingAd
:指出插入廣告是否正在播放。- 目前播放位置:目前播放位置 (位於目前
MediaItem
或插入的廣告中)。
- 目前的媒體項目索引:播放清單中目前
此外,Player
介面還可讓您存取可用的曲目、媒體中繼資料、播放速度、音量,以及播放的其他輔助屬性。
監聽變更
使用 Player.Listener
監聽 Player
中的變更。如要進一步瞭解如何建立及使用事件監聽器,請參閱「玩家事件」的 ExoPlayer 說明文件。
請注意,事件監聽器介面不包含任何回呼來追蹤正常播放進度。如要持續監控播放進度 (例如設定進度列 UI),建議您以適當的時間間隔查詢目前位置。
Kotlin
val handler = Handler(Looper.getMainLooper()) fun checkPlaybackPosition(delayMs: Long): Boolean = handler.postDelayed( { val currentPosition = player.currentPosition // Update UI based on currentPosition checkPlaybackPosition(delayMs) }, delayMs)
Java
Handler handler = new Handler(Looper.getMainLooper()); boolean checkPlaybackPosition(long delayMs) { return handler.postDelayed(() -> { long currentPosition = player.getCurrentPosition(); // Update UI based on currentPosition checkPlaybackPosition(delayMs); }, delayMs); }
控制播放功能
Player
介面提供多種操控狀態和控製播放的方式:
- 基本播放控制項,例如
play()
、pause()
、prepare()
和stop()
。 - 播放清單作業,例如
addMediaItem()
或removeMediaItem()
。 - 「跳轉」即可變更目前項目或位置。
- 設定重複模式和重組模式。
- 更新音軌選取偏好設定。
- 設定播放速度。
自訂 Player
實作
如要建立自訂播放器,請擴充 Media3 中的 SimpleBasePlayer
。這個類別提供 Player
介面的基本實作,以便將需要實作的方法數量減少到最低需求。
首先,覆寫 getState()
方法。這個方法應在呼叫時填入目前的玩家狀態,包括:
- 這組指令
- 播放屬性,例如播放狀態為
STATE_READY
時,是否應讓播放器開始播放、目前播放中媒體項目的索引,以及目前項目中的播放位置
Kotlin
class CustomPlayer : SimpleBasePlayer(looper) { override fun getState(): State { return State.Builder() .setAvailableCommands(...) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build() } }
Java
public class CustomPlayer extends SimpleBasePlayer { public CustomPlayer(Looper looper) { super(looper); } @Override protected State getState() { return new State.Builder() .setAvailableCommands(...) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build(); } }
SimpleBasePlayer
會強制 State
使用有效的狀態值組合建立。它也會處理事件監聽器,並通知狀態變更的監聽器。如果需要手動觸發狀態更新,請呼叫 invalidateState()
。
除了 getState()
方法以外,您只需要實作可用於玩家宣告指令的方法。請找出與您要實作的功能相對應的可覆寫處理常式方法。舉例來說,請覆寫 handleSeek()
方法以支援 COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM
和 COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
等作業。