Внедрение API совместного выполнения

На этой странице описывается, как использовать API совместного выполнения для поддержки сценария совместного выполнения.

Начальная настройка

Чтобы подготовить библиотеку к использованию, приложение совместного использования в реальном времени должно инициализировать объект CoDoingClient , который представляет сеанс совместной работы.

Чтобы использовать SDK Meet Live Sharing, вызовите метод AddonClientFactory.getClient . Это возвращает AddonClient , который служит точкой входа для сеанса совместной работы.

Чтобы использовать клиент, вызовите метод newSessionBuilder из AddonClient , чтобы вернуть построитель для нового AddonSession . newSessionBuilder реализует интерфейс AddonSessionHandler для обработки обратных вызовов, предоставляемых надстройкой для сеанса.

Чтобы начать сеанс, добавьте в конструктор метод withCoDoing .

В следующем примере кода показана базовая инициализация объекта совместного клиента:

Джава

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 . Общее глобальное состояние становится состоянием по умолчанию для всех участников, существующих или новых, до тех пор, пока не будет установлено новое состояние.

В следующем примере кода показано, как уведомить пользователей о состоянии паузы:

Джава

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 запуска Live Sharing.

Возобновить видео

Как и в случае с паузой видео , если пользователь снимает видео с паузы в своем локальном приложении, Meet должен транслировать эту операцию другим участникам прямой трансляции.

На стороне отправителя (пользователя, который снимает видео с паузы) единственное отличие от примера с паузой заключается в том, что статус isPaused обновляется.

В следующем примере кода показано, как уведомить пользователей о состоянии без паузы со стороны отправителя:

Джава

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 должен транслировать эту операцию всем участникам.

В следующем примере кода показано, как уведомить пользователей об обновленной метке времени со стороны отправителя:

Джава

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-адресе видео:

Джава

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 завершать собрание и не заставляет пользователя покидать собрание.

В следующем примере кода показано, как уведомить пользователей об остановленном сеансе:

Джава

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

Обрабатывать входящие обновления

Когда приложение Meet другого участника получает широковещательную рассылку, срабатывает обратный вызов onGlobalStateChanged() . Обычно важно принять правильное решение о том, какие действия предпринять в ответ на входящие обновления, например сопоставлять временные метки входящих видео только в том случае, если они существенно отличаются от локальных временных меток.

В следующем примере кода показано, как обрабатывать различные входящие обновления:

Джава

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