Các ứng dụng hiện đang sử 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ư 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 các phần sau để tìm hiểu thêm về lợi ích của API mới, API cần di chuyển và các điều kiện tiên quyết mà dự án của ứng dụng cần đáp ứng.
Lý do nên di chuyển sang Jetpack Media3
- Đây là không gian mới của ExoPlayer, còn
com.google.android.exoplayer2sẽ ngừng hoạt động. - Truy cập vào Player API trên các thành phần/quy trình bằng
MediaBrowser/MediaController. - Sử dụng các chức năng mở rộng của API
MediaSessionvàMediaController. - Quảng cáo các chức năng phát bằng quyền kiểm soát truy cập chi tiết.
- Đơn giản hoá ứng dụng bằng cách xoá
MediaSessionConnectorvàPlayerNotificationManager. - Tương thích ngược với API ứng dụng khách media-compat (
MediaBrowserCompat/MediaControllerCompat/MediaMetadataCompat)
Các API đa phương tiện cần di chuyển sang AndroidX Media3
- ExoPlayer và các tiện ích của ExoPlayer
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 phụ thuộc vào các gói trongcom.google.android.exoplayer2bằng tập lệnh di chuyển. - MediaSessionConnector (tuỳ thuộc vào các gói
androidx.media.*củaandroidx.media:media:1.4.3+)
XoáMediaSessionConnectorvà sử dụngandroidx.media3.session.MediaSession. - MediaBrowserServiceCompat (tuỳ thuộc vào các gói
androidx.media.*củaandroidx.media:media:1.4.3+)
Di chuyển các lớp con củaandroidx.media.MediaBrowserServiceCompatsangandroidx.media3.session.MediaLibraryServicevà mã sử dụngMediaBrowserCompat.MediaItemsangandroidx.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 bằngMediaBrowserCompathoặcMediaControllerCompatđể sử dụngandroidx.media3.session.MediaBrowservớiandroidx.media3.common.MediaItem.
Điều kiện tiên quyết
Đảm bảo dự án của bạn nằm trong hệ thống kiểm soát nguồn
Đảm bảo bạn có thể dễ dàng huỷ bỏ các thay đổi do công cụ di chuyển theo tập lệnh áp dụng. Nếu bạn chưa có dự án trong hệ thống 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 đó mà bạn không muốn làm việc này, hãy tạo một bản sao lưu dự án trước khi bắt đầu 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 mới nhất của thư viện ExoPlayer và xoá mọi lệnh gọi đến các phương thức không dùng nữa. Nếu dự định sử dụng tập lệnh để di chuyển, bạn cần phải 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 của Android Studio lên phiên bản mới nhất 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âu lệnh nhập ký tự đại diện đang sử dụng dấu hoa thị (*) 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 và sử dụng Android Studio để nhập câu lệnh đủ điều kiện (F2 – Alt/Enter, F2 – Alt/Enter, ...).
Di chuyển từ
com.google.android.exoplayer2.PlayerViewsangcom.google.android.exoplayer2.StyledPlayerView. Điều này là cần thiết vì không có lớp tương đương vớicom.google.android.exoplayer2.PlayerViewtrong AndroidX Media3.
Di chuyển ExoPlayer bằng tính năng hỗ trợ tập lệnh
Tập lệnh này 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ố quy trình kiểm tra xác thực cho dự án của bạn và đưa ra cảnh báo nếu không xác thực được.
Nếu không, công cụ này sẽ áp dụng các mối liên kết của các lớp và gói đã đổi tên trong tài nguyên của một 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 xuống từ thẻ của dự án ExoPlayer trên GitHub tương ứng với phiên bản mà bạn đã cập nhật ứng dụng:
curl -o media3-migration.sh \ "https://raw.githubusercontent.com/google/ExoPlayer/r2.19.1/media3-migration.sh"Đặt tập lệnh ở trạng thái có thể thực thi:
chmod 744 media3-migration.shChạy tập lệnh bằng
--helpđể tìm hiểu về các lựa 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 liệt kê mà không có cảnh báo):./media3-migration.sh -l -f /path/to/gradle/project/rootChạy tập lệnh bằng
-mđể liên kết các gói, lớp và mô-đun với Media3. Khi bạn chạy tập lệnh bằng tuỳ chọn-m, các thay đổi sẽ được áp dụng cho những tệp đã chọn.- Dừng khi có lỗi xác thực mà không thực hiện thay đổi
./media3-migration.sh -m /path/to/gradle/project/root- Buộc thực thi
Nếu tập lệnh phát hiện thấy lỗi vi phạm các điều kiện tiên quyết, bạn có thể buộc 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
Hoàn tất các bước thủ công sau đây sau khi chạy tập lệnh bằng tuỳ chọn -m:
- Kiểm tra cách tập lệnh thay đổi mã của bạn: Sử dụng công cụ diff và khắc phục các vấn đề tiềm ẩn (cân nhắc việc báo cáo lỗi nếu bạn cho rằng tập lệnh có vấn đề chung được đưa vào mà không truyền tuỳ chọn
-f). - Tạo dự án: Sử dụng
./gradlew clean buildhoặc trong Android Studio, chọn File > Sync Project with Gradle Files (Tệp > Đồng bộ hoá dự án với tệp Gradle), sau đó chọn Build > Clean project (Tạo > Dọn dẹp dự án), rồi chọn Build > Rebuild project (Tạo > Tạo lại dự án) (theo dõi quá trình tạo trong thẻ "Build – Build Output" (Tạo – Kết quả tạo) của Android Studio).
Các bước tiếp theo nên thực hiện:
- Giải quyết lựa chọn sử dụng đối với các 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 và tham khảo JavaDoc của biểu tượng không dùng nữa để tìm hiểu xem nên sử dụng biểu tượng nào thay vì lệnh gọi đã cho.
- Sắp xếp các 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 rồi chọn Optimize imports (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 trình phát với trạng thái của phiên và nhận lệnh từ các bộ điều khiển cần uỷ quyền cho các phương thức trình phát 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ả tệp đối chiếu và cách sử dụng MediaSessionConnector: 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ì có thể tập lệnh đó đã khiến mã của bạn không thể biên dịch được liên quan đến
MediaSessionConnectorkhông thể giải quyết. Android Studio sẽ cho bạn thấy mã bị hỏng khi bạn cố gắng tạo hoặc khởi động ứng dụng.Trong tệp
build.gradlenơi bạn duy trì các phần phụ thuộc, hãy thêm một 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.11.1"Thay thế
MediaSessionCompatbằngandroidx.media3.session.MediaSession.Tại trang web mã nơi bạn đã tạo
MediaSessionCompatcũ, 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.Kotlin
val player = ExoPlayer.Builder(context).build() mediaSession = MediaSession.Builder(context, player).setCallback(MySessionCallback()).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); mediaSession = new MediaSession.Builder(context, player).setCallback(new MySessionCallback()).build();
Triển khai
MySessionCallbacktheo yêu cầu của ứng dụng. Đây là bước không bắt buộc. Nếu bạn muốn cho phép bộ đ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(). Lớp này cung cấp nhiều phương thức API hiện tại và cũ để thêm các mục nội dung nghe nhìn vào trình phát để phát theo cách tương thích ngược. Trong đó bao gồm cả các phương thứcMediaController.set/addMediaItems()của trình đ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 cách triển khai mẫu củaonAddMediaItemstrongPlaybackServicecủa ứng dụng minh hoạ phiên.Giải phóng phiên phát nội dung nghe nhìn tại trang web mã nơi bạn đã huỷ phiên trước khi di chuyển:
Kotlin
mediaSession?.run { player.release() release() mediaSession = null }
Java
if (mediaSession != null) { mediaSession.getPlayer().release(); mediaSession.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.
| MediaSessionConnector | AndroidX Media3 |
|---|---|
CustomActionProvider |
MediaSession.Callback.onCustomCommand()/
MediaSession.setMediaButtonPreferences() |
PlaybackPreparer |
MediaSession.Callback.onAddMediaItems()
(prepare() được gọi nội bộ)
|
QueueNavigator |
ForwardingSimpleBasePlayer |
QueueEditor |
MediaSession.Callback.onAddMediaItems() |
RatingCallback |
MediaSession.Callback.onSetRating() |
PlayerNotificationManager |
DefaultMediaNotificationProvider/
MediaNotification.Provider |
Di chuyển MediaBrowserService sang MediaLibraryService
AndroidX Media3 giới thiệu 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 có khả năng tương thích ngược với
MediaBrowserService. Ứ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 MediaLibraryService. Đối với ứng dụng khách, việc ứng dụng của bạn đang sử dụng MediaLibraryService hay MediaBrowserServiceCompat cũ là điều rõ ràng.
Để 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, ứng dụng khách sẽ tìm thấy dịch vụ của bạn theo 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.gradlenơi bạn duy trì các phần phụ thuộc, hãy thêm một 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.11.1"Thay đổi dịch vụ của bạn để kế thừa từ
MediaLibraryServicethay vìMediaBrowserServiceNhư đã nói ở trên,MediaLibraryServicetương thích vớiMediaBrowserServicecũ. Theo đó, API rộng hơn mà dịch vụ đang cung cấp cho ứng dụng khách vẫn giữ nguyên. Vì vậy, có khả năng là một ứng dụng có thể giữ lại hầu hết logic cần thiết để triển khaiMediaBrowserServicevà điều chỉnh logic đó choMediaLibraryServicemới.Sau đây là những điểm khác biệt chính so với
MediaBrowserServiceCompatcũ:Triển khai các phương thức 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ổ/phát hành 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 vòng đời dịch vụ chuẩn, ứng dụng cần ghi đèonGetSession(MediaSession.ControllerInfo)để trả vềMediaLibrarySessionđược tích hợp trongonCreate.Triển khai MediaLibraryService.MediaLibrarySessionCallback: Để tạo một phiên, bạn cần có một
MediaLibraryService.MediaLibrarySessionCallbacktriể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:Kotlin
mediaLibrarySession = MediaLibrarySession.Builder(context, player, MySessionCallback()).build()
Java
mediaLibrarySession = new MediaLibrarySession.Builder(context, player, new 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ũ để thêm các mục nội dung nghe nhìn vào trình phát nhằm phát lại theo cách tương thích ngược. Điều này bao gồm các phương thứcMediaController.set/addMediaItems()của trình đ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 cách triển khai mẫu của lệnh gọi lại trongPlaybackServicecủa ứng dụng minh hoạ phiên.AndroidX Media3 đang sử dụng
androidx.media3.common.MediaItemthay 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 liên kết vớiMediaItemcủa 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ápResultcó thể tách rời củaMediaBrowserServiceCompat. Quá trình triển khai dịch vụ của bạn có thể trả về mộtListenableFuturekhô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 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 MediaNotification.Provider tuỳ chỉnh trong onCreate() để thay thế DefaultMediaNotificationProvider. Sau đó, MediaLibraryService sẽ đảm nhận việc bắt đầu dịch vụ trên 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 việc đăng thông báo và bắt đầu/dừng dịch vụ trên 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 xem 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 một MediaBrowser và chờ kết nối với dịch vụ được thiết lập:
Kotlin
scope.launch { val sessionToken = SessionToken(context, ComponentName(context, "MusicService")) browser = MediaBrowser.Builder(context, sessionToken) .setListener(BrowserListener()) .buildAsync() .await() }
Java
SessionToken sessionToken = new SessionToken(context, new ComponentName(context, "MusicService")); ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken) .setListener(new BrowserListener()) .buildAsync();
Hãy xem phần Điều khiển chế độ phát trong phiên phát nội dung nghe nhìn để tìm hiểu cách tạo MediaController nhằm đ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 di chuyển sang Media3, bạn có thể thấy lỗi tìm lỗi mã nguồn về việc sử dụng API không ổn định.
Bạn có thể sử dụng các API này một cách an toàn và lỗi tìm lỗi mã nguồn là một sản phẩm phụ của các đảm bảo về khả năng tương thích nhị phân mới của chúng tôi. Nếu bạn không yêu cầu khả năng tương thích nhị phân nghiêm ngặt, thì bạn có thể chặn các lỗi này một cách an toàn bằng chú thích @OptIn.
Nền
Cả ExoPlayer phiên bản 1 và phiên bản 2 đều không đả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 ký hiệu hoặc 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 trường hợp, những lỗi này được giảm thiểu bằng cách giới thiệu ký hiệu mới cùng với việc ngừng sử dụng ký hiệu cũ trong một vài phiên bản, để nhà phát triển có thời gian di chuyển các cách sử dụng, nhưng không phải lúc nào cũng có thể làm được điều này.
Những thay đổi có thể gây lỗi này dẫn đến hai vấn đề cho người dùng thư viện ExoPlayer phiên bản 1 và phiên bản 2:
- Việc nâng cấp lên 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 một thư viện trung gian phải đảm bảo rằng cả hai phần phụ thuộc đều có cùng phiên bản, nếu không, sự không tương thích nhị phân có thể dẫn đến sự cố trong thời gian chạy.
Những điểm 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ỏ của nền tảng API. Những phần không đảm bảo khả năng tương thích với tệp nhị phân được đánh dấu bằng @UnstableApi. Để làm rõ sự khác biệt này, việc sử dụng các ký hiệu API không ổn định sẽ tạo ra lỗi tìm mã nguồn trừ phi các ký hiệu đó được chú thích bằng @OptIn.
Sau khi di chuyển từ ExoPlayer phiên bản 2 sang Media3, bạn có thể thấy nhiều lỗi tìm 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 ExoPlayer phiên bản 2. Điều này không đúng. Các phần "không ổn định" của Media3 API có cùng mức độ ổn định với toàn bộ khu vực ExoPlayer v2 API và các đảm bảo về khu vực Media3 API ổn định hoàn toàn không có trong ExoPlayer v2. Điểm khác biệt duy nhất là giờ đây, lỗi tìm lỗi mã nguồn sẽ cảnh báo bạn về các mức độ ổn định khác nhau.
Xử lý lỗi tìm mã nguồn không ổn định của API
Hãy xem phần khắc phục sự cố về các lỗi tìm mã nguồn này để biết thông tin chi tiết về cách chú thích các cách sử dụng Java và Kotlin của API không ổn định bằng @OptIn.
API không dùng nữa
Bạn có thể nhận thấy các lệnh gọi đến API không dùng nữa bị gạch ngang trong Android Studio. Bạn nên thay thế các lệnh gọi đó bằng lệnh gọi thay thế thích hợp. Di chuột qua biểu tượng để xem JavaDoc cho biết API nào cần sử dụng.
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
- Bộ điều khiển chế độ phát bằng Trợ lý Google
- UAMP: Trình phát nội dung nghe nhìn Android (nhánh media3) (thiết bị di động, AutomotiveOS)
- Thông báo trên giao diện người dùng hệ thống, MediaButton/BT, Tiếp tục phát
- Bộ điều khiển chế độ phát bằng Trợ lý Google/WearOS
- AutomotiveOS: lệnh tuỳ chỉnh và đăng nhập