Implementar a API Co-Doing

Nesta página, descrevemos como usar a API Co-Doing para oferecer suporte a um cenário de co-Doing.

Configuração inicial

Para preparar a biblioteca para uso, o aplicativo de compartilhamento ao vivo precisa inicializar um objeto CoDoingClient que representa uma sessão de ação conjunta.

Para usar o SDK de compartilhamento ao vivo do Meet, chame o método AddonClientFactory.getClient. Isso retorna um AddonClient que serve como ponto de entrada para a sessão de ação conjunta.

Para usar o cliente, chame o método newSessionBuilder do AddonClient para retornar um builder para um novo AddonSession. O newSessionBuilder implementa a interface AddonSessionHandler para processar os callbacks fornecidos pelo complemento para a sessão.

Para iniciar uma sessão, adicione o método withCoDoing ao builder.

O exemplo de código a seguir mostra uma inicialização básica do objeto de cliente em conjunto:

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

Pausar vídeo

Ao participar de uma experiência de compartilhamento ao vivo, se um usuário pausar a reprodução no app de vídeo local, será preciso garantir que todos os participantes da experiência também pausem o vídeo.

Para fazer isso, crie uma mensagem CoDoingState mostrando que o vídeo está pausado e peça para o Google Meet transmitir para ele para todos os outros participantes usando o método setGlobalState. O estado global compartilhado se torna o estado padrão para todos os participantes, existentes ou novos, até que um novo estado seja definido.

O exemplo de código a seguir mostra como notificar os usuários sobre o estado pausado:

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

O exemplo de código aciona o objeto videoState serializado que é transmitido para todas as outras instâncias do Meet que participam da experiência de compartilhamento ao vivo. Para saber mais sobre como receber atualizações de transmissão de outros participantes, consulte a seção Processar atualizações de entrada.

O diagrama a seguir descreve a sequência de eventos após o acionamento da ação de pausa:

Iniciar o diagrama da API Live Share.

Retomar vídeo

Semelhante à pausa do vídeo, se um usuário retomar o vídeo no app local, o Meet vai transmitir essa operação para os outros participantes do compartilhamento ao vivo.

No lado do remetente (o usuário que retoma o vídeo), a única diferença do exemplo de pausa é que o status isPaused é atualizado.

O exemplo de código a seguir mostra como notificar os usuários sobre o estado não pausado do remetente:

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

Procurar vídeo

Assim como os recursos pausar vídeo e retomar vídeo, se um usuário arrastar a linha do tempo no app local para uma nova marcação de tempo, o Meet precisará transmitir essa operação a todos os participantes.

O exemplo de código a seguir mostra como notificar os usuários sobre o carimbo de data/hora atualizado do remetente:

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

Abrir outro vídeo

Se o usuário selecionar outro vídeo no app local para mudar o vídeo, o Meet precisará exibir o novo vídeo para todos os participantes do compartilhamento ao vivo. O vídeo alterado é armazenado em videoState.videoUrl.

O exemplo de código a seguir mostra como notificar os usuários sobre o URL do vídeo atualizado:

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

Encerrar a ação conjunta

Quando um usuário decide encerrar a atividade, o método endSession se desconecta do app Meet. Isso não força o Meet a encerrar a reunião nem faz com que o usuário saia dela.

O exemplo de código a seguir mostra como notificar os usuários sobre a sessão interrompida:

Java

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

Gerenciar atualizações recebidas

Quando o app Meet de outro participante recebe uma transmissão, o callback onGlobalStateChanged() é acionado. Geralmente, é importante tomar boas decisões sobre que ação tomar em resposta a atualizações recebidas, como corresponder apenas carimbos de data/hora de vídeo recebidos se eles forem suficientemente diferentes do carimbo de data/hora local.

O exemplo de código a seguir mostra como processar as diferentes atualizações recebidas:

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