Partilhar via


Inscrever-se em eventos do SDK

Recomendamos subscrever aos Eventos de Chamadas do SDK. Os SDKs dos Serviços de Comunicação do Azure são dinâmicos e contêm propriedades que podem mudar ao longo do tempo. Pode subscrever estes eventos para ser notificado com antecedência de quaisquer alterações. Siga as instruções neste artigo para assinar eventos do SDK dos Serviços de Comunicação do Azure.

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

Esta secção descreve os eventos e as alterações de propriedade às quais o seu aplicativo pode subscrever. A assinatura desses eventos permite que seu aplicativo seja informado sobre a alteração de estado no SDK de chamada e reaja de acordo.

O acompanhamento de eventos é crucial porque permite que o estado do seu aplicativo permaneça sincronizado com o estado da estrutura de Chamada dos Serviços de Comunicação do Azure. O controle de eventos ajuda você a lidar com alterações sem implementar um mecanismo de pull nos objetos SDK.

Esta seção pressupõe que você passou pelo QuickStart ou que implementou um aplicativo capaz de fazer e receber chamadas. Se você não concluiu o guia de introdução, consulte Adicionar chamadas de voz ao seu aplicativo.

Cada objeto no SDK de chamada JavaScript tem properties e collections. Seus valores mudam ao longo da vida útil do objeto.

Use o on() método para se inscrever em eventos de objeto. Use o método off() para cancelar a inscrição em eventos de objeto.

Propriedades

Pode subscrever o evento '<property>Changed' para monitorizar as alterações de valor na propriedade.

Exemplo de subscrição numa propriedade

Neste exemplo, subscrevemos 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 se inscrever no \<collection>Updated evento para receber notificações sobre alterações em uma coleção de objetos. O \<collection>Updated evento é acionado sempre que elementos são adicionados ou removidos da coleção que você está monitorando.

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

Exemplo de assinatura em uma coleção

Neste exemplo, subscrevemos as 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 CallAgent objeto

Nome do evento: incomingCall

O incomingCall evento é acionado quando o cliente recebe uma chamada de entrada.

Como é que a sua candidatura reage ao evento?

Seu aplicativo deve notificar o destinatário da chamada recebida. O prompt de notificação precisa permitir que o destinatário aceite ou recuse a chamada.

Exemplo de código:

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

Nome do evento: callsUpdated

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

Como é que a sua candidatura reage 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 é disparado quando o estado de sinalização do CallAgent é atualizado.

Como é que a sua candidatura reage ao evento?

Seu aplicativo deve atualizar sua interface do usuário com base no novo estado. Os valores possíveis do estado de conexão 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 Call objeto

Nome do evento: stateChanged

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

Como é que a sua candidatura reage ao evento?

A sua aplicação deve atualizar a interface do utilizador de acordo com isso. Desativando ou habilitando botões apropriados e outros elementos da interface do usuário com base no novo estado da 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 idChanged evento é acionado quando a ID de uma chamada é alterada. A ID de uma chamada muda quando a chamada passa de connecting estado para connected. Uma vez que a chamada é conectada, o ID da chamada permanece idêntico.

Como é que a sua candidatura reage ao evento?

Seu aplicativo pode salvar a nova ID de chamada ou recuperá-la 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 isMutedChanged evento é acionado quando o áudio local é silenciado ou desativado.

Como é que a sua candidatura reage ao evento?

Seu aplicativo deve atualizar o botão mute / unmute para o estado adequado.

Exemplo de código:

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

Evento: isScreenSharingOnChanged

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

Como é que a sua candidatura reage 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 estiver desativado, o aplicativo deve 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 isLocalVideoStartedChanged evento é acionado quando o utilizador ativa ou desativa o seu vídeo local.

Como é que a sua candidatura reage ao evento?

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

Exemplo de código:

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

Evento: remoteParticipantsUpdated

A sua aplicação tem de subscrever os eventos para cada RemoteParticipants adicionado e cancelar a subscrição dos eventos para os participantes que saírem da chamada.

Como é que a sua candidatura reage ao evento?

Seu aplicativo deve mostrar uma visualização do vídeo local e ativar ou desativar 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
        //   - unsubscribe from the remote participants events 
        //   - update the UI  
        removeParticipant(participant);
    });
});

Evento: localVideoStreamsUpdated

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

Como é que a sua candidatura reage ao evento?

Seu aplicativo deve mostrar visualizações para cada um dos LocalVideoStream adicionados. O seu aplicativo deve remover a pré-visualização e parar o processamento para cada LocalVideoStream que for 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 fluxos de áudio remotos é alterada. Essas alterações acontecem quando participantes remotos adicionam ou removem fluxos de áudio à chamada.

Como é que a sua candidatura reage 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 receção do evento é um bom ponto de partida para o processamento do novo fluxo de áudio.

Evento: totalParticipantCountChanged

O totalParticipantCountChanged é acionado quando o número de totalParticipant é alterado em uma chamada.

Como é que a sua candidatura reage ao evento?

Se o seu aplicativo estiver exibindo um contador de participante, 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 roleChanged participante é acionado quando as funções localParticipant são alteradas na chamada. Um exemplo seria quando o participante local se tornasse apresentador numa chamada ACSCallParticipantRolePresenter.

Como é que a sua candidatura reage ao evento?

Seu aplicativo deve habilitar ou desabilitar o botão com base na nova função do usuário.

Exemplo de código:

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

Evento: mutedByOthers

O mutedByOthers evento acontece quando o participante local silencia outros participantes na chamada.

Como é que a sua candidatura reage ao evento?

O seu aplicativo deve exibir uma mensagem ao utilizador notificando que está silenciado.

Exemplo de código:

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

Evento: callerInfoChanged

O callerInfoChanged evento acontece quando as informações do chamador foram atualizadas. Isso ocorre quando um chamador altera seu nome para exibição.

Como é que a sua aplicação reage ao evento? O aplicativo pode atualizar as informações do chamador.

Exemplo de código:

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

Evento: transferorInfoChanged

O transferorInfoChanged evento acontece quando as informações do cedente foram atualizadas. Isso ocorre quando um cedente altera seu nome de exibição.

Como é que a sua aplicação reage ao evento? O aplicativo pode atualizar as informações do transferidor.

Exemplo de código:

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

Eventos no RemoteParticipant objeto

Evento: roleChanged

O roleChanged evento é acionado quando a RemoteParticipant função é alterada na chamada. Um exemplo seria quando o ParticipanteRemoto se tornasse apresentador ACSCallParticipantRolePresenter numa chamada.

Como é que a sua candidatura reage ao evento?

Seu aplicativo deve atualizar sua interface do usuário com base na RemoteParticipant nova função.

Exemplo de código:

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

Evento: isMutedChanged

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

Como é que a sua candidatura reage ao evento?

Seu aplicativo pode exibir um ícone perto da 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 é que a sua candidatura reage ao evento?

Seu aplicativo deve 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;
});
remoteParticipant.on('displayNameChanged', (args: {newValue?: string, oldValue?: string, reason?: DisplayNameChangedReason}) => {
    remoteParticipant.nameLabel.innerText = remoteParticipant.displayName;
    console.log(`Display name changed from ${oldValue} to ${newValue} due to ${reason}`);
});

Evento: isSpeakingChanged

O isSpeakingChanged quando o orador dominante numa chamada muda.

Como é que a sua candidatura reage ao evento?

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

Exemplo de código:

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

Evento: videoStreamsUpdated

Ocorre quando videoStreamsUpdated um participante remoto adiciona ou remove um fluxo de vídeo para/de a chamada.

Como é que a sua candidatura reage ao evento?

Se o seu aplicativo estava processando um fluxo que foi removido, seu aplicativo deve parar o processamento. Quando um novo fluxo é adicionado, recomendamos que seu aplicativo comece a 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 liga a supressão de ruído, o effectsStarted dispara.

Como é que a sua candidatura reage ao evento?

Seu aplicativo pode exibir ou ativar um botão que permite ao usuário desativar 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 é acionado.

Como é que a sua candidatura reage ao evento?

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

Exemplo de código:

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

Evento: effectsError

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

Como é que a sua candidatura reage ao evento?

Seu aplicativo deve exibir um alerta ou uma mensagem de erro de 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 ficheiro build.gradle ao nível do projeto e adicione mavenCentral() à lista de repositórios sob buildscript e allprojects:

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

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

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

Inicializar os objetos necessários

Para criar uma instância de CallAgent, tem de chamar o método createCallAgent numa instância de CallClient. A chamada retorna um objeto de instância CallAgent de forma assíncrona.

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

Para aceder DeviceManager, deves primeiro criar uma instância callAgent. Depois pode 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();

Agora que instalou o Android SDK, pode subscrever a maioria das propriedades e coleções para ser notificado quando os valores forem alterados.

Propriedades

Para subscrever 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, vincule o ouvinte a uma variável. Para adicionar e remover métodos de ouvinte, passe a variável como um argumento.

Se tentares passar o ouvinte diretamente como um argumento, perdes a referência a esse ouvinte. Java está criando novas instâncias desses ouvintes e não fazendo referência a instâncias criadas anteriormente. Eles ainda disparam corretamente, mas não podem ser removidos porque você não tem mais uma referência a eles.

Coleções

Para subscrever 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);

Configure o seu sistema

Siga estes passos para configurar o seu sistema.

Criar o projeto Xcode

Em Xcode, crie um novo projeto iOS e selecione o modelo Aplicação de Visualização Única. Este artigo utiliza a estrutura SwiftUI. Portanto, deve definir-se a linguagem como Swift e a interface como SwiftUI.

Não vais criar testes neste artigo. Sinta-se à vontade para desmarcar a opção Incluir testes.

Captura de tela que mostra a janela para criar um projeto no Xcode.

Instale o pacote e as dependências utilizando 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 .xcworkspace usando o Xcode.

Solicitar acesso ao microfone

Para aceder ao microfone do dispositivo, é necessário atualizar a lista de propriedades de informações da sua aplicação utilizando NSMicrophoneUsageDescription. Defina o valor associado para uma cadeia de texto que está incluída no diálogo que o sistema utiliza para solicitar acesso ao utilizador.

Clique com o botão direito na entrada Info.plist da árvore do projeto e, em seguida, selecione Abrir Como>Código Fonte. Adicione as seguintes linhas na secção de nível superior <dict>, e depois guarde o ficheiro.

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

Configurar a estrutura do aplicativo

Abra o ficheiro ContentView.swift do seu projeto. Adicione uma declaração import no início do ficheiro para importar a biblioteca AzureCommunicationCalling. Além disso, importe AVFoundation. Você precisa dele para solicitações de permissão de áudio no código.

import AzureCommunicationCalling
import AVFoundation

Inicializar CallAgent

Para criar uma CallAgent instância a partir do CallClient, você precisa usar um callClient.createCallAgent método que retorna de forma assíncrona um CallAgent objeto depois que ele é 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")
        }
})

Agora que instalou o SDK do iOS, pode subscrever a maioria das propriedades e coleções para ser notificado quando os valores forem alterados.

Propriedades

Para se inscrever em property changed 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 se inscrever em collection updated 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óximos passos