Nghe sự kiện phát
Các sự kiện, chẳng hạn như các thay đổi về trạng thái và lỗi phát, được báo cáo cho những người đã đăng ký
Player.Listener
thực thể. Để đăng ký một trình nghe nhận
sự kiện:
Kotlin
// Add a listener to receive events from the player. player.addListener(listener)
Java
// Add a listener to receive events from the player. player.addListener(listener);
Player.Listener
có các phương thức mặc định trống nên bạn chỉ cần triển khai
các phương pháp mà mình quan tâm. Vui lòng xem Javadoc để biết nội dung mô tả đầy đủ về
các phương thức và thời điểm chúng được gọi. Một số phương pháp quan trọng nhất là
được mô tả chi tiết hơn bên dưới.
Trình nghe có thể lựa chọn giữa việc triển khai các lệnh gọi lại sự kiện riêng lẻ hoặc một
lệnh gọi lại onEvents
chung được gọi sau khi một hoặc nhiều sự kiện xảy ra
khi kết hợp cùng nhau. Xem Individual callbacks vs onEvents
để biết nội dung giải thích về
cần được ưu tiên cho các trường hợp sử dụng khác nhau.
Các thay đổi về trạng thái phát
Có thể nhận được các thay đổi về trạng thái của người chơi bằng cách triển khai
onPlaybackStateChanged(@State int state)
trong một đăng ký
Player.Listener
Trình phát có thể ở một trong bốn trạng thái phát:
Player.STATE_IDLE
: Đây là trạng thái ban đầu khi người chơi đã dừng và khi phát không thành công. Người chơi sẽ chỉ có tài nguyên giới hạn ở trạng thái này.Player.STATE_BUFFERING
: Người chơi không thể chơi ngay trên vị trí hiện tại. Điều này chủ yếu xảy ra vì cần tải nhiều dữ liệu hơn.Player.STATE_READY
: Người chơi có thể chơi ngay từ trò chơi hiện tại vị trí.Player.STATE_ENDED
: Trình phát đã phát xong tất cả nội dung nghe nhìn.
Ngoài các trạng thái này, người chơi còn có một cờ playWhenReady
để cho biết
ý định chơi của người dùng. Bạn có thể nhận được các thay đổi về cờ này bằng cách triển khai
onPlayWhenReadyChanged(playWhenReady, @PlayWhenReadyChangeReason int reason)
.
Người chơi đang chơi (tức là vị trí của người chơi đang thăng cấp còn nội dung nghe nhìn đang chuyển động cho người dùng) khi đáp ứng cả ba điều kiện sau:
- Người chơi đang ở trạng thái
Player.STATE_READY
playWhenReady
làtrue
- Phát không bị chặn vì lý do mà
Player.getPlaybackSuppressionReason
Thay vì phải kiểm tra từng thuộc tính, Player.isPlaying
. Có thể nhận được các thay đổi đối với trạng thái này bằng cách triển khai
onIsPlayingChanged(boolean isPlaying)
:
Kotlin
player.addListener( object : Player.Listener { override fun onIsPlayingChanged(isPlaying: Boolean) { if (isPlaying) { // Active playback. } else { // Not playing because playback is paused, ended, suppressed, or the player // is buffering, stopped or failed. Check player.playWhenReady, // player.playbackState, player.playbackSuppressionReason and // player.playerError for details. } } } )
Java
player.addListener( new Player.Listener() { @Override public void onIsPlayingChanged(boolean isPlaying) { if (isPlaying) { // Active playback. } else { // Not playing because playback is paused, ended, suppressed, or the player // is buffering, stopped or failed. Check player.getPlayWhenReady, // player.getPlaybackState, player.getPlaybackSuppressionReason and // player.getPlaybackError for details. } } });
Lỗi phát lại
Có thể nhận được các lỗi khiến phát lại không thành công bằng cách triển khai
onPlayerError(PlaybackException error)
trong một đăng ký
Player.Listener
Khi xảy ra lỗi, phương thức này sẽ được gọi
ngay trước khi trạng thái phát chuyển sang Player.STATE_IDLE
.
Bạn có thể thử lại hoặc dừng phát bằng cách gọi ExoPlayer.prepare
.
Lưu ý rằng một số phương thức triển khai Player
truyền các thực thể của lớp con của
PlaybackException
để cung cấp thêm thông tin về lỗi. Cho
ví dụ: ExoPlayer
truyền ExoPlaybackException
, có type
,
rendererIndex
và các trường khác dành riêng cho ExoPlayer.
Ví dụ sau đây trình bày cách phát hiện khi một lượt phát không thành công do Vấn đề kết nối mạng HTTP:
Kotlin
player.addListener( object : Player.Listener { override fun onPlayerError(error: PlaybackException) { val cause = error.cause if (cause is HttpDataSourceException) { // An HTTP error occurred. val httpError = cause // It's possible to find out more about the error both by casting and by querying // the cause. if (httpError is InvalidResponseCodeException) { // Cast to InvalidResponseCodeException and retrieve the response code, message // and headers. } else { // Try calling httpError.getCause() to retrieve the underlying cause, although // note that it may be null. } } } } )
Java
player.addListener( new Player.Listener() { @Override public void onPlayerError(PlaybackException error) { @Nullable Throwable cause = error.getCause(); if (cause instanceof HttpDataSourceException) { // An HTTP error occurred. HttpDataSourceException httpError = (HttpDataSourceException) cause; // It's possible to find out more about the error both by casting and by querying // the cause. if (httpError instanceof HttpDataSource.InvalidResponseCodeException) { // Cast to InvalidResponseCodeException and retrieve the response code, message // and headers. } else { // Try calling httpError.getCause() to retrieve the underlying cause, although // note that it may be null. } } } });
Chuyển đổi danh sách phát
Bất cứ khi nào trình phát thay đổi sang một mục nội dung nghe nhìn mới trong danh sách phát
onMediaItemTransition(MediaItem mediaItem,
@MediaItemTransitionReason int reason)
được gọi trên các thiết bị đã đăng ký
Đối tượng Player.Listener
. Lý do cho biết liệu đây có phải là truy vấn tự động
chuyển đổi, tua (ví dụ: sau khi gọi player.next()
), lặp lại
cùng một mục hoặc do thay đổi về danh sách phát gây ra (ví dụ: nếu
mục đang phát bị xoá).
Metadata
Siêu dữ liệu được trả về từ player.getCurrentMediaMetadata()
có thể thay đổi do có nhiều
lý do: chuyển đổi danh sách phát, cập nhật siêu dữ liệu trong luồng hoặc cập nhật
video đang phát giữa video MediaItem
.
Nếu bạn quan tâm đến việc thay đổi siêu dữ liệu, chẳng hạn như để cập nhật giao diện người dùng cho thấy
tên hiện tại, bạn có thể nghe onMediaMetadataChanged
.
Đang tìm kiếm
Việc gọi phương thức Player.seekTo
sẽ dẫn đến một loạt lệnh gọi lại đến các phương thức đã đăng ký
Player.Listener
thực thể:
onPositionDiscontinuity
cho thành viênreason=DISCONTINUITY_REASON_SEEK
. Đây là kết quả trực tiếp của việc gọiPlayer.seekTo
. Lệnh gọi lại cóPositionInfo
các trường cho vị trí trước và sau khi tìm kiếm.onPlaybackStateChanged
với mọi thay đổi về trạng thái tức thì liên quan đến lượt tìm kiếm. Xin lưu ý rằng có thể sẽ không có thay đổi nào như vậy.
Các lệnh gọi lại riêng lẻ so với onEvents
Trình nghe có thể chọn giữa việc triển khai từng lệnh gọi lại riêng lẻ như
onIsPlayingChanged(boolean isPlaying)
và thuộc tính chung
Lệnh gọi lại onEvents(Player player, Events events)
. Lệnh gọi lại chung cung cấp
quyền truy cập vào đối tượng Player
và chỉ định tập hợp events
đã xảy ra
khi kết hợp cùng nhau. Lệnh gọi lại này luôn được gọi sau các lệnh gọi lại tương ứng với
từng sự kiện.
Kotlin
override fun onEvents(player: Player, events: Player.Events) { if ( events.contains(Player.EVENT_PLAYBACK_STATE_CHANGED) || events.contains(Player.EVENT_PLAY_WHEN_READY_CHANGED) ) { uiModule.updateUi(player) } }
Java
@Override public void onEvents(Player player, Events events) { if (events.contains(Player.EVENT_PLAYBACK_STATE_CHANGED) || events.contains(Player.EVENT_PLAY_WHEN_READY_CHANGED)) { uiModule.updateUi(player); } }
Bạn nên ưu tiên các sự kiện riêng lẻ trong các trường hợp sau:
- Người nghe quan tâm đến lý do thay đổi. Ví dụ:
lý do được đưa ra cho
onPlayWhenReadyChanged
hoặconMediaItemTransition
. - Trình nghe chỉ hành động trên các giá trị mới được cung cấp thông qua các tham số gọi lại hoặc kích hoạt một yếu tố khác không phụ thuộc vào các tham số của lệnh gọi lại.
- Quá trình triển khai trình nghe ưu tiên chỉ báo dễ đọc về những gì đã kích hoạt sự kiện trong tên phương thức.
- Trình nghe báo cáo cho hệ thống phân tích cần biết về tất cả các sự kiện riêng lẻ và thay đổi trạng thái.
Bạn nên ưu tiên onEvents(Player player, Events events)
chung trong
các trường hợp sau:
- Trình nghe muốn kích hoạt cùng một logic cho nhiều sự kiện. Cho
ví dụ: cập nhật giao diện người dùng cho cả
onPlaybackStateChanged
vàonPlayWhenReadyChanged
- Trình nghe cần truy cập vào đối tượng
Player
để kích hoạt thêm các sự kiện, ví dụ: tìm kiếm sau khi chuyển đổi một mục nội dung đa phương tiện. - Trình nghe dự định sử dụng nhiều giá trị trạng thái được báo cáo
thông qua các lệnh gọi lại riêng biệt hoặc kết hợp với phương thức getter
Player
. Ví dụ: sử dụngPlayer.getCurrentWindowIndex()
với thuộc tínhTimeline
được cung cấp trongonTimelineChanged
chỉ an toàn từ bên trong Gọi lạionEvents
. - Trình nghe muốn biết liệu các sự kiện có xảy ra cùng nhau theo logic hay không. Cho
ví dụ:
onPlaybackStateChanged
thànhSTATE_BUFFERING
do một mục nội dung đa phương tiện chuyển đổi.
Trong một số trường hợp, trình nghe có thể cần kết hợp các lệnh gọi lại riêng lẻ với
lệnh gọi lại onEvents
chung, ví dụ để ghi lại lý do thay đổi mục nội dung đa phương tiện
bằng onMediaItemTransition
, nhưng chỉ hành động khi có thể sử dụng tất cả thay đổi về trạng thái
cùng nhau trong onEvents
.
Sử dụng AnalyticsListener
Khi sử dụng ExoPlayer
, người chơi có thể đăng ký AnalyticsListener
bằng cách gọi addAnalyticsListener
. Có thể triển khai AnalyticsListener
để nghe các sự kiện chi tiết có thể hữu ích cho việc phân tích và ghi nhật ký
. Vui lòng tham khảo trang số liệu phân tích để biết thêm chi tiết.
Sử dụng EventLogger
EventLogger
là một AnalyticsListener
do thư viện cung cấp trực tiếp cho
mục đích ghi nhật ký. Thêm EventLogger
vào ExoPlayer
để kích hoạt thông tin hữu ích
ghi nhật ký bổ sung chỉ một dòng duy nhất:
Kotlin
player.addAnalyticsListener(EventLogger())
Java
player.addAnalyticsListener(new EventLogger());
Hãy xem trang ghi nhật ký gỡ lỗi để biết thêm thông tin chi tiết.
Sự kiện kích hoạt tại những vị trí phát đã chỉ định
Một số trường hợp sử dụng yêu cầu phải kích hoạt sự kiện tại những vị trí phát cụ thể. Đây là
được hỗ trợ bằng PlayerMessage
. Bạn có thể tạo PlayerMessage
bằng
ExoPlayer.createMessage
Vị trí phát mà đoạn mã sẽ được thực thi
có thể đặt bằng PlayerMessage.setPosition
. Thông báo được thực thi trên
theo mặc định, nhưng bạn có thể tuỳ chỉnh luồng này bằng cách sử dụng
PlayerMessage.setLooper
. Có thể sử dụng PlayerMessage.setDeleteAfterDelivery
để kiểm soát liệu thông báo có được thực thi mỗi lần lệnh được chỉ định hay không
gặp phải vị trí phát (điều này có thể xảy ra nhiều lần do tua
và chế độ lặp lại) hoặc chỉ lần đầu tiên. Sau khi PlayerMessage
được
đã định cấu hình, bạn có thể lên lịch sự kiện này bằng PlayerMessage.send
.
Kotlin
player .createMessage { messageType: Int, payload: Any? -> } .setLooper(Looper.getMainLooper()) .setPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 120000) .setPayload(customPayloadData) .setDeleteAfterDelivery(false) .send()
Java
player .createMessage( (messageType, payload) -> { // Do something at the specified playback position. }) .setLooper(Looper.getMainLooper()) .setPosition(/* mediaItemIndex= */ 0, /* positionMs= */ 120_000) .setPayload(customPayloadData) .setDeleteAfterDelivery(false) .send();