นำ Co-Doing API ไปใช้

หน้านี้จะอธิบายวิธีใช้ Co-Doing API เพื่อสนับสนุนสถานการณ์ของการทำงานร่วมกัน

การตั้งค่าเบื้องต้น

แอปพลิเคชันการแชร์สดควรเริ่มต้นออบเจ็กต์ CoDoingClient ซึ่งแสดงเซสชันที่ทำร่วมกันเพื่อเตรียมไลบรารีสำหรับการใช้งาน

หากต้องการใช้ SDK การแชร์สดของ Meet ให้เรียกใช้เมธอด AddonClientFactory.getClient ซึ่งแสดงผล AddonClient ที่ทำหน้าที่เป็นจุดแรกเข้าของเซสชันการทำร่วมกัน

หากต้องการใช้ไคลเอ็นต์ ให้เรียกใช้เมธอด newSessionBuilder จาก AddonClient เพื่อแสดงเครื่องมือสร้างสำหรับ AddonSession ใหม่ newSessionBuilder ใช้อินเทอร์เฟซ AddonSessionHandler เพื่อจัดการการเรียกกลับที่ได้จากส่วนเสริมสำหรับเซสชัน

หากต้องการเริ่มเซสชัน ให้เพิ่มเมธอด withCoDoing ลงในเครื่องมือสร้าง

ตัวอย่างโค้ดต่อไปนี้แสดงการเริ่มต้นพื้นฐานของออบเจ็กต์ไคลเอ็นต์ที่ทำร่วมกัน

Java

class AwesomeVideoAddonSessionHandler implements AddonSessionHandler {}

//For sample implementation, see the "Handle incoming updates" section.
class AwesomeVideoCoDoingHandler implements CoDoingHandler {}

public ListenableFuture<AddonSession> initialSetup() {
  AddonClient meetClient = AddonClientFactory.getClient();
  return meetClient
      .newSessionBuilder(
          new AwesomeVideoAddonSessionHandler())
      .withCoDoing(new AwesomeVideoCoDoingHandler())
      .begin();
}

หยุดวิดีโอชั่วคราว

เมื่อมีส่วนร่วมในการแชร์สด หากผู้ใช้หยุดเล่นในแอปวิดีโอในเครื่องชั่วคราว คุณต้องตรวจสอบว่าผู้เข้าร่วมทุกคนในการแชร์สดได้หยุดวิดีโอของตนไว้ชั่วคราวด้วย

วิธีการคือให้ส่งข้อความ CoDoingState ที่แสดงว่าวิดีโอหยุดชั่วคราว แล้วบอกให้ Google Meet ประกาศแจ้งให้ผู้เข้าร่วมคนอื่นๆ ทุกคนทราบโดยใช้เมธอด setGlobalState สถานะทั่วโลกที่แชร์จะกลายเป็นสถานะเริ่มต้นสำหรับผู้เข้าร่วมทั้งหมด ไม่ว่าจะเป็นผู้เข้าร่วมที่มีอยู่หรือรายใหม่ จนกว่าจะมีการกำหนดสถานะใหม่

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีแจ้งให้ผู้ใช้ทราบถึงสถานะหยุดชั่วคราว

Java

public void onVideoPaused(String videoUrl, Instant currentTimestamp) {
  // Create an internal state object to share with other participants. Note: It's
  // good practice to encode all metadata—even seemingly irrelevant data—into
  // ActivityState updates to guard against race conditions and other subtle
  // failures.
  AwesomeVideoState videoState = AwesomeVideoState
    .builder()
    .videoUrl(videoUrl)
    .videoTimestamp(currentTimestamp)
    .isPaused(true)
    .build();

  // Create the CoDoingState object to wrap the internal state
  CoDoingState coDoingState = new CoDoingState();
  coDoingState.state = SerializationUtils.serialize(videoState);

  // Use Meet to broadcast internal state update to all other participants
  this.coDoingClient.setGlobalState(coDoingState);
};

ตัวอย่างโค้ดจะทริกเกอร์ออบเจ็กต์ videoState ที่ต่อเนื่องให้เผยแพร่ไปยังอินสแตนซ์อื่นๆ ทั้งหมดของ Meet ที่เข้าร่วมประสบการณ์การแชร์สด โปรดดูรายละเอียดเกี่ยวกับวิธีรับอัปเดตการประกาศจากผู้เข้าร่วมคนอื่นๆ ที่ส่วนจัดการการอัปเดตที่เข้ามา

แผนภาพต่อไปนี้อธิบายลำดับเหตุการณ์หลังจากที่การหยุดชั่วคราวทริกเกอร์

เริ่มแผนภาพ API การแชร์สด

เลิกหยุดวิดีโอชั่วคราว

เช่นเดียวกับหยุดวิดีโอชั่วคราว หากผู้ใช้ยกเลิกการหยุดวิดีโอชั่วคราวในแอปในเครื่อง Meet จะต้องเผยแพร่การดำเนินการนี้แก่ผู้เข้าร่วมการแชร์สดคนอื่นๆ

ทางฝั่งผู้ส่ง (ผู้ใช้ที่ยกเลิกการหยุดเล่นวิดีโอชั่วคราว) ความแตกต่างเพียงอย่างเดียวจากตัวอย่างการหยุดชั่วคราวคือการอัปเดตสถานะ isPaused

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีแจ้งให้ผู้ใช้ทราบถึงสถานะที่ไม่ได้หยุดชั่วคราวจากฝั่งผู้ส่ง

Java

public void onVideoUnpaused(String videoUrl, Instant currentTimestamp) {
  AwesomeVideoState videoState = AwesomeVideoState
    .builder()
    .videoUrl(videoUrl)
    .videoTimestamp(currentTimestamp)
    .isPaused(false)
    .build();

  CoDoingState coDoingState = new CoDoingState();
  coDoingState.state = SerializationUtils.serialize(videoState);

  this.coDoingClient.setGlobalState(coDoingState);
}

กรอวิดีโอ

เช่นเดียวกับหยุดวิดีโอชั่วคราวและยกเลิกการหยุดวิดีโอ หากผู้ใช้ลากไทม์ไลน์ในแอปในเครื่องไปยังการประทับเวลาใหม่ Meet จะต้องเผยแพร่การดำเนินการนี้ต่อผู้เข้าร่วมทุกคน

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีแจ้งให้ผู้ใช้ทราบเกี่ยวกับการประทับเวลาที่อัปเดตแล้วจากฝั่งผู้ส่ง

Java

public void onVideoSeeked(String videoUrl, Instant currentTimestamp, bool isPaused) {
  AwesomeVideoState videoState = AwesomeVideoState
    .builder()
    .videoUrl(videoUrl)
    .videoTimestamp(currentTimestamp)
    .isPaused(isPaused)
    .build();

  CoDoingState coDoingState = new CoDoingState();
  coDoingState.state = SerializationUtils.serialize(videoState);

  this.coDoingClient.setGlobalState(coDoingState);
}

เล่นวิดีโออื่น

หากผู้ใช้เปลี่ยนวิดีโอที่ดูอยู่โดยการเลือกวิดีโออื่นในแอปในพื้นที่ Meet จะต้องเล่นวิดีโอใหม่ให้กับผู้เข้าร่วมการแชร์สดทั้งหมด วิดีโอที่มีการเปลี่ยนแปลงจะจัดเก็บไว้ใน videoState.videoUrl

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีแจ้งให้ผู้ใช้ทราบเกี่ยวกับ URL ของวิดีโอที่อัปเดต

Java

public void onVideoChanged(String videoUrl, Duration currentTimestamp, bool isPaused) {
  AwesomeVideoState videoState = AwesomeVideoState
    .builder()
    .videoUrl(videoUrl)
    .videoTimestamp(currentTimestamp)
    .isPaused(isPaused)
    .build();

  CoDoingState coDoingState = new CoDoingState();
  coDoingState.state = SerializationUtils.serialize(videoState);

  this.coDoingClient.setGlobalState(coDoingState);
}

สิ้นสุดการทำงานร่วมกัน

เมื่อผู้ใช้เลือกที่จะสิ้นสุดกิจกรรม เมธอด endSession จะยกเลิกการเชื่อมต่อจากแอป Meet แต่จะไม่บังคับให้ Meet จบการประชุม และจะไม่ทำให้ผู้ใช้ออกจากการประชุม

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีแจ้งผู้ใช้เกี่ยวกับเซสชันที่หยุดแล้ว

Java

public void endCoDoing() {
  this.session.endSession();
}

จัดการการอัปเดตที่เข้ามาใหม่

เมื่อแอป Meet ของผู้เข้าร่วมรายอื่นได้รับการประกาศ ระบบจะทริกเกอร์การติดต่อกลับ onGlobalStateChanged() โดยปกติแล้ว คุณควรตัดสินใจให้ดีว่าจะทำอะไรเพื่อตอบสนองต่อการอัปเดตที่เข้ามาใหม่ เช่น การจับคู่การประทับเวลาของวิดีโอขาเข้าเฉพาะในกรณีที่แตกต่างจากการประทับเวลาในเครื่องมากพอ

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีจัดการกับอัปเดตต่างๆ ที่เข้ามา

Java

class AwesomeVideoCoDoingHandler implements CoDoingHandler {
  public void onGlobalStateChanged(CoDoingState update) {
    AwesomeVideoState videoState = SerializationUtils.deserialize(update.state());

    // Handle transition to new video.
    if (!videoState.videoUrl.equals(this.videoPlayer.videoUrl)) {
      this.videoPlayer.loadVideo(videoState.videoUrl);
    }

    // If the timestamp in the arriving update has sufficiently diverged, adjust
    // the local video playout.
    if (videoState.videoTimestamp.minus(this.videoPlayer.videoTimestamp).abs() >
                                        Duration.ofSeconds(2)) {
      this.videoPlayer.seek(videoState.videoTimestamp);
    }

    // Update pause state, if necessary.
    if (!videoState.isPaused && this.videoPlayer.isPaused) {
      this.videoPlayer.unpause();
    } else if (videoState.isPaused && !this.videoPlayer.isPaused) {
      this.videoPlayer.pause();
    }
  }
}