AndroidX Media3 遷移指南

目前使用獨立 com.google.android.exoplayer2 版本的應用程式 程式庫和 androidx.media 應遷移至 androidx.media3。使用 遷移指令碼:用於遷移 Gradle 建構檔案、Java 和 ExoPlayer 的 Kotlin 來源檔案和 XML 版面配置檔案 2.19.1 至 AndroidX Media3 1.1.1

總覽

遷移前,請參閱下列章節以進一步瞭解 新 API 的優點、要遷移的 API 以及必要條件 應用程式專案應符合哪些條件

遷移至 Jetpack Media3 的理由

  • 這是新的 ExoPlayer 首頁,而 com.google.android.exoplayer2 是 。
  • 透過以下項目存取跨元件/程序的播放器 APIMediaBrowser/MediaController
  • 使用 MediaSessionMediaController API。
  • 透過精細的存取權控管機制通告播放功能。
  • 簡化應用程式,移除 MediaSessionConnectorPlayerNotificationManager
  • 使用 Media-compat 用戶端 API 回溯相容 (MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)

要遷移至 AndroidX Media3 的媒體 API

  • ExoPlayer 及其擴充功能
    這包含舊版 ExoPlayer 專案的所有模組,但 mediasession 模組停止。應用程式或模組 要遷移 com.google.android.exoplayer2 中的套件,可以使用 遷移指令碼。
  • MediaSessionConnector (視 androidx.media.* 個套件,共 androidx.media:media:1.4.3+ 個)
    移除 MediaSessionConnector 並使用 androidx.media3.session.MediaSession
  • MediaBrowserServiceCompat (視 androidx.media.* 個套件,共 androidx.media:media:1.4.3+ 個)
    androidx.media.MediaBrowserServiceCompat 的子類別遷移至 androidx.media3.session.MediaLibraryService 以及使用 MediaBrowserCompat.MediaItemandroidx.media3.common.MediaItem
  • MediaBrowserCompat (視 android.support.v4.media.* 個套件,共 androidx.media:media:1.4.3+ 個)
    使用 MediaBrowserCompatMediaControllerCompat:使用 androidx.media3.session.MediaBrowser androidx.media3.common.MediaItem

必要條件

  1. 確認專案受到原始碼控管

    確認遷移工具套用指令碼後,您可以輕鬆還原變更。 如果您尚未讓專案受到原始碼控管,建議您現在開始 一開始如果您因故不想這麼做 。

  2. 更新應用程式

    • 建議您更新專案,改用 最新版本的 ExoPlayer 程式庫,並移除任何 。如果您打算 使用指令碼執行遷移,該應用程式必須和 更新版本,並使用指令碼處理的版本。

    • 請將 compileSdkVersion 應用程式提高為至少 32

    • 將 Gradle 和 Android Studio Gradle 外掛程式升級至最新版本 適用於與上述更新版依附元件相容的版本適用對象 執行個體:

      • Android Gradle 外掛程式版本:7.1.0
      • Gradle 版本:7.4
    • 取代所有使用 asterix 的萬用字元匯入陳述式 (*) 並使用完整的匯入陳述式:刪除萬用字元 匯入陳述式,並使用 Android Studio 匯入完整的 Statement (F2 - Alt/Enter、F2 - Alt/Enter,...)。

    • com.google.android.exoplayer2.PlayerView 遷移至 com.google.android.exoplayer2.StyledPlayerView。此為必要步驟 因為這沒有 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

使用遷移指令碼

  1. 從以下位置的 ExoPlayer 專案代碼下載遷移指令碼: 與已更新應用程式版本相對應的 GitHub:

    curl -o media3-migration.sh \
      "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
    
  2. 將指令碼設為可執行狀態:

    chmod 744 media3-migration.sh
    
  3. 使用 --help 執行指令碼以瞭解各種選項。

  4. 使用 -l 執行指令碼,列出為您選取的一組檔案 遷移 (使用 -f 強制列出清單,但不顯示警告):

    ./media3-migration.sh -l -f /path/to/gradle/project/root
    
  5. 使用 -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 選項執行指令碼後,請完成以下手動步驟:

  1. 檢查指令碼如何更改程式碼:使用差異比較工具並修正問題 潛在問題 (如果您認為指令碼含有錯誤,請考慮提交錯誤 未傳遞 -f 選項時發生的一般問題)。
  2. 「Build Project」:使用 ./gradlew clean build 或在 Android 中使用 Studio 選擇「File」(檔案) > 將專案與 Gradle 檔案同步處理,然後版本 > 清除專案,然後建構>重新建構專案 (在 「建構 - 建構輸出內容」Android Studio 的分頁
,瞭解如何調查及移除這項存取權。

建議後續追蹤步驟:

  1. 解決採用不穩定的 API 相關錯誤
  2. 取代已淘汰的 API 呼叫:使用建議的替代 API。 將指標懸停在 Android Studio 中的警告上,然後參閱 JavaDoc ,瞭解該使用哪些項目 (而非特定呼叫)。
  3. 排序匯入陳述式:在 Android Studio 中開啟專案,然後 在專案檢視器中的套件資料夾節點上按一下滑鼠右鍵,然後選擇 針對包含變更的來源檔案的套件最佳化匯入作業

androidx.media3.session.MediaSession 取代 MediaSessionConnector

在舊版 MediaSessionCompat 環境中,MediaSessionConnector 是 負責同步處理播放器狀態與工作階段狀態 並接收來自適當委派給適當的 播放器方法。使用 AndroidX Media3 時,可以直接由 MediaSession 執行 而且不必使用連接器

  1. 移除所有 MediaSessionConnector 參考資料和使用情形:如果您先前使用 遷移 ExoPlayer 類別和套件的自動化指令碼,然後 指令碼可能使您的程式碼處於無法編譯的狀態 無法解析的 MediaSessionConnector。Android Studio 會顯示 在嘗試建構或啟動應用程式時,會顯示毀損的程式碼。

  2. 在您維護依附元件的 build.gradle 檔案中,新增 並移除 AndroidX Media3 工作階段模組的實作依附元件 舊版依附元件

    implementation "androidx.media3:media3-session:1.4.0"
    
  3. MediaSessionCompat 替換成 androidx.media3.session.MediaSession

  4. 在您建立舊版 MediaSessionCompat 的程式碼網站中,使用 androidx.media3.session.MediaSession.Builder打造 MediaSession傳遞播放器以建構工作階段建立工具。

    val player = ExoPlayer.Builder(context).build()
    mediaSession = MediaSession.Builder(context, player)
        .setSessionCallback(MySessionCallback())
        .build()
    
  5. 依據應用程式的需求實作 MySessionCallback。。如果 您要允許控制器將媒體項目新增至播放器、 MediaSession.Callback.onAddMediaItems()。這個平台服務遍及各 舊版 API 方法,可將媒體項目加入播放器中, 能夠回溯相容這包括 Media3 控制器的 MediaController.set/addMediaItems() 方法,如 以及TransportControls.prepareFrom*/playFrom* 方法。onAddMediaItems 實作範例可 您可以在工作階段試用版應用程式的 PlaybackService中找到。

  6. 在刪除工作階段的程式碼網站上釋出媒體工作階段 遷移作業前的注意事項:

    mediaSession?.run {
      player.release()
      release()
      mediaSession = null
    }
    

Media3 中的 MediaSessionConnector 功能

下表顯示處理功能的 Media3 API 先前在 MediaSessionConnector 中實作的結果。

MediaSessionConnectorAndroidX 媒體 3
CustomActionProvider MediaSession.Callback.onCustomCommand()/ MediaSession.setCustomLayout()
PlaybackPreparer MediaSession.Callback.onAddMediaItems() (prepare() 會在內部呼叫)
QueueNavigator ForwardingPlayer
QueueEditor MediaSession.Callback.onAddMediaItems()
RatingCallback MediaSession.Callback.onSetRating()
PlayerNotificationManager DefaultMediaNotificationProvider/ MediaNotification.Provider

MediaBrowserService 遷移至 MediaLibraryService

AndroidX Media3 導入了 MediaLibraryService,用來取代 MediaBrowserServiceCompatMediaLibraryService 及其超級叢集的 JavaDoc MediaSessionService 類別提供了關於 API 和 非同步程式設計模型

MediaLibraryService 回溯相容於 MediaBrowserService。使用 MediaBrowserCompatMediaControllerCompat,連線時不變更程式碼也能繼續使用 至 MediaLibraryService。對用戶端而言,無論您的應用程式是 使用 MediaLibraryService 或舊版 MediaBrowserServiceCompat

含有服務、活動和外部應用程式的應用程式元件圖表。
圖 1:媒體應用程式元件總覽
  1. 為確保回溯相容性正常運作,必須註冊兩項服務 介面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>
    
  2. 在您維護依附元件的 build.gradle 檔案中,新增 AndroidX Media3 工作階段模組和 移除舊版依附元件:

    implementation "androidx.media3:media3-session:1.4.0"
    
  3. 將服務變更為沿用 MediaLibraryService MediaBrowserService 如先前所述,MediaLibraryService 與舊版程式庫相容 MediaBrowserService。因此,服務採用的廣度 API 提供給客戶的選擇仍維持不變。所以應用程式可能會 實作 MediaBrowserService 所需的大部分邏輯 並配合新的 MediaLibraryService 進行調整

    與舊版服務的主要差異 MediaBrowserServiceCompat 如下:

    • 實作服務生命週期方法:需要 為 onCreate/onDestroy,其中 應用程式會配置/釋出程式庫工作階段、播放器和其他 再複習一下,機構節點 是所有 Google Cloud Platform 資源的根節點除了標準的服務生命週期方法外,應用程式 需要覆寫 onGetSession(MediaSession.ControllerInfo) 才能傳回 在 onCreate 中建構的 MediaLibrarySession

    • 實作 MediaLibraryService.MediaLibrarySessionCallback:建構 工作階段需要 導入 MediaLibraryService.MediaLibrarySessionCallback 實際的網域 API 方法與其覆寫 舊版服務,您將覆寫 請改為使用「MediaLibrarySession.Callback」。

      接著,回呼會用於建構 MediaLibrarySession

      mediaLibrarySession =
            MediaLibrarySession.Builder(this, player, MySessionCallback())
               .build()
      

      找出 API 中的 MediaLibrarySessionCallback 完整 API 說明文件。

    • 實作 MediaSession.Callback.onAddMediaItems():回呼 供應onAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>) 目前和舊版的 API 方法,可將媒體項目加入播放器 能以回溯相容的方式播放這包括 MediaController.set/addMediaItems() 方法, 以及 TransportControls.prepareFrom*/playFrom* 方法。回呼的範例實作 您可以在工作階段示範應用程式的 PlaybackService 中找到

    • AndroidX Media3 改用 androidx.media3.common.MediaItem MediaBrowserCompat.MediaItemMediaMetadataCompat 中。零件 與舊版類別繫結的程式碼有部分必須隨之變更 或對應至 Media3 MediaItem

    • 一般而言,非同步程式設計模型變更為 Futures 與可卸離的 Result 方法 MediaBrowserServiceCompat。您的服務實作可能會傳回 非同步 ListenableFuture,而不是卸離結果或 傳回立即的 Future 以直接傳回值

移除 PlayerNotificationManager

MediaLibraryService 會自動支援媒體通知,且 PlayerNotificationManager您可以使用 MediaLibraryServiceMediaSessionService

應用程式可以透過將自訂欄位設為自訂通知 onCreate()中的 MediaNotification.Provider,用來取代 DefaultMediaNotificationProvider。接著 MediaLibraryService 會處理 在前景啟動服務。

覆寫 MediaLibraryService.updateNotification() 即可讓應用程式進一步 發布通知及啟動/停止服務 在前景執行

使用 MediaBrowser 遷移用戶端程式碼

在 AndroidX Media3 中,MediaBrowser 會實作 MediaController/Player 介面,除了瀏覽媒體之外,也可以用來控制媒體播放 資源庫。如果您必須建立 MediaBrowserCompatMediaControllerCompat,您也可以只使用 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 v1 或 v2 都無法保證二進位檔相容性 程式庫和程式庫之間的差異ExoPlayer API 介面非常相似 以便讓應用程式自訂大部分的功能 播放。後續版本的 ExoPlayer 偶爾會出現符號 重新命名或其他破壞性變更 (例如介面中的新必要方法)。於 大多數情況下,新星球上 以及淘汰幾個版本的舊符號,讓開發人員 但並非每次都可能進行此程序

這些破壞性變更造成 ExoPlayer v1 的使用者有兩個問題 和第 2 版程式庫:

  1. 升級至 ExoPlayer 版本可能會導致程式碼停止編譯。
  2. 直接與 ExoPlayer 透過中繼系統且依附於 ExoPlayer 的應用程式 必須確保兩個依附元件版本相同 否則二進位檔的不相容問題可能會導致執行階段異常終止。

Media3 中的改善項目

Media3 保證部分 API 介面的二進位檔相容性。 「無法」保證二進位檔相容性的部分會標示為 @UnstableApi。為了清楚區分實際情況 除非 API 符號加上 @OptIn 註解,否則 API 符號會產生 Lint 錯誤。

從 ExoPlayer v2 遷移至 Media3 後,您會看到許多不穩定的 API lint 錯誤這可能使 Media3 看起來「較不穩定」比 ExoPlayer 第 2 版。但此聲明與事實不符。「不穩定」Media3 API 的組成部分 穩定性和 ExoPlayer v2 API 介面的「整個」等級;以及 ExoPlayer v2 不提供穩定版 Media3 API 介面的保證: 全部。差別在於,Lint 錯誤現在會提醒您 穩定性。

處理不穩定的 API Lint 錯誤

如要進一步瞭解如何執行這些 Lint 錯誤,請參閱「這些 Lint 錯誤的疑難排解」一節。 使用 @OptIn 為不穩定 API 的 Java 和 Kotlin 使用情形加上註解。

已淘汰的 API

您可能會注意到在 Android 中,對已淘汰 API 的呼叫會加上刪除線 建議您以適當的替代方案取代這類呼叫。 將滑鼠遊標懸停在符號上,即可查看已改用哪個 API 的 JavaDoc。

螢幕截圖:如何以已淘汰的方法顯示 JavaDoc
圖 3:Android Studio 中的 JavaDoc 工具提示,針對任何已淘汰的符號提供替代建議。

程式碼範例和試用版應用程式