Implementar a API Co-Doing

Esta página descreve como usar a API Co-Doing para oferecer suporte a uma situação de co-doing.

Configuração inicial

Para preparar a biblioteca para uso, o aplicativo de compartilhamento em tempo real precisa inicializar um objeto CoDoingClient que representa uma sessão de co-ação.

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 co-ação.

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 cliente de co-atividade:

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, verifique se todos os participantes também pausam 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 todos os outros participantes usando o método setGlobalState. O estado global compartilhado se torna o 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 para ser transmitido para todas as outras instâncias do Meet que participam da experiência de compartilhamento ao vivo. Para detalhes sobre como receber atualizações de transmissão de outros participantes, consulte a seção Processar atualizações recebidas.

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

Inicie o diagrama da API Live Share.

Retomar vídeo

Semelhante à pausa do vídeo, se o usuário retomar o vídeo no app local, o Meet vai precisar transmitir essa operação para 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 de retomada do lado 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 ao 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 vai precisar transmitir essa operação para todos os participantes.

O exemplo de código a seguir mostra como notificar os usuários sobre o carimbo de data/hora atualizado pelo 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);
}

Assistir outro vídeo

Se o usuário também alterar o vídeo que está sendo assistido selecionando outro vídeo no app local, o Meet precisará reproduzir o novo vídeo para todos os participantes do compartilhamento ao vivo. O vídeo alterado está armazenado em videoState.videoUrl.

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

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 cofazer

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

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

Processar atualizações recebidas

Quando o app Meet de outro participante recebe uma transmissão, o callback onGlobalStateChanged() é acionado. Normalmente, é importante tomar boas decisões sobre qual ação realizar em resposta às atualizações recebidas, como corresponder apenas os 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();
    }
  }
}