Jetpack Media3 xác định giao diện Player
nêu rõ chức năng cơ bản để phát các tệp video và âm thanh. ExoPlayer
là phương thức triển khai mặc định của giao diện này trong Media3. Bạn nên sử dụng ExoPlayer, vì nó cung cấp một bộ tính năng toàn diện bao gồm hầu hết các trường hợp sử dụng phát lại và có thể tuỳ chỉnh để xử lý bất kỳ trường hợp sử dụng nào khác của bạn. ExoPlayer cũng tóm tắt phân đoạn thiết bị và hệ điều hành để mã của bạn hoạt động nhất quán trên toàn bộ hệ sinh thái Android. ExoPlayer bao gồm:
- Hỗ trợ cho danh sách phát
- Hỗ trợ nhiều định dạng truyền trực tuyến tăng dần và thích ứng
- Hỗ trợ cho tính năng chèn quảng cáo phía máy khách và phía máy chủ
- Hỗ trợ phát lại được bảo vệ bằng DRM
Trang này sẽ hướng dẫn bạn một số bước quan trọng để xây dựng ứng dụng phát. Để biết thêm thông tin chi tiết, bạn có thể xem hướng dẫn đầy đủ của chúng tôi về Media3 ExoPlayer.
Bắt đầu
Để bắt đầu, hãy thêm phần phụ thuộc vào ExoPlayer, giao diện người dùng và các mô-đun Common của Jetpack Media3:
implementation "androidx.media3:media3-exoplayer:1.3.1" implementation "androidx.media3:media3-ui:1.3.1" implementation "androidx.media3:media3-common:1.3.1"
Tuỳ thuộc vào trường hợp sử dụng, bạn cũng có thể cần thêm các mô-đun từ Media3, chẳng hạn như exoplayer-dash
để phát các luồng phát ở định dạng DASH.
Hãy nhớ thay thế 1.3.1
bằng phiên bản thư viện bạn muốn. Bạn có thể tham khảo ghi chú phát hành để xem phiên bản mới nhất.
Tạo trình phát đa phương tiện
Với Media3, bạn có thể sử dụng phương thức triển khai đi kèm của giao diện Player
, ExoPlayer
hoặc bạn có thể tạo phương thức triển khai tuỳ chỉnh của riêng mình.
Tạo ExoPlayer
Cách đơn giản nhất để tạo một thực thể ExoPlayer
như sau:
Kotlin
val player = ExoPlayer.Builder(context).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build();
Bạn có thể tạo trình phát nội dung đa phương tiện trong phương thức vòng đời onCreate()
của Activity
, Fragment
hoặc Service
nơi trình phát nội dung đó.
Builder
bao gồm nhiều tuỳ chọn tuỳ chỉnh mà bạn có thể quan tâm, chẳng hạn như:
setAudioAttributes()
để định cấu hình xử lý quyền phát âm thanhsetHandleAudioBecomingNoisy()
để định cấu hình hành vi phát khi thiết bị đầu ra âm thanh bị ngắt kết nốisetTrackSelector()
để định cấu hình lựa chọn bản nhạc
Media3 cung cấp thành phần giao diện người dùng PlayerView
mà bạn có thể đưa vào tệp bố cục của ứng dụng. Thành phần này đóng gói một PlayerControlView
để điều khiển chế độ phát, SubtitleView
để hiển thị phụ đề và Surface
để kết xuất video.
Chuẩn bị trình phát
Thêm mục nội dung nghe nhìn vào danh sách phát để phát lại bằng các phương thức như setMediaItem()
và addMediaItem()
.
Sau đó, hãy gọi prepare()
để bắt đầu tải nội dung nghe nhìn và thu thập những tài nguyên cần thiết.
Bạn không nên thực hiện các bước này trước khi ứng dụng chạy trên nền trước. Nếu người chơi của bạn đang ở trong Activity
hoặc Fragment
, điều này có nghĩa là phải chuẩn bị người chơi trong phương thức vòng đời onStart()
ở API cấp 24 trở lên hoặc phương thức vòng đời onResume()
trên API cấp 23 trở xuống. Đối với người chơi nằm trong Service
, bạn có thể chuẩn bị trong onCreate()
.
Điều khiển trình phát
Sau khi trình phát đã được chuẩn bị, bạn có thể điều khiển chế độ phát bằng cách gọi các phương thức trên trình phát, chẳng hạn như:
play()
vàpause()
để bắt đầu và tạm dừng phátseekTo()
để tìm một vị trí trong mục nội dung đa phương tiện hiện tạiseekToNextMediaItem()
vàseekToPreviousMediaItem()
để di chuyển trong danh sách phát
Các thành phần giao diện người dùng như PlayerView
hoặc PlayerControlView
sẽ cập nhật
tương ứng khi được liên kết với trình phát.
Thả trình phát
Việc phát có thể đòi hỏi những tài nguyên bị hạn chế, chẳng hạn như bộ giải mã video. Vì vậy, bạn cần gọi release()
trên trình phát để giải phóng tài nguyên khi không cần trình phát nữa.
Nếu trình phát của bạn đang ở Activity
hoặc Fragment
, hãy giải phóng trình phát bằng phương thức vòng đời onStop()
ở API cấp 24 trở lên hoặc phương thức onPause()
ở API cấp 23 trở xuống. Đối với trình phát nằm trong Service
, bạn có thể phát hành trình phát đó trong onDestroy()
.
Quản lý tính năng phát bằng một phiên nội dung nghe nhìn
Trên Android, các phiên phát nội dung đa phương tiện cung cấp một cách thức chuẩn hoá để tương tác với trình phát nội dung đa phương tiện qua các ranh giới của quy trình. Khi kết nối một phiên phát nội dung nghe nhìn với trình phát, bạn có thể quảng cáo nội dung nghe nhìn phát ở bên ngoài và nhận lệnh phát từ các nguồn bên ngoài, chẳng hạn như tích hợp với các chế độ điều khiển nội dung nghe nhìn của hệ thống trên thiết bị di động và thiết bị có màn hình lớn.
Để sử dụng các phiên phát nội dung đa phương tiện, hãy thêm phần phụ thuộc vào mô-đun Phiên Media3:
implementation "androidx.media3:media3-session:1.3.1"
Tạo một phiên phát nội dung nghe nhìn
Bạn có thể tạo MediaSession
sau khi khởi chạy trình phát như sau:
Kotlin
val player = ExoPlayer.Builder(context).build() val mediaSession = MediaSession.Builder(context, player).build()
Java
ExoPlayer player = new ExoPlayer.Builder(context).build(); MediaSession mediaSession = new MediaSession.Builder(context, player).build();
Media3 tự động đồng bộ hoá trạng thái của Player
với trạng thái của MediaSession
. Cách này phù hợp với mọi cách triển khai Player
, bao gồm cả ExoPlayer
, CastPlayer
hoặc một cách triển khai tuỳ chỉnh.
Cấp quyền kiểm soát cho các ứng dụng khác
Các ứng dụng khách có thể triển khai trình điều khiển nội dung nghe nhìn để điều khiển chế độ phát phiên nội dung nghe nhìn của bạn. Để nhận những yêu cầu này, hãy đặt một đối tượng callback (lệnh gọi lại) khi tạo MediaSession
.
Khi tay điều khiển sắp kết nối với phiên phát nội dung đa phương tiện của bạn, phương thức onConnect()
sẽ được gọi. Bạn có thể sử dụng ControllerInfo
được cung cấp để quyết định xem nên chấp nhận hay từ chối yêu cầu. Hãy xem ví dụ về nội dung này trong ứng dụng minh hoạ Phiên Media3.
Sau khi kết nối, tay điều khiển có thể gửi lệnh phát đến phiên đó. Sau đó, phiên sẽ uỷ quyền các lệnh đó cho trình phát. Các lệnh phát và danh sách phát được xác định trong giao diện Player
sẽ do phiên xử lý tự động.
Các phương thức gọi lại khác cho phép bạn xử lý các yêu cầu lệnh phát tuỳ chỉnh và sửa đổi danh sách phát chẳng hạn. Tương tự, các lệnh gọi lại này bao gồm đối tượng ControllerInfo
để bạn có thể xác định quyền kiểm soát quyền truy cập trên cơ sở từng yêu cầu.
Phát nội dung nghe nhìn trong nền
Để tiếp tục phát nội dung nghe nhìn khi ứng dụng của bạn không chạy ở nền trước, chẳng hạn như để phát nhạc, sách nói hoặc podcast ngay cả khi người dùng chưa mở ứng dụng, Player
và MediaSession
của bạn phải được đóng gói trong một dịch vụ trên nền trước. Media3 cung cấp giao diện MediaSessionService
cho mục đích này.
Triển khai một MediaSessionService
Tạo một lớp mở rộng MediaSessionService
và tạo thực thể cho MediaSession
của bạn trong phương thức vòng đời onCreate()
.
Kotlin
class PlaybackService : MediaSessionService() { private var mediaSession: MediaSession? = null // Create your Player and MediaSession in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaSession = MediaSession.Builder(this, player).build() } // Remember to release the player and media session in onDestroy override fun onDestroy() { mediaSession?.run { player.release() release() mediaSession = null } super.onDestroy() } }
Java
public class PlaybackService extends MediaSessionService { private MediaSession mediaSession = null; @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaSession = new MediaSession.Builder(this, player).build(); } @Override public void onDestroy() { mediaSession.getPlayer().release(); mediaSession.release(); mediaSession = null; super.onDestroy(); } }
Trong tệp kê khai, lớp Service
có bộ lọc ý định MediaSessionService
và yêu cầu quyền FOREGROUND_SERVICE
để chạy dịch vụ trên nền trước:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Cuối cùng, trong lớp mà bạn đã tạo, hãy ghi đè phương thức onGetSession()
để kiểm soát quyền truy cập của ứng dụng khách vào phiên phát nội dung đa phương tiện của bạn. Hãy trả về một MediaSession
để chấp nhận yêu cầu kết nối hoặc trả về null
để từ chối yêu cầu.
Kotlin
// This example always accepts the connection request override fun onGetSession( controllerInfo: MediaSession.ControllerInfo ): MediaSession? = mediaSession
Java
@Override public MediaSession onGetSession(MediaSession.ControllerInfo controllerInfo) { // This example always accepts the connection request return mediaSession; }
Kết nối với giao diện người dùng
Giờ đây, phiên phát nội dung đa phương tiện của bạn nằm trong Service
, tách biệt với Activity
hoặc Fragment
, nơi giao diện người dùng của trình phát hoạt động, bạn có thể sử dụng MediaController
để liên kết chúng với nhau. Trong phương thức onStart()
của Activity
hoặc Fragment
với giao diện người dùng, hãy tạo SessionToken
cho MediaSession
, sau đó sử dụng SessionToken
để tạo MediaController
. Quá trình tạo MediaController
diễn ra không đồng bộ.
Kotlin
override fun onStart() { val sessionToken = SessionToken(this, ComponentName(this, PlaybackService::class.java)) val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync() controllerFuture.addListener( { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()) }, MoreExecutors.directExecutor() ) }
Java
@Override public void onStart() { SessionToken sessionToken = new SessionToken(this, new ComponentName(this, PlaybackService.class)); ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(this, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // Call controllerFuture.get() to retrieve the MediaController. // MediaController implements the Player interface, so it can be // attached to the PlayerView UI component. playerView.setPlayer(controllerFuture.get()); }, MoreExecutors.directExecutor()) }
MediaController
triển khai giao diện Player
, vì vậy, bạn có thể sử dụng cùng các phương thức như play()
và pause()
để điều khiển chế độ phát. Tương tự như các thành phần khác, hãy nhớ giải phóng MediaController
khi không còn cần thiết nữa, chẳng hạn như phương thức vòng đời onStop()
của Activity
, bằng cách gọi MediaController.releaseFuture()
.
Xuất bản thông báo
Bạn phải có dịch vụ trên nền trước để đăng thông báo khi đang hoạt động. MediaSessionService
sẽ tự động tạo thông báo MediaStyle
cho bạn dưới dạng MediaNotification
.
Để cung cấp thông báo tuỳ chỉnh, hãy tạo MediaNotification.Provider
bằng DefaultMediaNotificationProvider.Builder
hoặc bằng cách triển khai giao diện nhà cung cấp theo cách tuỳ chỉnh. Thêm nhà cung cấp vào MediaSession
của bạn bằng setMediaNotificationProvider
.
Quảng cáo thư viện nội dung
MediaLibraryService
được xây dựng dựa trên MediaSessionService
bằng cách cho phép ứng dụng khách duyệt qua nội dung nghe nhìn do ứng dụng của bạn cung cấp. Ứng dụng khách sẽ triển khai MediaBrowser
để tương tác với MediaLibraryService
của bạn.
Việc triển khai MediaLibraryService
cũng tương tự như cách triển khai MediaSessionService
, ngoại trừ việc trong onGetSession()
, bạn nên trả về MediaLibrarySession
thay vì MediaSession
. So với MediaSession.Callback
, MediaLibrarySession.Callback
bao gồm các phương thức bổ sung cho phép ứng dụng trình duyệt điều hướng nội dung do dịch vụ thư viện của bạn cung cấp.
Tương tự như MediaSessionService
, hãy khai báo MediaLibraryService
trong tệp kê khai và yêu cầu quyền FOREGROUND_SERVICE
để chạy một dịch vụ trên nền trước:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaLibraryService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Ví dụ trên bao gồm một bộ lọc ý định cho cả MediaLibraryService
và MediaBrowserService
cũ để tương thích ngược. Bộ lọc ý định bổ sung cho phép các ứng dụng khách dùng API MediaBrowserCompat
để nhận dạng Service
của bạn.
MediaLibrarySession
cho phép bạn phân phát thư viện nội dung của mình theo cấu trúc dạng cây, với một MediaItem
gốc duy nhất. Mỗi MediaItem
trong cây có thể có số lượng nút MediaItem
con bất kỳ. Bạn có thể phân phát một gốc khác hoặc một cây khác dựa trên yêu cầu của ứng dụng khách. Ví dụ: cây bạn quay lại ứng dụng đang tìm kiếm danh sách các mục nội dung đa phương tiện đề xuất có thể chỉ chứa MediaItem
gốc và một cấp độ nút con MediaItem
, trong khi cây bạn trả về một ứng dụng khách khác có thể đại diện cho một thư viện nội dung hoàn chỉnh hơn.
Tạo một MediaLibrarySession
MediaLibrarySession
mở rộng API MediaSession
để thêm các API duyệt nội dung. So với lệnh gọi lại MediaSession
, lệnh gọi lại MediaLibrarySession
bổ sung các phương thức như:
onGetLibraryRoot()
trong trường hợp ứng dụng yêu cầuMediaItem
gốc của cây nội dungonGetChildren()
trong trường hợp ứng dụng yêu cầu phần tử con củaMediaItem
trong cây nội dungonGetSearchResult()
khi ứng dụng yêu cầu kết quả tìm kiếm từ cây nội dung cho một truy vấn nhất định
Các phương thức gọi lại có liên quan sẽ bao gồm đối tượng LibraryParams
với các tín hiệu bổ sung về loại cây nội dung mà ứng dụng khách quan tâm.