На этой странице описывается, как использовать 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, участвующим в совместном использовании в реальном времени. Подробную информацию о том, как получать широковещательные обновления от других участников, см. в разделе «Обработка входящих обновлений» .
На следующей диаграмме описана последовательность событий после срабатывания действия паузы:
Возобновить видео
Как и в случае с приостановкой видео , если пользователь снимает видео с паузы в своем локальном приложении, 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();
}
}
}