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