目前使用独立 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
和MediaController
API 的扩展功能。 - 通过精细访问权限控制来宣传播放功能。
- 通过移除
MediaSessionConnector
和PlayerNotificationManager
来简化应用。 - 与媒体兼容客户端 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.session.MediaBrowser
和androidx.media3.common.MediaItem
。
前提条件
确保您的项目处于源代码控制之下
确保您可以轻松还原脚本化迁移工具所应用的更改。 如果您的项目尚未纳入源代码控制,现在是开始使用源代码控制的好时机。如果出于某种原因,您不想这样做,请在开始迁移之前备份项目。
更新应用
我们建议您更新项目以使用 ExoPlayer 库的最新版本,并移除对已弃用方法的任何调用。如果您打算使用脚本进行迁移,则需要确保您要更新到的版本与脚本处理的版本一致。
将应用的 compileSdkVersion 提高到至少 32。
将 Gradle 和 Android Studio Gradle 插件升级到可与上述更新后的依赖项搭配使用的最新版本。例如:
- Android Gradle 插件版本:7.1.0
- Gradle 版本:7.4
替换所有使用星号 (*) 的通配符 import 语句,并使用完全限定的 import 语句:删除通配符 import 语句,并使用 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
选项引入的常规问题,请考虑提交bug)。 - 构建项目:使用
./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,了解应使用什么来代替给定的调用。
- 对 import 语句进行排序:在 Android Studio 中打开项目,然后在项目查看器中右键点击软件包文件夹节点,并选择包含已更改源文件的软件包的 Optimize imports。
将 MediaSessionConnector
替换为 androidx.media3.session.MediaSession
在旧版 MediaSessionCompat
世界中,MediaSessionConnector
负责将播放器的状态与会话的状态同步,并接收来自需要委托给相应播放器方法的控制器的命令。借助 AndroidX Media3,可以直接通过 MediaSession
完成此操作,而无需连接器。
移除对 MediaSessionConnector 的所有引用和使用:如果您使用自动化脚本迁移 ExoPlayer 类和软件包,则该脚本可能会使您的代码处于无法编译的状态,因为
MediaSessionConnector
无法解析。当您尝试构建或启动应用时,Android Studio 会显示损坏的代码。在您维护依赖项的
build.gradle
文件中,向 AndroidX Media3 会话模块添加实现依赖项,并移除旧版依赖项:implementation "androidx.media3:media3-session:1.7.1"
将
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 引入了取代 MediaBrowserServiceCompat
的 MediaLibraryService
。MediaLibraryService
及其超类 MediaSessionService
的 JavaDoc 很好地介绍了该 API 和服务的异步编程模型。
MediaLibraryService
向后兼容 MediaBrowserService
。使用 MediaBrowserCompat
或 MediaControllerCompat
的客户端应用在连接到 MediaLibraryService
时,无需更改代码即可继续运行。对于客户端,您的应用使用的是 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.7.1"
将您的服务更改为从
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。与旧版类相关联的部分代码需要相应更改,或者映射到 Media3MediaItem
。与
MediaBrowserServiceCompat
的可分离Result
方法相比,常规的异步编程模型已更改为Futures
。您的服务实现可以返回异步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 v1 还是 v2,都未严格保证库在后续版本之间的二进制兼容性。ExoPlayer API 表面在设计上非常大,以便应用能够自定义播放的几乎所有方面。后续版本的 ExoPlayer 会不时引入符号重命名或其他重大变更(例如,接口上的新必需方法)。在大多数情况下,这些中断通过以下方式得到缓解:在弃用旧符号的同时引入新符号,并持续几个版本,以便开发者有时间迁移其用法,但并非总是如此。
这些重大变更导致 ExoPlayer v1 和 v2 库的用户遇到两个问题:
- 从升级到 ExoPlayer 版本可能会导致代码停止编译。
- 如果应用直接依赖于 ExoPlayer,同时又通过中间库依赖于 ExoPlayer,则必须确保这两个依赖项的版本相同,否则二进制文件不兼容可能会导致运行时崩溃。
Media3 中的改进
Media3 保证了部分 API Surface 的二进制兼容性。不保证二进制兼容性的部分标记为 @UnstableApi
。为了明确区分,除非使用 @OptIn
注释,否则使用不稳定 API 符号会生成 lint 错误。
从 ExoPlayer v2 迁移到 Media3 后,您可能会看到许多不稳定的 API lint 错误。这可能会让人觉得 Media3 比 ExoPlayer v2“不太稳定”。其实不是这样。Media3 API 的“不稳定”部分与整个 ExoPlayer v2 API Surface 具有相同的稳定性级别,而稳定版 Media3 API Surface 的保证在 ExoPlayer v2 中根本无法实现。不同之处在于,lint 错误现在会提醒您注意不同的稳定性级别。
处理不稳定的 API lint 错误
如需详细了解如何使用 @OptIn
注解来注释 Java 和 Kotlin 对不稳定 API 的使用情况,请参阅有关这些 lint 错误的问题排查部分。
已弃用的 API
您可能会注意到,在 Android Studio 中,对已弃用的 API 的调用会带有删除线。我们建议您将此类调用替换为合适的替代方案。将鼠标悬停在符号上,即可查看 JavaDoc,其中说明了应改用哪个 API。

代码示例和演示应用
- AndroidX Media3 会话演示应用(移动设备和 WearOS)
- 自定义操作
- 系统界面通知、MediaButton/BT
- Google 助理播放控制
- UAMP:Android 媒体播放器(分支 media3)(移动设备、AutomotiveOS)
- 系统界面通知、MediaButton/BT、继续播放
- Google 助理/WearOS 播放控制
- AutomotiveOS:自定义命令和登录