Jetpack Media3 定義了 Player
介面,用於概述基本功能
影片和音訊檔案的播放。ExoPlayer
為預設實作方式
您之後要在 Media3 中使用這個介面的介面建議使用 ExoPlayer,因為其提供
功能完整的功能組合,涵蓋大部分的播放用途
再靈活自訂來處理其他用途ExoPlayer 也
去除裝置和 OS 零碎的零碎問題,確保程式碼能穩定運作
整個 Android 生態系統中ExoPlayer 包含下列項目:
- 支援播放清單
- 支援各種漸進式及適應性串流 格式
- 支援用戶端和伺服器端廣告插播
- 支援受數位版權管理保護的播放
本頁將逐步說明建立播放作業的重要步驟 應用程式。如需更多詳細資訊,請參閱完整指南 Media3 ExoPlayer。
開始使用
如要開始使用,請新增 ExoPlayer、UI,以及 Jetpack Media3:
implementation "androidx.media3:media3-exoplayer:1.4.0" implementation "androidx.media3:media3-ui:1.4.0" implementation "androidx.media3:media3-common:1.4.0"
根據您的用途,可能也需要 Media3、
例如 exoplayer-dash
,以 DASH 格式播放串流。
請務必將 1.4.0
替換為您偏好的
資源庫。請參閱版本資訊
即可查看最新版本
建立媒體播放器
在 Media3 中,您可以使用隨附的 Player
實作
您可以運用 ExoPlayer
介面,也可以自行建立實作項目。
建立 ExoPlayer
建立 ExoPlayer
例項最簡單的方式如下:
Kotlin
val player = ExoPlayer.Builder(context).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build();
您可以在以下項目的 onCreate()
生命週期方法中建立媒體播放器:
居住地的Activity
、Fragment
或Service
。
Builder
包括
您可能會感興趣的一系列自訂選項,例如:
setAudioAttributes()
敬上 設定音訊焦點處理功能setHandleAudioBecomingNoisy()
敬上 設定在音訊輸出裝置中斷連線時的播放行為setTrackSelector()
敬上 設定曲目選取
Media3 提供 PlayerView
UI 元件,您可以將其納入應用程式的
版面配置檔案。這個元件會封裝用於播放的 PlayerControlView
控制項、SubtitleView
顯示字幕、Surface
用於轉譯。
影片。
準備播放器
將媒體項目加入
運用以下方法播放內容:
setMediaItem()
敬上
和 addMediaItem()
。
然後呼叫 prepare()
以
開始載入媒體並取得必要資源。
您不應在應用程式於前景執行前執行這些步驟。如果您的
這表示玩家位於 Activity
或 Fragment
,亦即
API 級別 24 以上級別或 onResume()
的 onStart()
生命週期方法
生命週期方法。對於位於 Service
中的玩家,
「onCreate()
」中的準備工作
控製播放器
播放器準備就緒後,您可以透過呼叫方法控製播放 例如:
play()
和pause()
開始播放及暫停播放seekTo()
可跳轉至 目前媒體項目中的位置seekToNextMediaItem()
敬上 和seekToPreviousMediaItem()
瀏覽播放清單
PlayerView
或 PlayerControlView
等 UI 元件會更新
當繫結至玩家時即可對應 ID。
放開播放器
播放時可能需要有限的資源 (例如影片)
因此,請務必呼叫 release()
以便釋出資源。
如果玩家位於 Activity
或 Fragment
,請釋放
API 級別 24 以上級別或 onPause()
的 onStop()
生命週期方法
方法。對於位於 Service
中的玩家,您可以
onDestroy()
發布新版本。
透過媒體工作階段管理播放
在 Android 上,媒體工作階段是與媒體互動的標準化方式 跨越程序邊界的玩家。將媒體工作階段連線至播放器 可讓您對外宣傳媒體播放,以及接收 來自外部來源的命令,例如與 適用於行動裝置和大型的系統媒體控制項 螢幕裝置。
如要使用媒體工作階段,請在 Media3 Session 模組中新增依附元件:
implementation "androidx.media3:media3-session:1.4.0"
建立媒體工作階段
將播放器初始化後,您可以建立一個 MediaSession
,如下所示:
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
Media3 會自動將 Player
的狀態與
MediaSession
。此做法適用於任何 Player
實作,包括
ExoPlayer
、CastPlayer
或
自訂實作方式
將控制權授予其他用戶端
用戶端應用程式可以實作媒體控制器
控制媒體工作階段的播放如要接收這些要求,請設定
callback 物件
建立你的 MediaSession
當控制器準備連線到媒體工作階段時,
onConnect()
敬上
方法。您可以使用 Google 提供的 ControllerInfo
決定是否要接受。
或拒絕
要求。如要查看範例,請參見 Media3 Session 試用版應用程式。
連線後,控制器就能傳送播放指令給工作階段。
然後將這些指令委派給玩家。播放與播放清單
自動處理 Player
介面中定義的指令
會很有幫助
其他回呼方法可讓您處理
自訂播放指令
以及修改播放清單。這些回呼同樣包含 ControllerInfo
物件,因此您可以
可以依個別要求決定存取權控管機制
在背景播放媒體
舉例來說,在應用程式不在前景運作時,如要繼續播放媒體,例如:
播放音樂、有聲書或 Podcast,即使使用者沒有應用程式也沒問題
您的 Player
和 MediaSession
應該封裝於
前景服務。Media3 提供
為此用途的 MediaSessionService
介面。
實作 MediaSessionService
建立可擴充 MediaSessionService
的類別,並將
onCreate()
生命週期方法中的 MediaSession
。
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your Player and MediaSession in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, player).build() } // Remember to release the player and media session in onDestroy override fun onDestroy() { mediaSession?.run { player.release() release() mediaSession = null } super.onDestroy() } }
Java
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
在資訊清單中,Service
類別包含 MediaSessionService
意圖
篩選並要求 FOREGROUND_SERVICE
權限以執行前景
服務:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
最後,在您建立的類別中,覆寫 onGetSession()
方法以控制
用戶端的媒體工作階段存取權。傳回 MediaSession
以接受
連線要求,或傳回 null
以拒絕要求。
Kotlin
// This example always accepts the connection request override fun onGetSession( controllerInfo: MediaSession.ControllerInfo ): MediaSession? = mediaSession
Java
@Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { // This example always accepts the connection request return mediaSession; }
連線至使用者介面
現在媒體工作階段與 Activity
屬於不同的 Service
,或
Fragment
在玩家使用者介面所在的位置,您可以使用 MediaController
連結
在 Activity
或 Fragment
的 onStart()
方法中,
UI,為 MediaSession
建立 SessionToken
,然後使用 SessionToken
來建立 MediaController
。建立 MediaController
即可
以非同步方式載入物件
Kotlin
override fun onStart() { val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java)) val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync() controllerFuture.addListener( { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()) }, MoreExecutors.directExecutor() ) }
Java
@Override public void onStart() { SessionToken sessionToken = new SessionToken(this, new ComponentName(this, PlaybackService.class)); ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(this, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()); }, MoreExecutors.directExecutor()) }
MediaController
會實作 Player
介面,因此您可以使用相同的
方法,例如 play()
和 pause()
。和其他類似頻道
請記得在 MediaController
不再移除時釋出元件
例如 Activity
的 onStop()
生命週期方法,方法是呼叫
MediaController.releaseFuture()
。
發布通知
需要使用前景服務才能發布通知。A 罩杯
MediaSessionService
會自動建立
以下使用者的 MediaStyle
通知:
格式為 MediaNotification
。
如要提供自訂通知,請
MediaNotification.Provider
敬上
合作對象:DefaultMediaNotificationProvider.Builder
或建立自訂實作供應商介面。新增
透過以下方式將供應商加到您的「MediaSession
」:
setMediaNotificationProvider
。
宣傳你的內容資料庫
MediaLibraryService
以允許用戶端在 MediaSessionService
上建構
,藉此瀏覽應用程式提供的媒體內容。用戶端應用程式
MediaBrowser
即可進行互動
這項資訊分享給您的MediaLibraryService
。
實作 MediaLibraryService
與實作
MediaSessionService
,不過在 onGetSession()
中,您應該傳回
MediaLibrarySession
而不是 MediaSession
。相較於
MediaSession.Callback
,MediaLibrarySession.Callback
包含額外的
這個方法可讓瀏覽器用戶端瀏覽
程式庫服務
與 MediaSessionService
類似,請在MediaLibraryService
資訊清單,並要求 FOREGROUND_SERVICE
權限執行前景
服務:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaLibraryService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
上述範例包含同時有 MediaLibraryService
意圖的意圖篩選器
為了回溯相容性,舊版的 MediaBrowserService
。
額外的意圖篩選器可透過 MediaBrowserCompat
API 啟用用戶端應用程式
辨識你的Service
。
MediaLibrarySession
可讓您透過樹狀結構提供內容資料庫
單一根層級 MediaItem
樹狀結構中的每個 MediaItem
都可以
任意數量的子項 MediaItem
節點。您可以提供不同的根,或
不同的樹狀結構。舉例來說
尋找建議媒體項目清單的客戶,可能只有
包含根 MediaItem
和單一層級的子項 MediaItem
節點。
但您返回不同用戶端應用程式的樹狀結構,
完整的內容庫
建立 MediaLibrarySession
MediaLibrarySession
擴充 MediaSession
API,可新增內容瀏覽 API。相較於
MediaSession
回呼、
MediaLibrarySession
回呼
新增以下方法:
onGetLibraryRoot()
敬上 用戶端要求內容樹狀結構的根層級MediaItem
時onGetChildren()
敬上 在用戶端要求內容樹狀結構中MediaItem
的子項時觸發onGetSearchResult()
敬上 用戶端針對某個 項查詢
相關的回呼方法會包含 LibraryParams
包含用戶端應用程式的內容樹狀結構類型相關信號