目前使用獨立 com.google.android.exoplayer2 程式庫和 androidx.media 的應用程式應遷移至 androidx.media3。使用遷移指令碼,將 Gradle 建構檔案、Java 和 Kotlin 來源檔案,以及 XML 版面配置檔案,從 ExoPlayer 2.19.1 遷移至 AndroidX Media3 1.1.1。
總覽
遷移前,請先參閱下列章節,進一步瞭解新版 API 的優點、要遷移的 API,以及應用程式專案應符合的先決條件。
為什麼要遷移至 Jetpack Media3
- 這是 ExoPlayer 的新園地,而 com.google.android.exoplayer2已停止支援。
- 使用 MediaBrowser/MediaController存取各元件/程序中的 Player API。
- 使用 MediaSession和MediaControllerAPI 的擴充功能。
- 透過精細的存取權控管機制宣傳播放功能。
- 移除 MediaSessionConnector和PlayerNotificationManager,簡化應用程式。
- 可向後相容於 media-compat 用戶端 API
(MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)
要遷移至 AndroidX Media3 的媒體 API
- ExoPlayer 和擴充功能 
 這包括舊版 ExoPlayer 專案的所有模組,但已停止使用的 mediasession 模組除外。如果應用程式或模組依附於com.google.android.exoplayer2中的套件,可以使用遷移指令碼遷移。
- MediaSessionConnector (視 androidx.media:media:1.4.3+的androidx.media.*套件而定)
 移除MediaSessionConnector,改用androidx.media3.session.MediaSession。
- MediaBrowserServiceCompat (視 androidx.media:media:1.4.3+的androidx.media.*套件而定)
 將androidx.media.MediaBrowserServiceCompat的子類別遷移至androidx.media3.session.MediaLibraryService,並使用MediaBrowserCompat.MediaItem的程式碼遷移至androidx.media3.common.MediaItem。
- MediaBrowserCompat (視 androidx.media:media:1.4.3+的android.support.v4.media.*套件而定)
 使用MediaBrowserCompat或MediaControllerCompat遷移用戶端程式碼,以便搭配androidx.media3.common.MediaItem使用androidx.media3.session.MediaBrowser。
必要條件
- 確認專案受到來源控管 - 請確保您可以輕鬆還原指令碼遷移工具套用的變更。 如果專案尚未納入來源控管,現在是開始的好時機。如果因故不想這麼做,請先備份專案,再開始遷移。 
- 更新應用程式 - 建議您更新專案,使用最新版 ExoPlayer 程式庫,並移除對已淘汰方法的任何呼叫。如果您打算使用指令碼進行遷移,更新的版本必須與指令碼處理的版本相符。 
- 將應用程式的 compileSdkVersion 提高至 32 以上。 
- 將 Gradle 和 Android Studio Gradle 外掛程式升級至適用於上述更新後依附元件的最新版本。例如: - Android Gradle 外掛程式版本:7.1.0
- Gradle 版本:7.4
 
- 取代所有使用星號 (*) 的萬用字元匯入陳述式,並使用完整匯入陳述式:刪除萬用字元匯入陳述式,然後使用 Android Studio 匯入完整陳述式 (F2 - Alt/Enter、F2 - Alt/Enter...)。 
- 從 - com.google.android.exoplayer2.PlayerView遷移至- com.google.android.exoplayer2.StyledPlayerView。這是必要步驟,因為 AndroidX Media3 中沒有與- com.google.android.exoplayer2.PlayerView相對應的項目。
 
遷移 ExoPlayer 並支援指令碼
這個指令碼可協助您從 com.google.android.exoplayer2 遷移至 androidx.media3 底下的新套件和模組結構。指令碼會對專案套用一些驗證檢查,並在驗證失敗時列印警告。否則,系統會套用以 Java 或 Kotlin 編寫的 Android Gradle 專案資源中,重新命名的類別和套件對應項。
usage: ./media3-migration.sh [-p|-c|-d|-v]|[-m|-l [-x <path>] [-f] PROJECT_ROOT]
 PROJECT_ROOT: path to your project root (location of 'gradlew')
 -p: list package mappings and then exit
 -c: list class mappings (precedence over package mappings) and then exit
 -d: list dependency mappings and then exit
 -l: list files that will be considered for rewrite and then exit
 -x: exclude the path from the list of file to be changed: 'app/src/test'
 -m: migrate packages, classes and dependencies to AndroidX Media3
 -f: force the action even when validation fails
 -v: print the exoplayer2/media3 version strings of this script
 -h, --help: show this help text
使用遷移指令碼
- 從 GitHub 上 ExoPlayer 專案的標記下載遷移指令碼,該標記對應您更新應用程式時使用的版本: - curl -o media3-migration.sh \ "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
- 將指令碼設為可執行狀態: - chmod 744 media3-migration.sh
- 使用 - --help執行指令碼,瞭解相關選項。
- 使用 - -l執行指令碼,列出選取要遷移的檔案集 (使用- -f強制列出檔案,不顯示警告):- ./media3-migration.sh -l -f /path/to/gradle/project/root
- 使用 - -m執行指令碼,將套件、類別和模組對應至 Media3。 使用- -m選項執行指令碼,即可將變更套用至所選檔案。- 在驗證錯誤時停止,但不進行變更
 - ./media3-migration.sh -m /path/to/gradle/project/root- 強制執行
 - 如果指令碼發現違反先決條件的情況,可以使用 - -f標記強制遷移:- ./media3-migration.sh -m -f /path/to/gradle/project/root
 # list files selected for migration when excluding paths
 ./media3-migration.sh -l -x "app/src/test/" -x "service/" /path/to/project/root
 # migrate the selected files
 ./media3-migration.sh -m -x "app/src/test/" -x "service/" /path/to/project/root
使用 -m 選項執行指令碼後,請完成下列手動步驟:
- 檢查腳本如何變更程式碼:使用差異工具並修正潛在問題 (如果您認為腳本有一般問題,且是在未傳遞 -f選項的情況下導入,請考慮回報錯誤)。
- 建構專案:使用 ./gradlew clean build,或在 Android Studio 中依序選擇「File」>「Sync Project with Gradle Files」、「Build」>「Clean project」,然後「Build」>「Rebuild project」 (在 Android Studio 的「Build - Build Output」分頁中監控建構作業)。
建議採取的後續步驟:
- 解決有關使用不穩定 API 的錯誤。
- 取代已淘汰的 API 呼叫:使用建議的替代 API。 將指標懸停在 Android Studio 中的警告上,並參閱已淘汰符號的 JavaDoc,瞭解要使用哪些項目來取代特定呼叫。
- 排序匯入陳述式:在 Android Studio 中開啟專案,然後在專案檢視器中,以滑鼠右鍵按一下套件資料夾節點,並選擇包含已變更來源檔案的套件,然後選擇「Optimize imports」(最佳化匯入)。
以 androidx.media3.session.MediaSession 取代 MediaSessionConnector。
在舊版 MediaSessionCompat 世界中,MediaSessionConnector 負責將播放器的狀態與工作階段的狀態同步,並接收來自控制器的指令,這些指令需要委派給適當的播放器方法。使用 AndroidX Media3 時,這項作業會由 MediaSession 直接完成,不需要連接器。
- 移除 MediaSessionConnector 的所有參照和用法:如果您使用自動指令碼遷移 ExoPlayer 類別和套件,指令碼可能會讓程式碼處於無法編譯的狀態,且無法解決 - MediaSessionConnector問題。嘗試建構或啟動應用程式時,Android Studio 會顯示損毀的程式碼。
- 在維護依附元件的 - build.gradle檔案中,將 AndroidX Media3 媒體工作階段模組的實作依附元件新增至該檔案,並移除舊版依附元件:- implementation "androidx.media3:media3-session:1.8.0"
- 將 - MediaSessionCompat替換為- androidx.media3.session.MediaSession。
- 在您建立舊版 - MediaSessionCompat的程式碼網站,使用- androidx.media3.session.MediaSession.Builder建構- MediaSession。傳遞播放器來建構工作階段建構工具。- val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player) .setSessionCallback(MySessionCallback()) .build()
- 視應用程式需求實作 - MySessionCallback。這不是必要步驟。如要允許控制器將媒體項目新增至播放器,請實作- MediaSession.Callback.onAddMediaItems()。這項類別提供各種現有和舊版 API 方法,可將媒體項目新增至播放器,並以回溯相容的方式播放。包括 Media3 控制器的- MediaController.set/addMediaItems()方法,以及舊版 API 的- TransportControls.prepareFrom*/playFrom*方法。您可以在工作階段示範應用程式的- PlaybackService中找到- onAddMediaItems的實作範例。
- 在您遷移前終止工作階段的程式碼位置,釋放媒體工作階段: - mediaSession?.run { player.release() release() mediaSession = null }
Media3 中的 MediaSessionConnector 功能
下表列出可處理先前在 MediaSessionConnector 中實作功能的 Media3 API。
| MediaSessionConnector | AndroidX Media3 | 
|---|---|
| CustomActionProvider | MediaSession.Callback.onCustomCommand()/
MediaSession.setMediaButtonPreferences() | 
| PlaybackPreparer | MediaSession.Callback.onAddMediaItems()(內部稱為prepare()) | 
| QueueNavigator | ForwardingSimpleBasePlayer | 
| QueueEditor | MediaSession.Callback.onAddMediaItems() | 
| RatingCallback | MediaSession.Callback.onSetRating() | 
| PlayerNotificationManager | DefaultMediaNotificationProvider/
MediaNotification.Provider | 
將 MediaBrowserService 遷移至 MediaLibraryService
AndroidX Media3 推出 MediaLibraryService,取代 MediaBrowserServiceCompat。MediaLibraryService 和其超類別 MediaSessionService 的 JavaDoc 提供了 API 的良好簡介,以及服務的非同步程式設計模型。
MediaLibraryService 可回溯相容於 MediaBrowserService。使用  或  的用戶端應用程式連線至 MediaLibraryService 時,可繼續運作,不需變更程式碼。MediaBrowserCompatMediaControllerCompat對於用戶端而言,應用程式是使用 MediaLibraryService 還是舊版 MediaBrowserServiceCompat,都是一目瞭然。
 
    - 如要啟用回溯相容性,您需要在 - AndroidManifest.xml中向服務註冊這兩個服務介面。這樣一來,用戶端就能透過必要服務介面找到您的服務:- <service android:name=".MusicService" android:exported="true"> <intent-filter> <action android:name="androidx.media3.session.MediaLibraryService"/> <action android:name="android.media.browse.MediaBrowserService" /> </intent-filter> </service>
- 在維護依附元件的 - build.gradle檔案中,新增實作依附元件至 AndroidX Media3 工作階段模組,並移除舊版依附元件:- implementation "androidx.media3:media3-session:1.8.0"
- 將服務變更為從 - MediaLibraryService繼承,而不是- MediaBrowserService。如先前所述,- MediaLibraryService與舊版- MediaBrowserService相容。因此,服務提供給用戶端的廣泛 API 仍維持不變。因此,應用程式很可能可以保留實作- MediaBrowserService所需的大部分邏輯,並將其改編為適用於新版- MediaLibraryService。- 與舊版 - MediaBrowserServiceCompat相比,主要差異如下:- 實作服務生命週期方法:需要在服務本身覆寫的方法是 - onCreate/onDestroy,應用程式會在此方法中分配/釋放程式庫工作階段、播放器和其他資源。除了標準服務生命週期方法外,應用程式還需要覆寫- onGetSession(MediaSession.ControllerInfo),才能傳回在- onCreate中建構的- MediaLibrarySession。
- 實作 MediaLibraryService.MediaLibrarySessionCallback:建構工作階段需要實作實際網域 API 方法的 - MediaLibraryService.MediaLibrarySessionCallback。因此,您會覆寫- MediaLibrarySession.Callback的方法,而不是舊版服務的 API 方法。- 然後使用回呼建構 - MediaLibrarySession:- mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()- 在 API 說明文件中,找出 MediaLibrarySessionCallback 的完整 API。 
- 實作 - MediaSession.Callback.onAddMediaItems():回呼- onAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)可為各種現有和舊版 API 方法提供服務,以回溯相容的方式將媒體項目新增至播放器,以供播放。包括 Media3 控制器的- MediaController.set/addMediaItems()方法,以及舊版 API 的- TransportControls.prepareFrom*/playFrom*方法。您可以在工作階段示範應用程式的- PlaybackService中,找到回呼的實作範例。
- AndroidX Media3 使用 - androidx.media3.common.MediaItem,而非 MediaBrowserCompat.MediaItem 和 MediaMetadataCompat。與舊版類別相關聯的程式碼部分必須相應變更,或對應至 Media3- MediaItem。
- 一般非同步程式設計模型已變更為 - Futures,與- MediaBrowserServiceCompat的可拆卸- Result方法形成對比。服務實作項目可以傳回非同步- ListenableFuture,而不是分離結果或立即傳回 Future 來直接傳回值。
 
移除 PlayerNotificationManager
MediaLibraryService 會自動支援媒體通知,使用 MediaLibraryService 或 MediaSessionService 時,可以移除 PlayerNotificationManager。
應用程式可以透過在 onCreate() 中設定自訂 MediaNotification.Provider,取代 DefaultMediaNotificationProvider,藉此自訂通知。MediaLibraryService 接著會視需要負責啟動前景服務。
應用程式可以覆寫 MediaLibraryService.updateNotification(),進一步完全掌控通知的發布作業,並視需要啟動/停止前景服務。
使用 MediaBrowser 遷移用戶端程式碼
透過 AndroidX Media3,MediaBrowser 會實作 MediaController/Player 介面,除了瀏覽媒體庫,還可用於控制媒體播放。如果您必須在舊版世界中建立 MediaBrowserCompat 和 MediaControllerCompat,現在只要使用 Media3 中的 MediaBrowser 即可完成相同操作。
您可以建構 MediaBrowser,並等待與服務建立連線:
scope.launch {
    val sessionToken =
        SessionToken(context, ComponentName(context, MusicService::class.java)
    browser =
        MediaBrowser.Builder(context, sessionToken))
            .setListener(BrowserListener())
            .buildAsync()
            .await()
    // Get the library root to start browsing the library.
    root = browser.getLibraryRoot(/* params= */ null).await();
    // Add a MediaController.Listener to listen to player state events.
    browser.addListener(playerListener)
    playerView.setPlayer(browser)
}
請參閱「在媒體工作階段中控制播放」,瞭解如何建立 MediaController,以便在背景控制播放。
後續步驟和清除作業
不穩定的 API 錯誤
遷移至 Media3 後,您可能會看到有關不穩定 API 用法的 Lint 錯誤。這些 API 可放心使用,而 Lint 錯誤是我們新推出的二進位檔相容性保證所產生的副產品。如果您不需要嚴格的二進位檔相容性,可以使用 @OptIn 註解安全地略過這些錯誤。
背景
無論是 ExoPlayer 第 1 版或第 2 版,都無法嚴格保證後續版本之間的程式庫二進位檔相容性。ExoPlayer API 介面設計非常龐大,可讓應用程式自訂幾乎所有播放環節。ExoPlayer 後續版本有時會重新命名符號或其他破壞性變更 (例如介面上的新必要方法)。在大多數情況下,我們會在幾個版本中一併推出新符號,並淘汰舊符號,讓開發人員有時間遷移用法,藉此減輕這些中斷情形,但這並非總是可行。
這些重大變更導致 ExoPlayer 第 1 版和第 2 版程式庫的使用者遇到兩個問題:
- 從 升級至 ExoPlayer 版本可能會導致程式碼停止編譯。
- 如果應用程式直接依附 ExoPlayer,也透過中介程式庫依附 ExoPlayer,就必須確保這兩個依附元件的版本相同,否則二進位檔不相容可能會導致執行階段當機。
Media3 的改善項目
Media3 保證部分 API 介面的二進位檔相容性。凡是不保證二進位檔相容性的部分,都會標示 @UnstableApi。為明確區分,不穩定的 API 符號用法會產生 Lint 錯誤,除非以 @OptIn 註解。
從 ExoPlayer v2 遷移至 Media3 後,您可能會看到許多不穩定的 API 檢查錯誤。這可能會讓您覺得 Media3 比 ExoPlayer v2「不穩定」。但實情絕非如此。Media3 API 的「不穩定」部分與 ExoPlayer v2 API 介面的整體穩定程度相同,且 ExoPlayer v2 完全不提供穩定 Media3 API 介面的保證。不同之處在於,現在 Lint 錯誤會提醒您不同的穩定性等級。
處理不穩定的 API 檢查錯誤
如要瞭解如何使用 @OptIn 註解不穩定的 API 的 Java 和 Kotlin 用法,請參閱這些 Lint 錯誤的疑難排解章節。
已淘汰的 API
您可能會發現,Android Studio 會以刪除線標示對已淘汰 API 的呼叫。建議您改用適當的替代呼叫。 將滑鼠游標懸停在符號上,即可查看 JavaDoc,瞭解應改用哪個 API。
 
    程式碼範例和示範應用程式
- AndroidX Media3 會議示範應用程式 (行動裝置和 WearOS)
- 自訂操作
- 系統 UI 通知、MediaButton/BT
- Google 助理播放控制
 
- UAMP:Android 媒體播放器 (分支 media3) (行動裝置、AutomotiveOS)
- 系統 UI 通知、MediaButton/BT、播放續播
- Google 助理/WearOS 播放控制
- AutomotiveOS:自訂指令和登入
 
