Phiên phát nội dung nghe nhìn là cách thức tương tác phổ biến với trình phát âm thanh hoặc trình phát video. Trong Media3, trình phát mặc định là lớp ExoPlayer
, triển khai giao diện Player
. Việc kết nối phiên phát nội dung đa phương tiện với trình phát cho phép ứng dụng quảng cáo việc phát nội dung đa phương tiện từ bên ngoài và nhận các lệnh phát từ các nguồn bên ngoài.
Các lệnh có thể bắt nguồn từ các nút vật lý, chẳng hạn như nút phát trên tai nghe hoặc điều khiển từ xa của TV. Các lệnh này cũng có thể đến từ những ứng dụng khách có bộ điều khiển nội dung nghe nhìn, chẳng hạn như lệnh "tạm dừng" gửi đến Trợ lý Google. Phiên phát nội dung nghe nhìn sẽ uỷ quyền các lệnh này cho trình phát của ứng dụng nghe nhìn.
Khi nào nên chọn phiên đa phương tiện
Khi triển khai MediaSession
, bạn cho phép người dùng kiểm soát chế độ phát:
- Qua tai nghe. Thường thì người dùng có thể thực hiện các thao tác chạm hoặc nhấn nút trên tai nghe để phát hoặc tạm dừng nội dung nghe nhìn, hoặc chuyển đến bản nhạc tiếp theo hoặc trước đó.
- Bằng cách trò chuyện với Trợ lý Google. Một mẫu phổ biến là nói "Ok Google, tạm dừng" để tạm dừng mọi nội dung nghe nhìn đang phát trên thiết bị.
- Thông qua đồng hồ Wear OS. Nhờ đó, người dùng có thể dễ dàng truy cập vào các chế độ phát phổ biến nhất khi phát trên điện thoại.
- Thông qua Các nút điều khiển nội dung nghe nhìn. Băng chuyền này hiển thị các nút điều khiển cho từng phiên nội dung nghe nhìn đang chạy.
- Trên TV. Cho phép thực hiện các thao tác bằng nút phát thực, chế độ điều khiển phát trên nền tảng và quản lý nguồn (ví dụ: nếu TV, loa thanh hoặc bộ thu A/V tắt hoặc nguồn đầu vào chuyển đổi, thì quá trình phát sẽ dừng trong ứng dụng).
- Thông qua các nút điều khiển nội dung nghe nhìn của Android Auto. Điều này giúp bạn có thể kiểm soát chế độ phát một cách an toàn khi lái xe.
- Và mọi quy trình bên ngoài khác cần ảnh hưởng đến quá trình phát.
Điều này rất hữu ích trong nhiều trường hợp sử dụng. Cụ thể, bạn nên cân nhắc sử dụng MediaSession
khi:
- Bạn đang phát trực tiếp nội dung video dài, chẳng hạn như phim hoặc truyền hình trực tiếp.
- Bạn đang phát trực tuyến nội dung âm thanh dài, chẳng hạn như podcast hoặc danh sách phát nhạc.
- Bạn đang tạo một ứng dụng truyền hình.
Tuy nhiên, không phải trường hợp sử dụng nào cũng phù hợp với MediaSession
. Bạn có thể chỉ muốn sử dụng Player
trong những trường hợp sau:
- Bạn đang chiếu nội dung dạng ngắn, không cần chế độ điều khiển bên ngoài hoặc chế độ phát trong nền.
- Không có một video đang hoạt động duy nhất, chẳng hạn như người dùng đang cuộn qua một danh sách và nhiều video được hiển thị trên màn hình cùng một lúc.
- Bạn đang phát một video giới thiệu hoặc giải thích một lần mà bạn muốn người dùng chủ động xem mà không cần các chế độ điều khiển phát bên ngoài.
- Nội dung của bạn là nội dung nhạy cảm về quyền riêng tư và bạn không muốn các quy trình bên ngoài truy cập vào siêu dữ liệu của nội dung nghe nhìn (ví dụ: chế độ ẩn danh trong trình duyệt).
Nếu trường hợp sử dụng của bạn không phù hợp với bất kỳ trường hợp nào nêu trên, hãy cân nhắc xem bạn có muốn ứng dụng tiếp tục phát khi người dùng không tương tác tích cực với nội dung hay không. Nếu câu trả lời là có, thì có lẽ bạn nên chọn MediaSession
. Nếu câu trả lời là không, thì có lẽ bạn nên sử dụng Player
.
Tạo một phiên phát nội dung nghe nhìn
Một phiên nội dung nghe nhìn tồn tại cùng với trình phát mà phiên đó quản lý. Bạn có thể tạo một phiên phát nội dung nghe nhìn bằng đối tượng Context
và Player
. Bạn nên tạo và khởi chạy một phiên nội dung nghe nhìn khi cần, chẳng hạn như phương thức vòng đời onStart()
hoặc onResume()
của Activity
hoặc Fragment
, hoặc phương thức onCreate()
của Service
sở hữu phiên nội dung nghe nhìn và trình phát được liên kết.
Để tạo một phiên phát nội dung nghe nhìn, hãy khởi động một Player
và cung cấp phiên đó cho MediaSession.Builder
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();
Tự động xử lý trạng thái
Thư viện Media3 tự động cập nhật phiên phát nội dung đa phương tiện bằng trạng thái của trình phát. Do đó, bạn không cần xử lý việc liên kết từ trình phát đến phiên theo cách thủ công.
Điều này khác với phiên nội dung nghe nhìn của nền tảng, nơi bạn cần tạo và duy trì một PlaybackState
độc lập với chính trình phát, chẳng hạn như để cho biết mọi lỗi.
Mã phiên duy nhất
Theo mặc định, MediaSession.Builder
sẽ tạo một phiên có chuỗi trống làm mã phiên. Điều này là đủ nếu một ứng dụng chỉ định tạo một phiên bản phiên duy nhất, đây là trường hợp phổ biến nhất.
Nếu muốn quản lý nhiều phiên bản phiên cùng một lúc, ứng dụng phải đảm bảo rằng mã nhận dạng phiên của mỗi phiên là duy nhất. Bạn có thể đặt mã phiên khi tạo phiên bằng MediaSession.Builder.setId(String id)
.
Nếu bạn thấy IllegalStateException
làm ứng dụng của bạn gặp sự cố với thông báo lỗi IllegalStateException: Session ID must be unique. ID=
, thì có thể là một phiên đã được tạo ngoài dự kiến trước khi một phiên bản được tạo trước đó có cùng mã nhận dạng được phát hành. Để tránh rò rỉ phiên do lỗi lập trình, những trường hợp như vậy sẽ được phát hiện và thông báo bằng cách gửi một ngoại lệ.
Cấp quyền điều khiển cho các ứng dụng khác
Phiên nội dung nghe nhìn là chìa khoá để kiểm soát hoạt động phát. Điều này cho phép bạn định tuyến các lệnh từ các nguồn bên ngoài đến trình phát thực hiện việc phát nội dung nghe nhìn. Các nguồn này có thể là nút vật lý (chẳng hạn như nút phát trên tai nghe hoặc điều khiển từ xa của TV) hoặc lệnh gián tiếp (chẳng hạn như hướng dẫn "tạm dừng" cho Trợ lý Google). Tương tự, bạn có thể muốn cấp quyền truy cập cho hệ thống Android để hỗ trợ thông báo và các chế độ kiểm soát trên màn hình khoá, hoặc cho đồng hồ Wear OS để bạn có thể kiểm soát chế độ phát từ mặt đồng hồ. Các ứng dụng bên ngoài có thể dùng một trình điều khiển nội dung nghe nhìn để gửi lệnh phát đến ứng dụng đa phương tiện của bạn. Các lệnh này sẽ được phiên phát nội dung nghe nhìn của bạn nhận, sau đó phiên này sẽ uỷ quyền các lệnh cho trình phát nội dung nghe nhìn.

Khi một bộ điều khiển sắp kết nối với phiên nội dung nghe nhì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 có chấp nhận hay từ chối yêu cầu này hay không. Hãy xem ví dụ về cách chấp nhận yêu cầu kết nối trong phần Khai báo các lệnh tuỳ chỉnh.
Sau khi kết nối, bộ điều khiển có thể gửi lệnh phát đến phiên. Sau đó, phiên này 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ẽ được phiên tự động xử lý.
Các phương thức gọi lại khác cho phép bạn xử lý, chẳng hạn như các yêu cầu về lệnh tuỳ chỉnh và sửa đổi danh sách phát. Tương tự, các lệnh gọi lại này cũng bao gồm một đối tượng ControllerInfo
để bạn có thể sửa đổi cách phản hồi từng yêu cầu theo từng bộ điều khiển.
Sửa đổi danh sách phát
Một phiên nội dung nghe nhìn có thể trực tiếp sửa đổi danh sách phát của trình phát, như được giải thích trong hướng dẫn về danh sách phát của ExoPlayer.
Người điều khiển cũng có thể sửa đổi danh sách phát nếu có biểu tượng COMMAND_SET_MEDIA_ITEM
hoặc COMMAND_CHANGE_MEDIA_ITEMS
cho người điều khiển.
Khi thêm các mục mới vào danh sách phát, trình phát thường yêu cầu các phiên bản MediaItem
có URI được xác định để có thể phát các mục đó. Theo mặc định, các mục mới được thêm sẽ tự động chuyển tiếp đến các phương thức của trình phát như player.addMediaItem
nếu có URI được xác định.
Nếu muốn tuỳ chỉnh các thực thể MediaItem
được thêm vào trình phát, bạn có thể ghi đè onAddMediaItems()
.
Bạn cần thực hiện bước này khi muốn hỗ trợ những bộ điều khiển yêu cầu nội dung nghe nhìn mà không có URI được xác định. Thay vào đó, MediaItem
thường có một hoặc nhiều trường sau đây được đặt để mô tả nội dung nghe nhìn được yêu cầu:
MediaItem.id
: Giá trị nhận dạng chung xác định nội dung nghe nhìn.MediaItem.RequestMetadata.mediaUri
: Một URI yêu cầu có thể sử dụng một giản đồ tuỳ chỉnh và không nhất thiết phải phát trực tiếp được bởi trình phát.MediaItem.RequestMetadata.searchQuery
: Cụm từ tìm kiếm bằng văn bản, ví dụ: từ Trợ lý Google.MediaItem.MediaMetadata
: Siêu dữ liệu có cấu trúc như "tiêu đề" hoặc "nghệ sĩ".
Để có thêm các lựa chọn tuỳ chỉnh cho danh sách phát hoàn toàn mới, bạn cũng có thể ghi đè onSetMediaItems()
. Lựa chọn này cho phép bạn xác định mục bắt đầu và vị trí trong danh sách phát. Ví dụ: bạn có thể mở rộng một mục được yêu cầu thành toàn bộ danh sách phát và hướng dẫn trình phát bắt đầu tại chỉ mục của mục được yêu cầu ban đầu. Bạn có thể tìm thấy ví dụ về cách triển khai onSetMediaItems()
bằng tính năng này trong ứng dụng minh hoạ phiên.
Quản lý lựa chọn ưu tiên về nút nội dung nghe nhìn
Mọi bộ điều khiển (ví dụ: Giao diện người dùng hệ thống, Android Auto hoặc Wear OS) đều có thể tự quyết định nút nào sẽ hiện cho người dùng. Để cho biết những chế độ điều khiển phát nào bạn muốn cung cấp cho người dùng, bạn có thể chỉ định lựa chọn ưu tiên về nút đa phương tiện trên MediaSession
. Các lựa chọn ưu tiên này bao gồm một danh sách có thứ tự gồm các thực thể CommandButton
, mỗi thực thể xác định một lựa chọn ưu tiên cho một nút trong giao diện người dùng.
Xác định nút lệnh
Các thực thể CommandButton
được dùng để xác định các lựa chọn ưu tiên về nút đa phương tiện. Mỗi nút xác định 3 khía cạnh của phần tử giao diện người dùng mong muốn:
- Biểu tượng, xác định giao diện trực quan. Bạn phải đặt biểu tượng thành một trong các hằng số được xác định trước khi tạo
CommandButton.Builder
. Xin lưu ý rằng đây không phải là Bitmap hoặc tài nguyên hình ảnh thực tế. Hằng số chung giúp các bộ điều khiển chọn một tài nguyên phù hợp để có giao diện nhất quán trong giao diện người dùng của riêng chúng. Nếu không có hằng số biểu tượng nào được xác định trước phù hợp với trường hợp sử dụng của bạn, thì bạn có thể sử dụngsetCustomIconResId
. - Lệnh, xác định hành động được kích hoạt khi người dùng tương tác với nút. Bạn có thể sử dụng
setPlayerCommand
choPlayer.Command
hoặcsetSessionCommand
choSessionCommand
được xác định trước hoặc tuỳ chỉnh. - Slot, xác định vị trí đặt nút trong giao diện người dùng của bộ điều khiển. Đây là trường không bắt buộc và được đặt tự động dựa trên Biểu tượng và Lệnh. Ví dụ: bạn có thể chỉ định rằng một nút sẽ xuất hiện trong vùng điều hướng "tiến" của giao diện người dùng thay vì vùng "tràn" mặc định.
Kotlin
val button = CommandButton.Builder(CommandButton.ICON_SKIP_FORWARD_15) .setSessionCommand(SessionCommand(CUSTOM_ACTION_ID, Bundle.EMPTY)) .setSlots(CommandButton.SLOT_FORWARD) .build()
Java
CommandButton button = new CommandButton.Builder(CommandButton.ICON_SKIP_FORWARD_15) .setSessionCommand(new SessionCommand(CUSTOM_ACTION_ID, Bundle.EMPTY)) .setSlots(CommandButton.SLOT_FORWARD) .build();
Khi các lựa chọn ưu tiên về nút đa phương tiện được giải quyết, thuật toán sau đây sẽ được áp dụng:
- Đối với mỗi
CommandButton
trong lựa chọn ưu tiên về nút đa phương tiện, hãy đặt nút này vào vị trí được phép và có sẵn đầu tiên. - Nếu bất kỳ vị trí nào ở giữa, phía trước và phía sau không có nút, hãy thêm các nút mặc định cho vị trí này.
Bạn có thể dùng CommandButton.DisplayConstraints
để tạo bản xem trước về cách giải quyết các lựa chọn ưu tiên cho nút đa phương tiện, tuỳ thuộc vào các quy tắc ràng buộc hiển thị giao diện người dùng.
Đặt lựa chọn ưu tiên cho nút nội dung nghe nhìn
Cách dễ nhất để đặt lựa chọn ưu tiên cho nút đa phương tiện là xác định danh sách khi tạo MediaSession
. Ngoài ra, bạn có thể ghi đè MediaSession.Callback.onConnect
để tuỳ chỉnh các lựa chọn ưu tiên cho nút đa phương tiện đối với từng bộ điều khiển đã kết nối.
Kotlin
val mediaSession = MediaSession.Builder(context, player) .setMediaButtonPreferences(ImmutableList.of(likeButton, favoriteButton)) .build()
Java
MediaSession mediaSession = new MediaSession.Builder(context, player) .setMediaButtonPreferences(ImmutableList.of(likeButton, favoriteButton)) .build();
Cập nhật lựa chọn ưu tiên về nút nội dung nghe nhìn sau khi người dùng tương tác
Sau khi xử lý một lượt tương tác với trình phát, bạn có thể muốn cập nhật các nút xuất hiện trong giao diện người dùng của bộ điều khiển. Ví dụ điển hình là nút bật/tắt sẽ thay đổi biểu tượng và hành động sau khi kích hoạt hành động được liên kết với nút này. Để cập nhật lựa chọn ưu tiên về nút đa phương tiện, bạn có thể dùng MediaSession.setMediaButtonPreferences
để cập nhật lựa chọn ưu tiên cho tất cả bộ điều khiển hoặc một bộ điều khiển cụ thể:
Kotlin
// Handle "favoritesButton" action, replace by opposite button mediaSession.setMediaButtonPreferences( ImmutableList.of(likeButton, removeFromFavoritesButton))
Java
// Handle "favoritesButton" action, replace by opposite button mediaSession.setMediaButtonPreferences( ImmutableList.of(likeButton, removeFromFavoritesButton));
Thêm lệnh tuỳ chỉnh và tuỳ chỉnh hành vi mặc định
Bạn có thể mở rộng các lệnh của trình phát hiện có bằng các lệnh tuỳ chỉnh. Ngoài ra, bạn cũng có thể chặn các lệnh của trình phát và nút đa phương tiện đến để thay đổi hành vi mặc định.
Khai báo và xử lý các lệnh tuỳ chỉnh
Các ứng dụng đa phương tiện có thể xác định các lệnh tuỳ chỉnh mà chẳng hạn như có thể dùng trong lựa chọn ưu tiên về nút đa phương tiện. Ví dụ: bạn có thể muốn triển khai các nút cho phép người dùng lưu một mục nội dung nghe nhìn vào danh sách các mục yêu thích. MediaController
sẽ gửi các lệnh tuỳ chỉnh và MediaSession.Callback
sẽ nhận các lệnh đó.
Để xác định các lệnh tuỳ chỉnh, bạn cần ghi đè MediaSession.Callback.onConnect()
để đặt các lệnh tuỳ chỉnh có sẵn cho mỗi bộ điều khiển được kết nối.
Kotlin
private class CustomMediaSessionCallback: MediaSession.Callback { // Configure commands available to the controller in onConnect() override fun onConnect( session: MediaSession, controller: MediaSession.ControllerInfo ): MediaSession.ConnectionResult { val sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(SessionCommand(SAVE_TO_FAVORITES, Bundle.EMPTY)) .build() return AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build() } }
Java
class CustomMediaSessionCallback implements MediaSession.Callback { // Configure commands available to the controller in onConnect() @Override public ConnectionResult onConnect( MediaSession session, ControllerInfo controller) { SessionCommands sessionCommands = ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(new SessionCommand(SAVE_TO_FAVORITES, new Bundle())) .build(); return new AcceptedResultBuilder(session) .setAvailableSessionCommands(sessionCommands) .build(); } }
Để nhận các yêu cầu về lệnh tuỳ chỉnh từ MediaController
, hãy ghi đè phương thức onCustomCommand()
trong Callback
.
Kotlin
private class CustomMediaSessionCallback: MediaSession.Callback { ... override fun onCustomCommand( session: MediaSession, controller: MediaSession.ControllerInfo, customCommand: SessionCommand, args: Bundle ): ListenableFuture<SessionResult> { if (customCommand.customAction == SAVE_TO_FAVORITES) { // Do custom logic here saveToFavorites(session.player.currentMediaItem) return Futures.immediateFuture( SessionResult(SessionResult.RESULT_SUCCESS) ) } ... } }
Java
class CustomMediaSessionCallback implements MediaSession.Callback { ... @Override public ListenableFuture<SessionResult> onCustomCommand( MediaSession session, ControllerInfo controller, SessionCommand customCommand, Bundle args ) { if(customCommand.customAction.equals(SAVE_TO_FAVORITES)) { // Do custom logic here saveToFavorites(session.getPlayer().getCurrentMediaItem()); return Futures.immediateFuture( new SessionResult(SessionResult.RESULT_SUCCESS) ); } ... } }
Bạn có thể theo dõi bộ điều khiển nội dung nghe nhìn nào đang đưa ra yêu cầu bằng cách sử dụng thuộc tính packageName
của đối tượng MediaSession.ControllerInfo
được truyền vào các phương thức Callback
. Điều này cho phép bạn điều chỉnh hành vi của ứng dụng để phản hồi một lệnh nhất định nếu lệnh đó bắt nguồn từ hệ thống, ứng dụng của riêng bạn hoặc các ứng dụng khách khác.
Tuỳ chỉnh các lệnh mặc định của trình phát
Tất cả các lệnh mặc định và hoạt động xử lý trạng thái đều được uỷ quyền cho Player
trên MediaSession
. Để tuỳ chỉnh hành vi của một lệnh được xác định trong giao diện Player
, chẳng hạn như play()
hoặc seekToNext()
, hãy bao bọc Player
trong ForwardingSimpleBasePlayer
trước khi truyền lệnh đó đến MediaSession
:
Kotlin
val player = (logic to build a Player instance) val forwardingPlayer = object : ForwardingSimpleBasePlayer(player) { // Customizations } val mediaSession = MediaSession.Builder(context, forwardingPlayer).build()
Java
ExoPlayer player = (logic to build a Player instance) ForwardingSimpleBasePlayer forwardingPlayer = new ForwardingSimpleBasePlayer(player) { // Customizations }; MediaSession mediaSession = new MediaSession.Builder(context, forwardingPlayer).build();
Để biết thêm thông tin về ForwardingSimpleBasePlayer
, hãy xem hướng dẫn về ExoPlayer trong phần Tuỳ chỉnh.
Xác định bộ điều khiển yêu cầu của lệnh trình phát
Khi một lệnh gọi đến phương thức Player
được bắt nguồn từ MediaController
, bạn có thể xác định nguồn gốc bằng MediaSession.controllerForCurrentRequest
và nhận ControllerInfo
cho yêu cầu hiện tại:
Kotlin
class CallerAwarePlayer(player: Player) : ForwardingSimpleBasePlayer(player) { override fun handleSeek( mediaItemIndex: Int, positionMs: Long, seekCommand: Int, ): ListenableFuture<*> { Log.d( "caller", "seek operation from package ${session.controllerForCurrentRequest?.packageName}", ) return super.handleSeek(mediaItemIndex, positionMs, seekCommand) } }
Java
public class CallerAwarePlayer extends ForwardingSimpleBasePlayer { public CallerAwarePlayer(Player player) { super(player); } @Override protected ListenableFuture<?> handleSeek( int mediaItemIndex, long positionMs, int seekCommand) { Log.d( "caller", "seek operation from package: " + session.getControllerForCurrentRequest().getPackageName()); return super.handleSeek(mediaItemIndex, positionMs, seekCommand); } }
Tuỳ chỉnh cách xử lý nút đa phương tiện
Nút đa phương tiện là các nút phần cứng có trên thiết bị Android và các thiết bị ngoại vi khác, chẳng hạn như nút phát/tạm dừng trên tai nghe Bluetooth. Media3 xử lý các sự kiện nút đa phương tiện cho bạn khi các sự kiện này đến phiên và gọi phương thức Player
thích hợp trên trình phát của phiên.
Bạn nên xử lý tất cả các sự kiện nút đa phương tiện đến trong phương thức Player
tương ứng. Đối với các trường hợp sử dụng nâng cao hơn, bạn có thể chặn các sự kiện nút đa phương tiện trong MediaSession.Callback.onMediaButtonEvent(Intent)
.
Xử lý và báo cáo lỗi
Có hai loại lỗi mà một phiên phát ra và báo cáo cho bộ điều khiển. Lỗi nghiêm trọng báo cáo lỗi phát kỹ thuật của trình phát phiên, làm gián đoạn quá trình phát. Lỗi nghiêm trọng sẽ tự động được báo cáo cho bộ điều khiển khi xảy ra. Lỗi không nghiêm trọng là những lỗi không liên quan đến kỹ thuật hoặc chính sách, không làm gián đoạn quá trình phát và được ứng dụng gửi đến các bộ điều khiển theo cách thủ công.
Lỗi phát nghiêm trọng
Trình phát sẽ báo cáo lỗi phát nghiêm trọng cho phiên, sau đó báo cáo cho các bộ điều khiển để gọi thông qua Player.Listener.onPlayerError(PlaybackException)
và Player.Listener.onPlayerErrorChanged(@Nullable PlaybackException)
.
Trong trường hợp như vậy, trạng thái phát sẽ chuyển sang STATE_IDLE
và MediaController.getPlaybackError()
sẽ trả về PlaybackException
gây ra quá trình chuyển đổi. Bộ điều khiển có thể kiểm tra PlayerException.errorCode
để biết thông tin về lý do gây ra lỗi.
Để có khả năng tương tác, một lỗi nghiêm trọng sẽ được sao chép vào phiên nền tảng bằng cách chuyển trạng thái của phiên đó thành STATE_ERROR
và đặt mã lỗi cũng như thông báo theo PlaybackException
.
Tuỳ chỉnh lỗi nghiêm trọng
Để cung cấp thông tin có ý nghĩa và phù hợp với ngôn ngữ của người dùng, bạn có thể tuỳ chỉnh mã lỗi, thông báo lỗi và thông tin bổ sung về lỗi của một lỗi phát nghiêm trọng bằng cách sử dụng ForwardingPlayer
khi tạo phiên:
Kotlin
val forwardingPlayer = ErrorForwardingPlayer(player) val session = MediaSession.Builder(context, forwardingPlayer).build()
Java
Player forwardingPlayer = new ErrorForwardingPlayer(player); MediaSession session = new MediaSession.Builder(context, forwardingPlayer).build();
Trình phát chuyển tiếp có thể dùng ForwardingSimpleBasePlayer
để chặn lỗi và tuỳ chỉnh mã lỗi, thông báo hoặc các phần bổ sung. Tương tự, bạn cũng có thể tạo các lỗi mới không có trong trình phát ban đầu:
Kotlin
class ErrorForwardingPlayer (private val context: Context, player: Player) : ForwardingSimpleBasePlayer(player) { override fun getState(): State { var state = super.getState() if (state.playerError != null) { state = state.buildUpon() .setPlayerError(customizePlaybackException(state.playerError!!)) .build() } return state } fun customizePlaybackException(error: PlaybackException): PlaybackException { val buttonLabel: String val errorMessage: String when (error.errorCode) { PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW -> { buttonLabel = context.getString(R.string.err_button_label_restart_stream) errorMessage = context.getString(R.string.err_msg_behind_live_window) } else -> { buttonLabel = context.getString(R.string.err_button_label_ok) errorMessage = context.getString(R.string.err_message_default) } } val extras = Bundle() extras.putString("button_label", buttonLabel) return PlaybackException(errorMessage, error.cause, error.errorCode, extras) } }
Java
class ErrorForwardingPlayer extends ForwardingSimpleBasePlayer { private final Context context; public ErrorForwardingPlayer(Context context, Player player) { super(player); this.context = context; } @Override protected State getState() { State state = super.getState(); if (state.playerError != null) { state = state.buildUpon() .setPlayerError(customizePlaybackException(state.playerError)) .build(); } return state; } private PlaybackException customizePlaybackException(PlaybackException error) { String buttonLabel; String errorMessage; switch (error.errorCode) { case PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW: buttonLabel = context.getString(R.string.err_button_label_restart_stream); errorMessage = context.getString(R.string.err_msg_behind_live_window); break; default: buttonLabel = context.getString(R.string.err_button_label_ok); errorMessage = context.getString(R.string.err_message_default); break; } Bundle extras = new Bundle(); extras.putString("button_label", buttonLabel); return new PlaybackException(errorMessage, error.getCause(), error.errorCode, extras); } }
Lỗi không nghiêm trọng
Các lỗi không nghiêm trọng không bắt nguồn từ một ngoại lệ kỹ thuật có thể được ứng dụng gửi đến tất cả hoặc một bộ điều khiển cụ thể:
Kotlin
val sessionError = SessionError( SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED, context.getString(R.string.error_message_authentication_expired), ) // Option 1: Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError) // Option 2: Sending a nonfatal error to the media notification controller only // to set the error code and error message in the playback state of the platform // media session. mediaSession.mediaNotificationControllerInfo?.let { mediaSession.sendError(it, sessionError) }
Java
SessionError sessionError = new SessionError( SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED, context.getString(R.string.error_message_authentication_expired)); // Option 1: Sending a nonfatal error to all controllers. mediaSession.sendError(sessionError); // Option 2: Sending a nonfatal error to the media notification controller only // to set the error code and error message in the playback state of the platform // media session. ControllerInfo mediaNotificationControllerInfo = mediaSession.getMediaNotificationControllerInfo(); if (mediaNotificationControllerInfo != null) { mediaSession.sendError(mediaNotificationControllerInfo, sessionError); }
Khi một lỗi không nghiêm trọng được gửi đến bộ điều khiển thông báo về nội dung nghe nhìn, mã lỗi và thông báo lỗi sẽ được sao chép vào phiên đa phương tiện của nền tảng, trong khi PlaybackState.state
không thay đổi thành STATE_ERROR
.
Nhận lỗi không nghiêm trọng
MediaController
nhận được một lỗi không nghiêm trọng bằng cách triển khai MediaController.Listener.onError
:
Kotlin
val future = MediaController.Builder(context, sessionToken) .setListener(object : MediaController.Listener { override fun onError(controller: MediaController, sessionError: SessionError) { // Handle nonfatal error. } }) .buildAsync()
Java
MediaController.Builder future = new MediaController.Builder(context, sessionToken) .setListener( new MediaController.Listener() { @Override public void onError(MediaController controller, SessionError sessionError) { // Handle nonfatal error. } });