Compartilhar via


Inscrever-se para eventos de SDK

Serviços de Comunicação do Azure SDKs são dinâmicos e contêm muitas propriedades. Quando elas mudam, você, como desenvolvedor, talvez queira saber quando e, mais importante, o que muda. Veja como.

Eventos no SDK de Chamada de Comunicação do Azure

Este guia descreve os vários eventos ou alterações de propriedades que seu aplicativo pode assinar. Assinar esses eventos permite que seu aplicativo seja informado sobre a alteração de estado no SDK de chamada e reaja adequadamente.

O acompanhamento de eventos é crucial porque permite que o estado do aplicativo permaneça sincronizado com o estado da estrutura ACSCalling, tudo sem exigir que você implemente um mecanismo de pull nos objetos do SDK.

Este guia pressupõe que você passou pelo Início Rápido ou que implementou um aplicativo capaz de fazer e receber chamadas. Se você não concluiu o guia de início, consulte nosso Início Rápido.

Cada objeto no SDK de chamada JavaScript tem properties e collections. Os valores deles mudam durante o tempo de vida do objeto. Use o método on() para assinar eventos de objetos, e use o método off() para cancelar a assinatura de eventos de objetos.

Propriedades

Você pode assinar o evento '<property>Changed' para ouvir as alterações de valor na propriedade.

Exemplo de assinatura em uma propriedade

Neste exemplo, assinamos alterações no valor da propriedade isLocalVideoStarted.

call.on('isLocalVideoStartedChanged', () => {
    // At that point the value call.isLocalVideoStarted is updated
    console.log(`isLocalVideoStarted changed: ${call.isLocalVideoStarted}`);
});

Coleções

Você pode assinar o evento '<collection>Updated' para receber notificações sobre alterações em uma coleção de objetos. O evento '<collection>Updated' é disparado sempre que os elementos são adicionados ou removidos da coleção que você está monitorando.

  • O conteúdo do evento '<collection>Updated' tem uma matriz added que contém valores que foram adicionados à coleção.
  • O conteúdo do evento '<collection>Updated' também tem uma matriz removed que contém valores que foram removidos da coleção.

Assinatura de exemplo em uma coleção

Neste exemplo, assinamos alterações nos valores do objeto Call LocalVideoStream.

call.on('localVideoStreamsUpdated', updateEvent => {
    updateEvent.added.forEach(async (localVideoStream) => {
        // Contains an array of LocalVideoStream that were added to the call
        // Add a preview and start any processing if needed
        handleAddedLocalVideoStream(localVideoStream )
    });
    updateEvent.removed.forEach(localVideoStream => {
        // Contains an array of LocalVideoStream that were removed from the call
        // Remove the preview and stop any processing if needed
        handleRemovedLocalVideoStream(localVideoStream ) 
    });
});

Eventos no objeto CallAgent

Nome do evento: incomingCall

O evento incomingCall é acionado quando o cliente está recebendo uma chamada de entrada.

Como seu aplicativo deve reagir ao evento?

Seu aplicativo deve notificar o usuário sobre a chamada de entrada. O prompt de notificação deve propor que o usuário aceite ou recuse a chamada.

Exemplo de código:

callClient.on('incomingCall', (async (incomimgCallEvent) => {
    try {
        // Store a reference to the call object
        incomingCall = incomimgCallEvent.incomingCall; 
        // Update your UI to allow
        acceptCallButton.disabled = false; 
        callButton.disabled = true;
    } catch (error) {
        console.error(error);
    }
});

Nome do evento: callsUpdated

O evento callsUpdated atualizado é acionado quando uma chamada é removida ou adicionada ao agente de chamada. Esse evento ocorre quando o usuário faz, recebe ou encerra a chamada.

Como seu aplicativo deve reagir ao evento? Seu aplicativo deve atualizar sua interface do usuário com base no número de chamadas ativas para a instância do CallAgent.

Nome do evento: connectionStateChanged

O evento connectionStateChanged é acionado quando o estado de sinalização do CallAgent é atualizado.

Como seu aplicativo deve reagir ao evento?

Seu aplicativo deve atualizar sua interface do usuário com base no novo estado. Os valores de estado de conexão possíveis são Connected e Disconnected

Exemplo de código:

callClient.on('connectionStateChanged', (async (connectionStateChangedEvent) => {
    if (connectionStateChangedEvent.newState === "Connected") {
        enableCallControls() // Enable all UI element that allow user to make a call
    }

    if (connectionStateChangedEvent.newState === 'Disconnected') {
        if (typeof connectionStateChangedEvent.reason !== 'undefined') {
            alert(`Disconnected reason: ${connectionStateChangedEvent.reason}`)
        } 
        disableCallControls() // Disable all the UI element that allows the user to make a call
    }
});

Eventos no objeto Call

Nome do evento: stateChanged

O evento stateChanged é acionado quando o estado da chamada é alterado. Por exemplo, quando uma chamada vai de connected para disconnected.

Como seu aplicativo deve reagir ao evento?

Seu aplicativo deve atualizar a interface do usuário adequadamente. Desabilitando ou habilitando botões apropriados e outros elementos de interface do usuário com base no novo estado de chamada.

Exemplo de código:

call.on('stateChanged', (async (connectionStateChangedEvent) => {
  if(call.state === 'Connected') {
      connectedLabel.hidden = false;
      acceptCallButton.disabled = true;
      startCallButton.disabled = true;
      startVideoButton.disabled = false;
      stopVideoButton.disabled = false
  } else if (call.state === 'Disconnected') {
      connectedLabel.hidden = true;
      startCallButton.disabled = false;
      console.log(`Call ended, call end reason={code=${call.callEndReason.code}, subCode=${call.callEndReason.subCode}}`);
  }
});

Evento: idChanged

O evento idChanged é acionado quando a ID de uma chamada é alterada. A ID de uma chamada é alterada quando a chamada passa do estado connecting para connected. Depois que a chamada estiver conectada, a ID da chamada permanecerá idêntica.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo deve salvar a nova ID de chamada, mas também pode ser recuperada do objeto de chamada mais tarde, quando necessário.

Exemplo de código:

let callId = "";
call.on('idChanged', (async (callIdChangedEvent) => {
  callId = call.id; // You can log it as the call ID is useful for debugging call issues
});

Evento: isMutedChanged

O evento isMutedChanged é acionado quando o áudio local é silenciado ou desativado.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo deve atualizar o botão de ativar/desativar mudo para o estado adequado.

Exemplo de código:

call.on('isMutedChanged', (async (isMutedChangedEvent) => {
    microphoneButton.disabled = call.isMuted;       
});

Evento: isScreenSharingOnChanged

O evento isScreenSharingOnChanged é acionado quando o compartilhamento de tela para o usuário local está habilitado ou desabilitado.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo deve mostrar uma visualização e/ou um aviso para o usuário se o compartilhamento de tela estiver ativado. Se o compartilhamento de tela tiver desativado, o aplicativo deverá remover a visualização e o aviso.

Exemplo de código:

call.on('isScreenSharingOnChanged', () => {
  if (!this.call.isScreenSharing) {
      displayStartScreenSharingButton();
      hideScreenSharingWarning()
      removeScreenSharingPreview();    
  } else {
      displayScreenSharingWarning()
      displayStopScreenSharingButton();
      renderScreenSharingPreview(); 
  }
});

Evento: isLocalVideoStartedChanged

O evento isLocalVideoStartedChanged é acionado quando o usuário habilita nosso vídeo local desabilitado.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo deve mostrar uma visualização do vídeo local e habilitar ou desabilitar o botão de ativação da câmera.

Exemplo de código:

call.on('isLocalVideoStartedChanged', () => {
    showdDisableCameraButton(call.isLocalVideoStarted);
});

Evento: remoteParticipantsUpdated

Seu aplicativo deve assinar o evento para cada evento adicionado a RemoteParticipants e cancelar a assinatura de eventos para participantes que saíram da chamada.

Como seu aplicativo pode reagir ao evento? Seu aplicativo deve mostrar uma visualização do vídeo local e habilitar ou desabilitar o botão de ativação da câmera.

Exemplo de código:

call.on('remoteParticipantsUpdated', (remoteParticipantsUpdatedEvent) => {
    remoteParticipantsUpdatedEvent.added.forEach(participant => {
        // handleParticipant should
        //   - subscribe to the remote participants events 
        //   - update the UI 
        handleParticipant(participant);
    });
    
    remoteParticipantsUpdatedEvent.removed.forEach(participant => {
        // removeParticipant should
        //   - unsubcribe from the remote participants events 
        //   - update the UI  
        removeParticipant(participant);
    });
});

Evento: localVideoStreamsUpdated

O evento localVideoStreamsUpdated é acionado quando a lista de fluxo de vídeo local é alterada. Essas alterações ocorrem quando o usuário inicia ou remove um fluxo de vídeo.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo deve mostrar visualizações para cada um dos LocalVideoStream adicionados. Seu aplicativo deve remover a visualização e interromper o processamento de cada LocalVideoStream removido.

Exemplo de código:

call.on('localVideoStreamsUpdated', (localVideoStreamUpdatedEvent) => {
    localVideoStreamUpdatedEvent.added.forEach(addedLocalVideoStream => { 
        // Add a preview and start any processing if needed
        handleAddedLocalVideoStream(addedLocalVideoStream) 
    });

    localVideoStreamUpdatedEvent.removed.forEach(removedLocalVideoStream => {
         // Remove the preview and stop any processing if needed
        this.handleRemovedLocalVideoStream(removedLocalVideoStream) 
    });
});

Evento: remoteAudioStreamsUpdated

O evento remoteAudioStreamsUpdated é acionado quando a lista de fluxo de áudio remoto muda. Essas alterações ocorrem quando os participantes remotos adicionam ou removem fluxos de áudio à chamada.

Como seu aplicativo pode reagir ao evento?

Se um fluxo estava sendo processado e agora é removido, o processamento deve ser interrompido. Por outro lado, se um fluxo for adicionado, a recepção do evento será um bom local para iniciar o processamento do novo fluxo de áudio.

Evento: totalParticipantCountChanged

O totalParticipantCountChanged aciona quando o número de totalParticipant foi alterado em uma chamada.

Como seu aplicativo pode reagir ao evento?

Se o aplicativo estiver exibindo um contador de participantes, seu aplicativo poderá atualizar o contador de participantes quando o evento for recebido.

Exemplo de código:

call.on('totalParticipantCountChanged', () => {
    participantCounterElement.innerText = call.totalParticipantCount;
});

Evento: roleChanged

O participante roleChanged é acionado quando as funções localParticipant são alteradas na chamada. Um exemplo seria quando o participante local se tornar apresentador ACSCallParticipantRolePresenter em uma chamada.

Como seu aplicativo pode reagir ao evento? Seu aplicativo deve habilitar ou desabilitar a base de botões na nova função do usuário.

Exemplo de código:

call.on('roleChanged', () => {
    this.roleElement = call.role;
});

Evento: mutedByOthers

O evento mutedByOthers ocorre quando o participante local ativou o mudo para outros participantes da chamada.

Como seu aplicativo pode reagir ao evento? Seu aplicativo deve exibir uma mensagem para o usuário notificando que o mudo dele foi ativado.

Exemplo de código:

call.on('mutedByOthers', () => {
    messageBanner.innerText = "You have been muted by other participant in this call";
});

Evento: callerInfoChanged

O evento callerInfoChanged ocorre quando as informações do chamador foram atualizadas.

Como seu aplicativo pode reagir ao evento? O aplicativo pode atualizar as informações do chamador.

Exemplo de código:

call.on('callerInfoChanged', () => {
    showCallerInfo(call.callerInfo)
});

Evento: transferorInfoChanged

O evento transferorInfoChanged ocorre quando as informações do transferidor foram atualizadas.

Como seu aplicativo pode reagir ao evento? O aplicativo pode atualizar as informações do transferidor.

Exemplo de código:

call.on('transferorInfoChanged', () => {
    showTransferorInfo(call.transferorInfo)
});

Eventos no objeto RemoteParticipant

Evento: roleChanged

O evento roleChanged é acionado quando a função RemotePartipant é alterada na chamada. Um exemplo seria quando o RemoteParticipant se tornar apresentador ACSCallParticipantRolePresenter em uma chamada.

Como seu aplicativo pode reagir ao evento? Seu aplicativo deve atualizar sua interface do usuário com base na nova função do RemoteParticipant.

Exemplo de código:

remoteParticipant.on('roleChanged', () => {
    updateRole(remoteParticipant);
});

Evento: isMutedChanged

O evento isMutedChanged é acionado quando um dos RemoteParticipant ativa ou desativa o mudo do microfone.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo pode exibir um ícone próximo à exibição que exibe o participante.

Exemplo de código:

remoteParticipant.on('isMutedChanged', () => {
    updateMuteStatus(remoteParticipant); // Update the UI based on the mute state of the participant
});

Evento: displayNameChanged

O displayNameChanged quando o nome do RemoteParticipant é atualizado.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo deverá atualizar o nome do participante se ele estiver sendo exibido na interface do usuário.

Exemplo de código:

remoteParticipant.on('displayNameChanged', () => {
    remoteParticipant.nameLabel.innerText = remoteParticipant.displayName;
});

Evento: isSpeakingChanged

O isSpeakingChanged quando o alto-falante dominante em uma chamada é alterado.

Como seu aplicativo pode reagir ao evento?

A interface do usuário do aplicativo deve dar prioridade para exibir o RemotePartipant que se tornou o orador dominante.

Exemplo de código:

remoteParticipant.on('isSpeakingChanged', () => {
    showAsRemoteSpeaker(remoteParticipant) // Display a speaking icon near the participant
});

Evento: videoStreamsUpdated

O videoStreamsUpdated quando um participante remoto adiciona ou remove um VideoStream de/para a chamada.

Como seu aplicativo pode reagir ao evento?

Se o aplicativo estava processando um fluxo que foi removido. Seu aplicativo deve interromper o processamento. Quando um novo fluxo é adicionado, seu aplicativo pode querer renderizá-lo ou processá-lo.

Exemplo de código:

remoteParticipant.on('videoStreamsUpdated', (videoStreamsUpdatedEvent) => {

     videoStreamsUpdatedEvent.added.forEach(addedRemoteVideoStream => { 
       // Remove a renderer and start processing the stream if any processing is needed
        handleAddedRemoteVideoStream(addedRemoteVideoStream) 
    });

    videoStreamsUpdatedEvent.removed.forEach(removedRemoteVideoStream => {
        // Remove the renderer and stop processing the stream if any processing is ongoing
        this.handleRemovedRemoteVideoStream(removedRemoteVideoStream) 
    });
});

Evento no objeto AudioEffectsFeature

Evento: effectsStarted

Esse evento ocorre quando o efeito de áudio selecionado é aplicado ao fluxo de áudio. Por exemplo, quando alguém ativa a Supressão de Ruído, o effectsStarted será acionado.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo pode exibir ou habilitar um botão que permite ao usuário desabilitar o efeito de áudio.

Exemplo de código:

audioEffectsFeature.on('effectsStarted', (effects) => {
    stopEffectButton.style.visibility = "visible"; 
});

Evento: effectsStopped

Esse evento ocorre quando o efeito de áudio selecionado é aplicado ao fluxo de áudio. Por exemplo, quando alguém desativa a Supressão de Ruído, o effectsStopped será acionado.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo pode exibir ou habilitar um botão que permite que o usuário habilite o efeito de áudio.

Exemplo de código:

audioEffectsFeature.on('effectsStopped', (effects) => {
    startEffectButton.style.visibility = "visible"; 
});

Evento: effectsError

Esse evento ocorre quando acontece um erro enquanto um efeito de áudio é iniciado ou aplicado.

Como seu aplicativo pode reagir ao evento?

Seu aplicativo deve exibir um alerta ou uma mensagem de erro informando que o efeito de áudio não está funcionando conforme o esperado.

Exemplo de código:

audioEffectsFeature.on('effectsError', (error) => {
    console.log(`Error with the audio effect ${error}`);
    alert(`Error with the audio effect`);
});

Instalar o SDK

Localize o arquivo build.gradle de nível do projeto e adicione mavenCentral() à lista de repositórios em buildscript e allprojects:

buildscript {
    repositories {
    ...
        mavenCentral()
    ...
    }
}
allprojects {
    repositories {
    ...
        mavenCentral()
    ...
    }
}

Em seguida, no arquivo build.gradle no nível do módulo, adicione as seguintes linhas à seção dependencies:

dependencies {
    ...
    implementation 'com.azure.android:azure-communication-calling:1.0.0'
    ...
}

Inicializar objetos necessários

Para criar uma instância CallAgent, você precisa chamar o método createCallAgent em uma instância CallClient. Essa chamada retorna de forma assíncrona um objeto de instância CallAgent.

O método createCallAgent usa CommunicationUserCredential como argumento, que encapsula um token de acesso.

Para acessar DeviceManager, você deverá criar uma instância callAgent primeiro. Em seguida, você poderá usar o método CallClient.getDeviceManager para obter DeviceManager.

String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential).get();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();

Para definir um nome de exibição para o chamador, use este método alternativo:

String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgentOptions callAgentOptions = new CallAgentOptions();
callAgentOptions.setDisplayName("Alice Bob");
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential, callAgentOptions).get();

Com o nosso SDK do Android, você pode assinar a maioria das propriedades e coleções para ser notificado quando os valores forem alterados.

Propriedades

Para assinar eventos property changed:

// subscribe
PropertyChangedListener callStateChangeListener = new PropertyChangedListener()
{
    @Override
    public void onPropertyChanged(PropertyChangedEvent args)
    {
        Log.d("The call state has changed.");
    }
}
call.addOnStateChangedListener(callStateChangeListener);

//unsubscribe
call.removeOnStateChangedListener(callStateChangeListener);

Quando você usa ouvintes de eventos definidos dentro da mesma classe, associe-os a uma variável. Passe a variável como um argumento para adicionar e remover métodos de ouvinte.

Se você tentar passar o ouvinte diretamente como um argumento, perderá a referência a esse ouvinte. O Java está criando instâncias desses ouvintes e não referenciando aquelas criadas anteriormente. Eles ainda serão disparados corretamente, mas não será possível removê-los devido à ausência de referência a eles.

Coleções

Para assinar eventos collection updated:

LocalVideoStreamsChangedListener localVideoStreamsChangedListener = new LocalVideoStreamsChangedListener()
{
    @Override
    public void onLocalVideoStreamsUpdated(LocalVideoStreamsEvent localVideoStreamsEventArgs) {
        Log.d(localVideoStreamsEventArgs.getAddedStreams().size());
        Log.d(localVideoStreamsEventArgs.getRemovedStreams().size());
    }
}
call.addOnLocalVideoStreamsChangedListener(localVideoStreamsChangedListener);
// To unsubscribe
call.removeOnLocalVideoStreamsChangedListener(localVideoStreamsChangedListener);

Configurar o backup do sistema

Siga essas etapas para configurar seu sistema.

Criar o projeto do Xcode

No Xcode, crie um projeto do iOS e selecione o modelo Aplicativo de Modo de Exibição Único. Como este artigo usa a estrutura SwiftUI, defina Linguagem como Swift e Interface como SwiftUI.

Você não criará testes neste artigo. Fique à vontade para limpar a caixa de seleção Incluir Testes.

Captura de tela que mostra a janela para a criação de um projeto no Xcode.

Instalar o pacote e as dependências usando o CocoaPods

  1. Crie um Podfile para seu aplicativo, como este exemplo:

    platform :ios, '13.0'
    use_frameworks!
    target 'AzureCommunicationCallingSample' do
        pod 'AzureCommunicationCalling', '~> 1.0.0'
    end
    
  2. Execute pod install.

  3. Abra o .xcworkspace usando o Xcode.

Solicitar acesso ao microfone

Para acessar o microfone do dispositivo, você precisa atualizar a lista de propriedades de informações do aplicativo usando NSMicrophoneUsageDescription. Defina o valor associado como uma cadeia de caracteres incluída na caixa de diálogo que é usada pelo sistema para solicitar o acesso do usuário.

Clique com o botão direito do mouse na entrada Info.plist da árvore de projeto e selecione Abrir Como>Código-Fonte. Adicione as linhas a seguir na seção do nível superior<dict>e, em seguida, salve o arquivo.

<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>

Configurar o framework de aplicativos

Abra o arquivo ContentView.swift do projeto. Adicione uma declaração import à parte superior do arquivo para importar a biblioteca AzureCommunicationCalling. Além disso, importeAVFoundation. Você precisa dele para solicitações de permissão de áudio no código.

import AzureCommunicationCalling
import AVFoundation

Inicialização do CallAgent

Para criar umaCallAgentinstânciaCallClient,você precisa usar um método callClient.createCallAgentque retorne de modo assíncrono um objetoCallAgentdepois que ele for inicializado.

Para criar um cliente de chamada, passe um objeto CommunicationTokenCredential:

import AzureCommunication

let tokenString = "token_string"
var userCredential: CommunicationTokenCredential?
do {
    let options = CommunicationTokenRefreshOptions(initialToken: token, refreshProactively: true, tokenRefresher: self.fetchTokenSync)
    userCredential = try CommunicationTokenCredential(withOptions: options)
} catch {
    updates("Couldn't created Credential object", false)
    initializationDispatchGroup!.leave()
    return
}

// tokenProvider needs to be implemented by Contoso, which fetches a new token
public func fetchTokenSync(then onCompletion: TokenRefreshOnCompletion) {
    let newToken = self.tokenProvider!.fetchNewToken()
    onCompletion(newToken, nil)
}

Passe o objeto CommunicationTokenCredential que você criou para CallClient e defina o nome de exibição:

self.callClient = CallClient()
let callAgentOptions = CallAgentOptions()
options.displayName = " iOS Azure Communication Services User"

self.callClient!.createCallAgent(userCredential: userCredential!,
    options: callAgentOptions) { (callAgent, error) in
        if error == nil {
            print("Create agent succeeded")
            self.callAgent = callAgent
        } else {
            print("Create agent failed")
        }
})

Com o nosso SDK do iOS, você pode assinar a maioria das propriedades e coleções para ser notificado quando os valores forem alterados.

Propriedades

Para assinarproperty changed os eventos, use o código a seguir.

call.delegate = self
// Get the property of the call state by getting on the call's state member
public func call(_ call: Call, didChangeState args: PropertyChangedEventArgs) {
{
    print("Callback from SDK when the call state changes, current state: " + call.state.rawValue)
}

// to unsubscribe
self.call.delegate = nil

Coleções

Para assinarcollection updated os eventos, use o código a seguir.

call.delegate = self
// Collection contains the streams that were added or removed only
public func call(_ call: Call, didUpdateLocalVideoStreams args: LocalVideoStreamsUpdatedEventArgs) {
{
    print(args.addedStreams.count)
    print(args.removedStreams.count)
}
// to unsubscribe
self.call.delegate = nil

Próximas etapas