เหตุการณ์ของผู้เล่น

กำลังฟังเหตุการณ์การเล่น

เหตุการณ์ เช่น การเปลี่ยนแปลงสถานะและข้อผิดพลาดในการเล่น จะได้รับการรายงานไปยัง Player.Listener อินสแตนซ์ หากต้องการลงทะเบียนผู้ฟังเพื่อรับ กิจกรรม:

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 ไม่มีเมธอดเริ่มต้น คุณจึงต้องติดตั้งใช้งาน วิธีการที่คุณสนใจ โปรดดู Javadoc สำหรับคำอธิบายแบบเต็มของ เมธอดและเวลาที่เรียกใช้ วิธีการที่สำคัญที่สุดส่วนหนึ่ง ได้แก่ ตามที่อธิบายไว้โดยละเอียดด้านล่าง

ผู้ฟังมีตัวเลือกระหว่างการติดตั้งใช้งาน Callback เหตุการณ์แต่ละรายการหรือ Callback ทั่วไปของ onEvents ที่เรียกใช้หลังจากเกิดเหตุการณ์อย่างน้อย 1 เหตุการณ์ ดู Individual callbacks vs onEvents สำหรับคำอธิบายเกี่ยวกับ สำหรับกรณีการใช้งานที่แตกต่างกัน

การเปลี่ยนแปลงสถานะการเล่น

คุณสามารถรับการเปลี่ยนแปลงสถานะโปรแกรมเล่นวิดีโอได้โดยใช้ onPlaybackStateChanged(@State int state) ใน Player.Listener โดยโปรแกรมเล่นอาจอยู่ในสถานะการเล่นใดสถานะหนึ่งจาก 4 สถานะต่อไปนี้

  • Player.STATE_IDLE: นี่คือสถานะเริ่มต้น หรือสถานะเมื่อโปรแกรมเล่นวิดีโออยู่ และเมื่อการเล่นล้มเหลว โปรแกรมเล่นนี้จะมีทรัพยากรจำกัดเท่านั้น ในสถานะนี้
  • Player.STATE_BUFFERING: โปรแกรมเล่นจะไม่สามารถเล่นจากโปรแกรมเล่นได้ทันที ตำแหน่งปัจจุบัน ปัญหานี้มักเกิดขึ้นเพราะต้องโหลดข้อมูลเพิ่ม
  • Player.STATE_READY: โปรแกรมเล่นนี้จะเล่นจากสตรีมปัจจุบันได้ทันที ตำแหน่ง
  • Player.STATE_ENDED: โปรแกรมเล่นเล่นสื่อทั้งหมดเสร็จแล้ว

นอกจากรัฐเหล่านี้แล้ว ผู้เล่นยังมีธง playWhenReady เพื่อระบุ ที่ผู้ใช้ตั้งใจที่จะเล่น การเปลี่ยนแปลงใน Flag นี้สามารถรับได้โดยใช้การติดตั้งใช้งาน onPlayWhenReadyChanged(playWhenReady, @PlayWhenReadyChangeReason int reason)

โปรแกรมเล่นวิดีโอกำลังเล่น (กล่าวคือ ตำแหน่งของผู้เล่นคือความคืบหน้า และสื่อยังคงเล่นอยู่ แสดงแก่ผู้ใช้) เมื่อเป็นไปตามเงื่อนไขทั้ง 3 ข้อต่อไปนี้

  • โปรแกรมเล่นอยู่ในสถานะPlayer.STATE_READY
  • playWhenReadytrue
  • ไม่ได้ระงับการเล่นด้วยเหตุผลที่แสดงผลโดย Player.getPlaybackSuppressionReason

แทนที่จะต้องตรวจสอบคุณสมบัติเหล่านี้ทีละรายการ Player.isPlaying จะสามารถโทรออกได้ รับการเปลี่ยนแปลงสถานะนี้ได้โดยใช้ 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.
        }
      }
    });

ข้อผิดพลาดในการเล่น

คุณสามารถแก้ไขข้อผิดพลาดที่ทำให้การเล่นไม่สำเร็จโดยใช้ onPlayerError(PlaybackException error) ใน Player.Listener เมื่อเกิดข้อผิดพลาด ระบบจะเรียกใช้เมธอดนี้ ก่อนที่สถานะการเล่นจะเปลี่ยนเป็น Player.STATE_IDLE คุณลองเล่นที่ไม่สำเร็จหรือหยุดได้อีกโดยโทรหา ExoPlayer.prepare

โปรดทราบว่าการติดตั้งใช้งาน Player บางรายการผ่านอินสแตนซ์ของคลาสย่อยของ PlaybackException เพื่อระบุข้อมูลเพิ่มเติมเกี่ยวกับความล้มเหลว สำหรับ เช่น ExoPlayer ส่ง ExoPlaybackException ซึ่งมี type rendererIndex และช่องอื่นๆ สำหรับ ExoPlayer โดยเฉพาะ

ตัวอย่างต่อไปนี้แสดงวิธีตรวจสอบว่าเล่นไม่สำเร็จเนื่องจาก ปัญหาเกี่ยวกับเครือข่าย 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.
          }
        }
      }
    });

การเปลี่ยนเพลย์ลิสต์

ทุกครั้งที่โปรแกรมเล่นเปลี่ยนเป็นรายการสื่อใหม่ในเพลย์ลิสต์ onMediaItemTransition(MediaItem mediaItem, @MediaItemTransitionReason int reason) เรียกใช้เมื่อลงทะเบียน Player.Listener ออบเจ็กต์ เหตุผลระบุว่านี่เป็นการดำเนินการอัตโนมัติ การเปลี่ยน การกรอ (ตัวอย่างเช่น หลังจากเรียก player.next()) การกล่าวซ้ำๆ รายการเดียวกันหรือเกิดจากการเปลี่ยนแปลงเพลย์ลิสต์ (เช่น หาก รายการที่กำลังเล่นถูกนำออก)

ข้อมูลเมตา

ข้อมูลเมตาที่แสดงผลจาก player.getCurrentMediaMetadata() อาจมีการเปลี่ยนแปลงเนื่องจาก เหตุผล: การเปลี่ยนเพลย์ลิสต์ การอัปเดตข้อมูลเมตาในสตรีม หรือการอัปเดต การเล่นMediaItemตรงกลางปัจจุบัน

หากคุณต้องการเปลี่ยนแปลงข้อมูลเมตา เช่น เพื่ออัปเดต UI ที่แสดง เพลงปัจจุบัน คุณสามารถฟัง onMediaMetadataChanged ได้

กำลังค้นหา

การเรียกใช้ Player.seekTo วิธีจะทําให้เกิดการติดต่อกลับหลายครั้งเพื่อลงทะเบียน อินสแตนซ์ Player.Listener รายการ:

  1. onPositionDiscontinuity ด้วย reason=DISCONTINUITY_REASON_SEEK นี่คือ ผลลัพธ์โดยตรงจากการโทรหา Player.seekTo การติดต่อกลับมี PositionInfo สำหรับตำแหน่งก่อนและหลังการกรอ
  2. onPlaybackStateChanged โดยมีการเปลี่ยนแปลงสถานะในทันทีที่เกี่ยวข้องกับการค้นหา โปรดทราบว่าอาจไม่มีการเปลี่ยนแปลงดังกล่าว

การเรียกกลับแต่ละรายการเทียบกับ onEvents

ผู้ฟังสามารถเลือกระหว่างการติดตั้งใช้งาน Callback แต่ละรายการ เช่น onIsPlayingChanged(boolean isPlaying) และข้อกำหนดทั่วไป onEvents(Player player, Events events) Callback Callback ทั่วไปจะให้ สิทธิ์เข้าถึงออบเจ็กต์ Player และระบุชุดของ events ที่เกิดขึ้น Callback นี้จะถูกเรียกหลังจาก Callback ที่สอดคล้องกับ แต่ละเหตุการณ์

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);
  }
}

ควรเลือกใช้เหตุการณ์แต่ละรายการในกรณีต่อไปนี้

  • ผู้ฟังสนใจเหตุผลในการเปลี่ยนแปลง ตัวอย่างเช่น พารามิเตอร์ ระบุเหตุผลสำหรับ onPlayWhenReadyChanged หรือ onMediaItemTransition
  • Listener จะดำเนินการกับค่าใหม่ที่ระบุผ่านพารามิเตอร์ Callback เท่านั้น หรือทริกเกอร์อย่างอื่นที่ไม่ได้ขึ้นอยู่กับพารามิเตอร์ Callback
  • การใช้งาน Listener ต้องการตัวบ่งชี้ที่อ่านได้ชัดเจนว่า ทริกเกอร์เหตุการณ์ในชื่อเมธอด
  • ผู้ฟังรายงานไปยังระบบข้อมูลวิเคราะห์ที่จำเป็นต้องทราบ แต่ละเหตุการณ์และการเปลี่ยนแปลงสถานะ

ควรใช้ onEvents(Player player, Events events) ทั่วไปใน กรณีต่อไปนี้

  • Listener ต้องการทริกเกอร์ตรรกะเดียวกันสำหรับหลายเหตุการณ์ สำหรับ ตัวอย่างเช่น การอัปเดต UI สำหรับทั้ง onPlaybackStateChanged และ onPlayWhenReadyChanged
  • Listener ต้องการสิทธิ์เข้าถึงออบเจ็กต์ Player เพื่อทริกเกอร์เหตุการณ์เพิ่มเติม ตัวอย่างเช่น การกรอวิดีโอ หลังการเปลี่ยนรายการสื่อ
  • Listener ต้องการใช้ค่าสถานะหลายค่าที่มีการรายงาน ผ่าน Callback แยกต่างหากรวมกัน หรือใช้ร่วมกับ Getter ของ Player ตัวอย่างเช่น การใช้ Player.getCurrentWindowIndex() กับแท็ก Timeline ที่ให้ไว้ใน onTimelineChanged ปลอดภัยจากภายใน การติดต่อกลับ onEvents
  • ผู้ฟังต้องการทราบว่าเหตุการณ์ต่างๆ เกิดขึ้นพร้อมกันอย่างสมเหตุสมผลหรือไม่ สำหรับ ตัวอย่างเช่น onPlaybackStateChanged ถึง STATE_BUFFERING เนื่องจากรายการสื่อ การเปลี่ยนแปลง

ในบางกรณี ผู้ฟังอาจต้องรวมการเรียกกลับแต่ละรายการเข้ากับ Callback ทั่วไปของ onEvents เช่น เพื่อบันทึกเหตุผลที่เปลี่ยนแปลงรายการสื่อ กับ onMediaItemTransition แต่จะดำเนินการเมื่อสามารถเปลี่ยนสถานะทั้งหมดได้แล้วเท่านั้น ร่วมกันใน onEvents

กำลังใช้ AnalyticsListener

เมื่อใช้ ExoPlayer คุณจะลงทะเบียน AnalyticsListener กับโปรแกรมเล่นได้ โดยโทรไปที่ addAnalyticsListener การติดตั้งใช้งาน AnalyticsListener รายการได้ เพื่อฟังเหตุการณ์โดยละเอียดที่อาจเป็นประโยชน์สำหรับข้อมูลวิเคราะห์และการบันทึก วัตถุประสงค์ โปรดดูรายละเอียดเพิ่มเติมในหน้าข้อมูลวิเคราะห์

กำลังใช้ EventLogger

EventLogger เป็นAnalyticsListenerที่ห้องสมุดดนตรีโดยตรงสำหรับ วัตถุประสงค์ของการบันทึก เพิ่ม EventLogger ไปยัง ExoPlayer เพื่อเปิดใช้ การบันทึกเพิ่มเติมด้วยบรรทัดเดียว:

Kotlin

player.addAnalyticsListener(EventLogger())

Java

player.addAnalyticsListener(new EventLogger());

ดูรายละเอียดเพิ่มเติมได้ที่หน้าบันทึกการแก้ไขข้อบกพร่อง

การเริ่มทำงานที่ตำแหน่งการเล่นที่ระบุ

กรณีการใช้งานบางอย่างต้องการให้เหตุการณ์การเริ่มทำงานที่ตำแหน่งการเล่นที่ระบุ นี่คือ สนับสนุนโดยใช้ PlayerMessage PlayerMessage สามารถสร้างขึ้นได้โดยใช้ ExoPlayer.createMessage ตำแหน่งการเล่นที่ควรจะดำเนินการ ตั้งค่าได้โดยใช้ PlayerMessage.setPosition ข้อความจะดำเนินการใน เทรดการเล่นตามค่าเริ่มต้น แต่สามารถปรับแต่งได้โดยใช้ PlayerMessage.setLooper คุณใช้ PlayerMessage.setDeleteAfterDelivery ได้ เพื่อควบคุมว่าจะเรียกใช้ข้อความทุกครั้งที่ พบตำแหน่งการเล่น (ซึ่งอาจเกิดขึ้นได้หลายครั้งเนื่องจากการกรอวิดีโอ และโหมดซ้ำ) หรือแค่ครั้งแรก เมื่อ PlayerMessage คือ กำหนดค่าแล้ว ก็สามารถกำหนดเวลาโดยใช้ 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();