Các ứng dụng hiện đang dùng thư viện com.google.android.exoplayer2
độc lập và androidx.media
nên di chuyển sang androidx.media3
. Sử dụng tập lệnh di chuyển để di chuyển các tệp bản dựng gradle, tệp nguồn Java và Kotlin cũng như các tệp bố cục XML từ ExoPlayer
2.19.1
sang AndroidX Media3 1.1.1
.
Tổng quan
Trước khi di chuyển, hãy xem lại các phần sau để tìm hiểu thêm về lợi ích của các API mới, API cần di chuyển và những điều kiện tiên quyết mà dự án của ứng dụng cần đáp ứng.
Lý do bạn nên chuyển sang Jetpack Media3
- Đây là ngôi nhà mới của ExoPlayer, trong khi
com.google.android.exoplayer2
đã ngừng hoạt động. - Truy cập API Trình phát trên các thành phần/quy trình bằng
MediaBrowser
/MediaController
. - Hãy sử dụng các tính năng mở rộng của API
MediaSession
vàMediaController
. - Quảng cáo khả năng phát bằng chế độ kiểm soát quyền truy cập chi tiết.
- Đơn giản hoá ứng dụng của bạn bằng cách xoá
MediaSessionConnector
vàPlayerNotificationManager
. - Tương thích ngược với các API ứng dụng có khả năng tương thích ngược với nội dung đa phương tiện (
MediaBrowserCompat
/MediaControllerCompat
/MediaMetadataCompat
)
Media API để di chuyển sang AndroidX Media3
- ExoPlayer và các tiện ích của nó
Bao gồm tất cả các mô-đun của dự án ExoPlayer cũ, ngoại trừ mô-đun mediasession đã ngừng hoạt động. Bạn có thể di chuyển các ứng dụng hoặc mô-đun tuỳ thuộc vào các gói trongcom.google.android.exoplayer2
bằng tập lệnh di chuyển. - MediaSessionRenderer (tuỳ thuộc vào gói
androidx.media.*
củaandroidx.media:media:1.4.3+
)
XoáMediaSessionConnector
và sử dụngandroidx.media3.session.MediaSession
. - MediaBrowserServiceCompat (tuỳ thuộc vào gói
androidx.media.*
củaandroidx.media:media:1.4.3+
)
Di chuyển các lớp con củaandroidx.media.MediaBrowserServiceCompat
sangandroidx.media3.session.MediaLibraryService
và mã bằng cách sử dụngMediaBrowserCompat.MediaItem
đếnandroidx.media3.common.MediaItem
. - MediaBrowserCompat (tuỳ thuộc vào các gói
android.support.v4.media.*
củaandroidx.media:media:1.4.3+
)
Di chuyển mã ứng dụng khách bằngMediaBrowserCompat
hoặcMediaControllerCompat
để sử dụngandroidx.media3.session.MediaBrowser
vớiandroidx.media3.common.MediaItem
.
Điều kiện tiên quyết
Đảm bảo dự án của bạn nằm trong chế độ kiểm soát nguồn
Đảm bảo bạn có thể dễ dàng huỷ bỏ các thay đổi mà các công cụ di chuyển theo tập lệnh đã áp dụng. Nếu bạn chưa có dự án ở chế độ kiểm soát nguồn, thì bây giờ là thời điểm thích hợp để bắt đầu. Nếu vì lý do nào đó bạn không muốn làm việc đó, hãy tạo một bản sao dự phòng của dự án trước khi bắt đầu quá trình di chuyển.
Cập nhật ứng dụng
Bạn nên cập nhật dự án để sử dụng phiên bản thư viện ExoPlayer mới nhất và xoá mọi lệnh gọi đến các phương thức không dùng nữa. Nếu có ý định sử dụng tập lệnh để di chuyển, bạn cần so khớp phiên bản mà bạn đang cập nhật với phiên bản do tập lệnh xử lý.
Tăng compileSdkVersion của ứng dụng lên ít nhất là 32.
Nâng cấp Gradle và trình bổ trợ Gradle cho Android Studio lên một phiên bản gần đây để hoạt động với các phần phụ thuộc đã cập nhật ở trên. Ví dụ:
- Phiên bản trình bổ trợ Android cho Gradle: 7.1.0
- Phiên bản Gradle: 7.4
Thay thế tất cả các câu lệnh nhập ký tự đại diện đang dùng dấu sao (*) và sử dụng câu lệnh nhập đủ điều kiện: Xoá câu lệnh nhập ký tự đại diện rồi sử dụng Android Studio để nhập các câu lệnh đủ điều kiện (F2 – Alt/Enter, F2 – Alt/Enter, ...).
Di chuyển từ
com.google.android.exoplayer2.PlayerView
sangcom.google.android.exoplayer2.StyledPlayerView
. Điều này là cần thiết vì không có công thức nào tương đương vớicom.google.android.exoplayer2.PlayerView
trong AndroidX Media3.
Di chuyển ExoPlayer có hỗ trợ tập lệnh
Tập lệnh sẽ hỗ trợ việc di chuyển từ com.google.android.exoplayer2
sang cấu trúc gói và mô-đun mới trong androidx.media3
. Tập lệnh này áp dụng một số bước kiểm tra xác thực cho dự án của bạn và in cảnh báo nếu quá trình xác thực không thành công.
Nếu không, thao tác này sẽ áp dụng mối liên kết của các lớp và gói đã đổi tên trong các tài nguyên của dự án Android gradle được viết bằng Java hoặc Kotlin.
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
Sử dụng tập lệnh di chuyển
Tải tập lệnh di chuyển từ thẻ của dự án ExoPlayer trên GitHub xuống tương ứng với phiên bản mà bạn đã cập nhật ứng dụng của mình thành:
curl -o media3-migration.sh \ "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"
Làm cho tập lệnh có thể thực thi:
chmod 744 media3-migration.sh
Chạy tập lệnh bằng
--help
để tìm hiểu về các tuỳ chọn.Chạy tập lệnh bằng
-l
để liệt kê tập hợp các tệp được chọn để di chuyển (sử dụng-f
để buộc hiển thị trang thông tin mà không có cảnh báo):./media3-migration.sh -l -f /path/to/gradle/project/root
Chạy tập lệnh bằng
-m
để ánh xạ các gói, lớp và mô-đun với Media3. Việc chạy tập lệnh có tuỳ chọn-m
sẽ áp dụng nội dung thay đổi cho các tệp đã chọn.- Dừng khi gặp lỗi xác thực mà không thay đổi gì
./media3-migration.sh -m /path/to/gradle/project/root
- Thực thi bắt buộc
Nếu tập lệnh phát hiện lỗi vi phạm các điều kiện tiên quyết, thì bạn có thể thực thi quá trình di chuyển bằng cờ
-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
Hãy hoàn tất các bước thủ công sau khi chạy tập lệnh với tuỳ chọn -m
:
- Kiểm tra cách tập lệnh đã thay đổi mã của bạn: Sử dụng một công cụ so sánh và khắc phục các vấn đề tiềm ẩn (hãy cân nhắc báo lỗi nếu bạn cho rằng tập lệnh có một sự cố chung đã xảy ra mà không truyền tuỳ chọn
-f
). - Xây dựng dự án: Sử dụng
./gradlew clean build
hoặc trong Android Studio, hãy chọn File > Sync Project with Gradle Files (Tệp > Đồng bộ hoá dự án với tệp Gradle), sau đó chọn Build > Refresh project (Tạo > Làm sạch dự án) rồi chọn Build > Rebuild project (Bản dựng > Tạo lại dự án) (theo dõi bản dựng của bạn trong thẻ "Build - Build Output" (Tạo – Đầu ra của bản dựng) của Android Studio.
Các bước tiếp theo bạn nên thực hiện:
- Xử lý trạng thái chọn nhận lỗi liên quan đến việc sử dụng API không ổn định.
- Thay thế các lệnh gọi API không dùng nữa: Sử dụng API thay thế được đề xuất. Giữ con trỏ trên cảnh báo trong Android Studio rồi tham khảo JavaDoc của biểu tượng không dùng nữa để tìm hiểu nội dung cần sử dụng thay cho một lệnh gọi nhất định.
- Sắp xếp câu lệnh nhập: Mở dự án trong Android Studio, sau đó nhấp chuột phải vào nút thư mục gói trong trình xem dự án và chọn Optimize Import (Tối ưu hoá lệnh nhập) trên các gói chứa tệp nguồn đã thay đổi.
Thay thế MediaSessionConnector
bằng androidx.media3.session.MediaSession
.
Trong thế giới MediaSessionCompat
cũ, MediaSessionConnector
chịu trách nhiệm đồng bộ hoá trạng thái của người chơi với trạng thái của phiên và nhận lệnh từ những bộ điều khiển cần uỷ quyền cho các phương thức người chơi thích hợp. Với AndroidX Media3, việc này được MediaSession
thực hiện trực tiếp mà không cần trình kết nối.
Xoá tất cả thông tin tham chiếu và cách sử dụng MediaSessionRenderer: Nếu bạn đã sử dụng tập lệnh tự động để di chuyển các lớp và gói ExoPlayer, thì tập lệnh có thể đã để mã của bạn ở trạng thái không biên dịch được do
MediaSessionConnector
không thể giải quyết được. Android Studio sẽ hiển thị cho bạn mã bị hỏng khi bạn cố gắng tạo hoặc khởi động ứng dụng.Trong tệp
build.gradle
mà bạn duy trì các phần phụ thuộc, hãy thêm phần phụ thuộc triển khai vào mô-đun phiên AndroidX Media3 và xoá phần phụ thuộc cũ:implementation "androidx.media3:media3-session:1.3.1"
Thay thế
MediaSessionCompat
bằngandroidx.media3.session.MediaSession
.Tại trang web mã mà bạn đã tạo
MediaSessionCompat
cũ, hãy sử dụngandroidx.media3.session.MediaSession.Builder
để tạoMediaSession
. Truyền trình phát để tạo trình tạo phiên.val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player) .setSessionCallback(MySessionCallback()) .build()
Triển khai
MySessionCallback
theo yêu cầu của ứng dụng (không bắt buộc). Nếu bạn muốn cho phép tay điều khiển thêm mục nội dung nghe nhìn vào trình phát, hãy triển khaiMediaSession.Callback.onAddMediaItems()
. API này phân phát nhiều phương thức API hiện tại và cũ giúp thêm mục nội dung đa phương tiện vào trình phát để phát theo cách tương thích ngược. Trong đó bao gồm các phương thứcMediaController.set/addMediaItems()
của bộ điều khiển Media3, cũng như các phương thứcTransportControls.prepareFrom*/playFrom*
của API cũ. Bạn có thể tìm thấy ví dụ về cách triển khaionAddMediaItems
trongPlaybackService
của ứng dụng minh hoạ phiên.Phát hành phiên phát nội dung đa phương tiện tại trang web mã mà bạn đã huỷ phiên hoạt động trước khi di chuyển:
mediaSession?.run { player.release() release() mediaSession = null }
Chức năng MediaSessionConnector
trong Media3
Bảng sau đây cho thấy các API Media3 xử lý chức năng đã triển khai trước đó trong MediaSessionConnector
.
MediaSessionTrình kết nối | AndroidX Media3 |
---|---|
CustomActionProvider |
MediaSession.Callback.onCustomCommand()/
MediaSession.setCustomLayout() |
PlaybackPreparer |
MediaSession.Callback.onAddMediaItems()
(prepare() được gọi nội bộ)
|
QueueNavigator |
ForwardingPlayer |
QueueEditor |
MediaSession.Callback.onAddMediaItems() |
RatingCallback |
MediaSession.Callback.onSetRating() |
PlayerNotificationManager |
DefaultMediaNotificationProvider/
MediaNotification.Provider |
Di chuyển MediaBrowserService
sang MediaLibraryService
AndroidX Media3 ra mắt MediaLibraryService
thay thế cho MediaBrowserServiceCompat
. JavaDoc của MediaLibraryService
và lớp cấp cao MediaSessionService
của lớp này cung cấp thông tin giới thiệu hữu ích về API và mô hình lập trình không đồng bộ của dịch vụ.
MediaLibraryService
tương thích ngược với MediaBrowserService
. Một ứng dụng khách đang sử dụng MediaBrowserCompat
hoặc MediaControllerCompat
sẽ tiếp tục hoạt động mà không cần thay đổi mã khi kết nối với một MediaLibraryService
. Đối với ứng dụng, thông tin rõ ràng cho biết ứng dụng của bạn đang dùng MediaLibraryService
hay MediaBrowserServiceCompat
cũ.
![Sơ đồ thành phần ứng dụng với dịch vụ, hoạt động và ứng dụng bên ngoài.](https://developer.android.com/static/media/images/overview.png?authuser=6&hl=vi)
Để khả năng tương thích ngược hoạt động, bạn cần đăng ký cả hai giao diện dịch vụ với dịch vụ của mình trong
AndroidManifest.xml
. Bằng cách này, máy khách sẽ tìm thấy dịch vụ của bạn bằng giao diện dịch vụ bắt buộc:<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>
Trong tệp
build.gradle
mà bạn duy trì các phần phụ thuộc, hãy thêm phần phụ thuộc triển khai vào mô-đun phiên AndroidX Media3 và xoá phần phụ thuộc cũ:implementation "androidx.media3:media3-session:1.3.1"
Thay đổi dịch vụ để kế thừa từ
MediaLibraryService
thay vìMediaBrowserService
Như đã đề cập trước đó,MediaLibraryService
tương thích vớiMediaBrowserService
cũ. Theo đó, API rộng hơn mà dịch vụ cung cấp cho khách hàng vẫn giống nhau. Vì vậy, có khả năng một ứng dụng có thể giữ hầu hết logic cần thiết để triển khaiMediaBrowserService
và điều chỉnh cho phù hợp vớiMediaLibraryService
mới.Sau đây là những điểm khác biệt chính so với
MediaBrowserServiceCompat
cũ:Triển khai các phương thức trong vòng đời dịch vụ: Các phương thức cần được ghi đè trên chính dịch vụ là
onCreate/onDestroy
, trong đó ứng dụng phân bổ/giải phóng phiên thư viện, trình phát và các tài nguyên khác. Ngoài các phương thức tiêu chuẩn trong vòng đời dịch vụ, ứng dụng cần ghi đèonGetSession(MediaSession.ControllerInfo)
để trả vềMediaLibrarySession
được tạo trongonCreate
.Triển khai MediaLibraryService.MediaLibrarySessionCallback: Việc tạo một phiên cần có một
MediaLibraryService.MediaLibrarySessionCallback
triển khai các phương thức API miền thực tế. Vì vậy, thay vì ghi đè các phương thức API của dịch vụ cũ, bạn sẽ ghi đè các phương thức củaMediaLibrarySession.Callback
.Sau đó, lệnh gọi lại được dùng để tạo
MediaLibrarySession
:mediaLibrarySession = MediaLibrarySession.Builder(this, player, MySessionCallback()) .build()
Tìm API đầy đủ của MediaLibrarySessionCallback trong tài liệu về API.
Triển khai
MediaSession.Callback.onAddMediaItems()
: Lệnh gọi lạionAddMediaItems(MediaSession, ControllerInfo, List<MediaItem>)
phân phát nhiều phương thức API hiện tại và cũ, giúp thêm các mục nội dung đa phương tiện vào trình phát để phát theo cách có khả năng tương thích ngược. Trong đó bao gồm các phương thứcMediaController.set/addMediaItems()
của bộ điều khiển Media3, cũng như các phương thứcTransportControls.prepareFrom*/playFrom*
của API cũ. Bạn có thể xem cách triển khai lệnh gọi lại mẫu trongPlaybackService
của ứng dụng minh hoạ phiên.AndroidX Media3 đang sử dụng
androidx.media3.common.MediaItem
thay vì MediaBrowserCompat.MediaItem và MediaMetadataCompat. Các phần mã liên kết với các lớp cũ cần được thay đổi cho phù hợp hoặc ánh xạ đếnMediaItem
Media3.Mô hình lập trình không đồng bộ chung đã thay đổi thành
Futures
để trái ngược với phương phápResult
có thể tháo rời củaMediaBrowserServiceCompat
. Quá trình triển khai dịch vụ của bạn có thể trả về mộtListenableFuture
không đồng bộ thay vì tách kết quả hoặc trả về một Future ngay lập tức để trực tiếp trả về một giá trị.
Xoá PlayerNotificationManager
MediaLibraryService
tự động hỗ trợ thông báo về nội dung nghe nhìn và bạn có thể xoá PlayerNotificationManager
khi sử dụng MediaLibraryService
hoặc MediaSessionService
.
Ứng dụng có thể tuỳ chỉnh thông báo bằng cách đặt một MediaNotification.Provider
tuỳ chỉnh trong onCreate()
thay thế DefaultMediaNotificationProvider
. Sau đó, MediaLibraryService
sẽ đảm nhận việc khởi động dịch vụ ở nền trước theo yêu cầu.
Bằng cách ghi đè MediaLibraryService.updateNotification()
, ứng dụng có thể nắm toàn quyền sở hữu hơn nữa đối với việc đăng thông báo và bắt đầu/dừng dịch vụ ở nền trước theo yêu cầu.
Di chuyển mã ứng dụng bằng MediaBrowser
Với AndroidX Media3, MediaBrowser
triển khai các giao diện MediaController/Player
và có thể dùng để điều khiển việc phát nội dung nghe nhìn bên cạnh việc duyệt qua thư viện nội dung nghe nhìn. Nếu phải tạo MediaBrowserCompat
và MediaControllerCompat
trong thế giới cũ, bạn có thể làm tương tự bằng cách chỉ sử dụng MediaBrowser
trong Media3.
Bạn có thể tạo MediaBrowser
và chờ kết nối với dịch vụ:
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)
}
Hãy xem phần Điều khiển chế độ phát trong phiên phát nội dung đa phương tiện để tìm hiểu cách tạo MediaController
để điều khiển chế độ phát trong nền.
Các bước tiếp theo và dọn dẹp
Lỗi API không ổn định
Sau khi chuyển sang Media3, bạn có thể thấy lỗi tìm lỗi mã nguồn về cách sử dụng API không ổn định.
Các API này an toàn khi sử dụng và lỗi tìm lỗi mã nguồn là sản phẩm phụ trong quá trình đảm bảo khả năng tương thích nhị phân mới của chúng tôi. Nếu không yêu cầu khả năng tương thích nhị phân nghiêm ngặt, bạn có thể chặn các lỗi này một cách an toàn bằng chú giải @OptIn
.
Thông tin khái quát
Cả ExoPlayer v1 hoặc v2 đều không cung cấp sự đảm bảo nghiêm ngặt về khả năng tương thích nhị phân của thư viện giữa các phiên bản tiếp theo. Giao diện API ExoPlayer có thiết kế rất lớn để cho phép các ứng dụng tuỳ chỉnh gần như mọi khía cạnh của quá trình phát. Các phiên bản tiếp theo của ExoPlayer đôi khi sẽ đổi tên biểu tượng hoặc những thay đổi có thể gây lỗi khác (ví dụ: các phương thức mới bắt buộc trên giao diện). Trong hầu hết các trường hợp, những sự cố này đã được giảm thiểu bằng cách ra mắt biểu tượng mới, ngoài việc ngừng sử dụng biểu tượng cũ trong một số phiên bản, để nhà phát triển có thời gian di chuyển cách sử dụng. Tuy nhiên, không phải lúc nào cũng có thể làm như vậy.
Những thay đổi có thể gây lỗi này dẫn đến 2 vấn đề cho người dùng thư viện ExoPlayer v1 và v2:
- Việc nâng cấp từ phiên bản ExoPlayer có thể khiến mã ngừng biên dịch.
- Một ứng dụng phụ thuộc vào ExoPlayer cả trực tiếp và thông qua thư viện trung gian phải đảm bảo rằng cả hai phần phụ thuộc đều là cùng một phiên bản, nếu không sự không tương thích của tệp nhị phân có thể dẫn đến sự cố trong thời gian chạy.
Những cải tiến trong Media3
Media3 đảm bảo khả năng tương thích nhị phân cho một nhóm nhỏ nền tảng API. Các phần không đảm bảo khả năng tương thích nhị phân sẽ được đánh dấu bằng @UnstableApi
. Để làm rõ sự khác biệt này, việc sử dụng biểu tượng API không ổn định sẽ tạo ra lỗi tìm lỗi mã nguồn (lint), trừ phi các biểu tượng này được chú thích bằng @OptIn
.
Sau khi di chuyển từ ExoPlayer v2 sang Media3, bạn có thể thấy nhiều lỗi tìm lỗi mã nguồn API không ổn định. Điều này có thể khiến Media3 có vẻ "kém ổn định" hơn so với ExoPlayer phiên bản 2. Tuy nhiên, trường hợp này không đúng. Các phần "không ổn định" của API Media3 có cùng mức độ ổn định như toàn bộ giao diện API ExoPlayer phiên bản 2 và bảo đảm về khu vực API Media3 ổn định hoàn toàn không có trong ExoPlayer phiên bản 2. Điểm khác biệt đơn giản là lỗi tìm lỗi mã nguồn giờ đây sẽ cảnh báo bạn về các mức độ ổn định khác nhau.
Xử lý các lỗi tìm lỗi mã nguồn API không ổn định
Hãy xem phần khắc phục sự cố về các lỗi tìm lỗi mã nguồn này để biết thông tin chi tiết về cách chú giải cách sử dụng Java và Kotlin của các API không ổn định bằng @OptIn
.
API không dùng nữa
Bạn có thể nhận thấy rằng các lệnh gọi đến các API không dùng nữa sẽ bị gạch ngang trong Android Studio. Bạn nên thay thế các lệnh gọi đó bằng phương thức thay thế phù hợp. Hãy di chuột qua biểu tượng này để xem JavaDoc cho biết cần sử dụng API nào.
![Ảnh chụp màn hình: Cách hiển thị JavaDoc với phương thức thay thế cho phương thức không dùng nữa](https://developer.android.com/static/media/media3/exoplayer/images/deprecation.png?authuser=6&hl=vi)
Mã mẫu và ứng dụng minh hoạ
- Ứng dụng minh hoạ phiên AndroidX Media3 (thiết bị di động và WearOS)
- Thao tác tuỳ chỉnh
- Thông báo trên giao diện người dùng hệ thống, MediaButton/BT
- Điều khiển chế độ phát của Trợ lý Google
- UAMP: Android Media Player (branch media3) (thiết bị di động, AutomotiveOS)
- Thông báo giao diện người dùng hệ thống, MediaButton/BT, Tiếp tục phát
- Điều khiển chế độ phát cho Trợ lý Google/WearOS
- AutomotiveOS: lệnh tuỳ chỉnh và thông tin đăng nhập