Поделиться через


Подписка на события SDK

Службы коммуникации Azure пакеты SDK являются динамическими и содержат много свойств. Когда эти изменения изменяются, как разработчик может потребоваться знать, когда и более важно, какие изменения. Вот как!

События в пакете SDK для вызовов связи Azure

В этом руководстве описаны различные события или свойства, которые могут подписаться на приложение. Подписка на эти события позволяет приложению получать сведения об изменении состояния в вызывающем пакете SDK и реагировать соответствующим образом.

Отслеживание событий имеет решающее значение, так как оно позволяет приложению оставаться синхронизированным с состоянием платформы ACSCalling, не требуя реализации механизма извлечения для объектов ПАКЕТА SDK.

В этом руководстве предполагается, что вы выполнили краткое руководство или реализовали приложение, которое может выполнять и принимать звонки. Если вы не выполнили руководство по началу работы, ознакомьтесь с нашим кратким руководством.

Каждый объект в пакете SDK для вызовов JavaScript имеет properties и collections. Их значения изменяются в течение всего времени существования объекта. Используйте метод on(), чтобы подписаться на события объектов, и метод off(), чтобы отменить эту подписку.

Свойства

Вы можете подписаться на '<property>Changed' событие, чтобы прослушивать изменения значений в свойстве.

Пример подписки для свойства

В этом примере мы подписываемся на изменения в значении isLocalVideoStarted свойства.

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

Коллекции

Вы можете подписаться на событие "<Коллекция>Обновлено", чтобы получать уведомления об изменениях в коллекции объектов. Событие "<Обновление коллекции>" активируется при каждом добавлении или удалении элементов из отслеживаемой коллекции.

  • В полезных данных события '<collection>Updated' имеется массив added, в котором содержатся значения, добавленные в коллекцию.
  • В полезных данных события '<collection>Updated' также имеется массив removed, в котором содержатся значения, удаленные из коллекции.

Пример подписки в коллекции

В этом примере мы подписываемся на изменения значений объекта LocalVideoStreamCall.

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

События объекта CallAgent

Имя события: incomingCall

Событие incomingCall возникает, когда клиент получает входящий вызов.

Как приложение должно реагировать на событие?

Приложение должно уведомить пользователя о входящем вызове. Запрос на уведомление должен предложить пользователю принять или отказаться от вызова.

Пример кода:

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

Имя события: callsUpdated

Обновленное callsUpdated событие запускается при удалении или добавлении вызова в агент вызова. Это событие происходит, когда пользователь делает, получает или завершает вызов.

Как приложение должно реагировать на событие? Приложение должно обновить пользовательский интерфейс на основе количества активных вызовов для экземпляра CallAgent.

Имя события: connectionStateChanged

Событие connectionStateChanged , возникающее при обновлении сигнального CallAgent состояния.

Как приложение должно реагировать на событие?

Приложение должно обновить пользовательский интерфейс на основе нового состояния. Возможные значения состояния подключения:ConnectedDisconnected

Пример кода:

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

События объекта Call

Имя события: stateChanged

Событие stateChanged запускается при изменении состояния вызова. Например, когда вызов переходит из connected disconnected.

Как приложение должно реагировать на событие?

Приложение должно соответствующим образом обновить пользовательский интерфейс. Отключение или включение соответствующих кнопок и других элементов пользовательского интерфейса на основе нового состояния вызова.

Пример кода:

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

Событие: idChanged

Событие idChanged запускается при изменении идентификатора вызова. Идентификатор вызова изменяется при перемещении вызова из connecting состояния connectedв . После подключения вызова идентификатор вызова остается идентичным.

Как ваше приложение может реагировать на событие?

Приложение должно сохранить новый идентификатор вызова, но его также можно получить из объекта вызова позже, когда это необходимо.

Пример кода:

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

Событие: isMutedChanged

Событие isMutedChanged запускается при отключении или отключении локального звука.

Как ваше приложение может реагировать на событие?

Приложение должно обновить кнопку выключения или отмены звука до правильного состояния.

Пример кода:

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

Событие: isScreenSharingOnChanged

Событие isScreenSharingOnChanged запускается при включении или отключении общего доступа к экрану для локального пользователя.

Как ваше приложение может реагировать на событие?

Приложение должно отображать предварительное просмотр и/или предупреждение пользователю, если общий доступ к экрану включен. Если общий доступ к экрану отключен, приложение должно удалить предварительный просмотр и предупреждение.

Пример кода:

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

Событие: isLocalVideoStartedChanged

Событие isLocalVideoStartedChanged запускается, когда пользователь включил наше локальное видео.

Как ваше приложение может реагировать на событие?

Приложение должно отобразить предварительную версию локального видео и включить или отключить кнопку активации камеры.

Пример кода:

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

Событие: remoteParticipantsUpdated

Приложение должно подписаться на событие для каждого добавленного RemoteParticipants и отменив подписку на события для участников, которые оставили звонок.

Как ваше приложение может реагировать на событие? Приложение должно отобразить предварительную версию локального видео и включить или отключить кнопку активации камеры.

Пример кода:

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

Событие: localVideoStreamsUpdated

Событие localVideoStreamsUpdated запускается при изменении списка локальных видеопотоков. Эти изменения происходят при запуске или удалении видеопотока.

Как ваше приложение может реагировать на событие?

Приложение должно отображать предварительные версии для каждого добавленного LocalVideoStream . Приложение должно удалить предварительный просмотр и остановить обработку для каждого LocalVideoStream удаленного.

Пример кода:

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

Событие: remoteAudioStreamsUpdated

Событие remoteAudioStreamsUpdated запускается при изменении списка удаленных звуковых потоков. Эти изменения происходят, когда удаленные участники добавляют или удаляют звуковые потоки в вызов.

Как ваше приложение может реагировать на событие?

Если поток обрабатывается и теперь удаляется, обработка должна быть остановлена. С другой стороны, если добавляется поток, прием событий является хорошим местом для начала обработки нового аудиопотока.

Событие: totalParticipantCountChanged

Вызывается totalParticipantCountChanged при изменении числа общей части вызова.

Как ваше приложение может реагировать на событие?

Если приложение отображает счетчик участника, приложение может обновить его счетчик участника при получении события.

Пример кода:

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

Событие: roleChanged

Участник roleChanged запускается при изменении локальных ролейParticipant в вызове. Примером будет, когда локальный участник становится выступающим ACSCallParticipantRolePresenter в вызове.

Как ваше приложение может реагировать на событие? Приложение должно включить или отключить кнопку на основе новой роли пользователя.

Пример кода:

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

Событие: mutedByOthers

Это mutedByOthers событие происходит, когда другие участники вызова отключаются локальным участником.

Как ваше приложение может реагировать на событие? Приложение должно отобразить сообщение пользователю, уведомляющее его о отключении.

Пример кода:

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

Событие: callerInfoChanged

Это callerInfoChanged событие происходит при обновлении сведений о вызывающем объекте.

Как ваше приложение может реагировать на событие? Приложение может обновлять сведения о вызывающем объекте.

Пример кода:

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

Событие: transferorInfoChanged

Событие transferorInfoChanged происходит при обновлении сведений о методе передачи.

Как ваше приложение может реагировать на событие? Приложение может обновить сведения о средстве передачи.

Пример кода:

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

События объекта RemoteParticipant

Событие: roleChanged

Событие roleChanged возникает при RemotePartipant изменении роли в вызове. Примером будет, когда remoteParticipant становится выступающим ACSCallParticipantRolePresenter в вызове.

Как ваше приложение может реагировать на событие? Приложение должно обновить пользовательский интерфейс на RemoteParticipant основе новой роли.

Пример кода:

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

Событие: isMutedChanged

Событие isMutedChanged возникает, когда один из RemoteParticipant отключенных или размыкает микрофон.

Как ваше приложение может реагировать на событие?

Приложение может отображать значок рядом с представлением, отображающим участника.

Пример кода:

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

Событие: displayNameChanged

Значение displayNameChanged при обновлении имени объекта RemoteParticipant .

Как ваше приложение может реагировать на событие?

Приложение должно обновить имя участника, если оно отображается в пользовательском интерфейсе.

Пример кода:

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

Событие: isSpeakingChanged

Когда isSpeakingChanged доминирующий динамик в вызове изменяется.

Как ваше приложение может реагировать на событие?

Пользовательский интерфейс приложения должен иметь приоритет для отображения RemotePartipant того, кто стал доминирующим динамиком.

Пример кода:

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

Событие: videoStreamsUpdated

Когда videoStreamsUpdated удаленный участник добавляет или удаляет видеопоток в вызов или из него.

Как ваше приложение может реагировать на событие?

Если приложение обрабатывает удаленный поток. Приложение должно остановить обработку. При добавлении нового потока приложение может потребовать отрисовки или обработки.

Пример кода:

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

Событие объекта AudioEffectsFeature

Событие: effectsStarted

Это событие возникает, когда выбранный звуковой эффект применяется к звуковому потоку. Например, когда кто-то включает подавление шума, effectsStarted будет уволен.

Как ваше приложение может реагировать на событие?

Приложение может отображать или включать кнопку, которая позволяет пользователю отключить звуковой эффект.

Пример кода:

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

Событие: effectsStopped

Это событие возникает, когда выбранный звуковой эффект применяется к звуковому потоку. Например, когда кто-то отключает подавление шума, effectsStopped будет уволен.

Как ваше приложение может реагировать на событие?

Приложение может отображать или включать кнопку, которая позволяет пользователю включить звуковой эффект.

Пример кода:

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

Событие: effectsError

Это событие возникает при возникновении ошибки при запуске или применении звукового эффекта.

Как ваше приложение может реагировать на событие?

Приложение должно отображать оповещение или сообщение об ошибке, что эффект звука не работает должным образом.

Пример кода:

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

Установка пакета SDK

Найдите файл уровня build.gradle проекта и добавьте mavenCentral() в список репозиториев в buildscript разделе и allprojects:

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

Затем в файле уровня build.gradle модуля добавьте в раздел следующие строки dependencies :

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

Инициализация обязательных объектов

Чтобы создать CallAgent экземпляр, необходимо вызвать createCallAgent метод в экземпляре CallClient . Этот вызов асинхронно возвращает объект экземпляра CallAgent .

Метод createCallAgent принимает CommunicationUserCredential в качестве аргумента, который инкапсулирует маркер доступа.

Чтобы получить доступ DeviceManager, сначала необходимо создать callAgent экземпляр. Затем можно использовать CallClient.getDeviceManager метод для получения 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();

Чтобы задать отображаемое имя для вызывающей стороны, используйте следующий альтернативный метод:

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

С помощью пакета SDK для Android вы можете подписаться на большинство свойств и коллекций, которые будут получать уведомления при изменении значений.

Свойства

Чтобы подписаться на события 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);

Если вы используете прослушиватели событий, определенные в одном классе, выполните привязку прослушивателя к переменной. Передайте переменную в качестве аргумента, чтобы добавить или удалить методы прослушивателя.

Если попытаться передать прослушиватель непосредственно в качестве аргумента, то ссылка на этот прослушиватель будет утрачена. Java создает новые экземпляры этих прослушивателей, а не ссылается на ранее созданные. Они по-прежнему будут запускаться, но их нельзя будет удалить, поскольку у вас больше не будет ссылки на эти экземпляры.

Коллекции

Чтобы подписаться на события 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);

Настройка системы

Выполните следующие действия, чтобы настроить систему.

Создайте проект Xcode

В Xcode создайте новый проект iOS и выберите шаблон Single View App (Приложение с одним представлением). В этой статье используется платформа SwiftUI, поэтому необходимо задать для языка значение Swift и задать для интерфейса значение SwiftUI.

Вы не собираетесь создавать тесты в этой статье. Снимите флажок "Включить тесты ".

Снимок экрана, на котором показано окно для создания проекта в Xcode.

Установка пакета и зависимостей с помощью CocoaPods

  1. Создайте Podfile для приложения, как показано в следующем примере:

    platform :ios, '13.0'
    use_frameworks!
    target 'AzureCommunicationCallingSample' do
        pod 'AzureCommunicationCalling', '~> 1.0.0'
    end
    
  2. Запустите pod install.

  3. Откройте .xcworkspace с помощью Xcode.

Запрос доступа к микрофону

Чтобы получить доступ к микрофону устройства, необходимо обновить список свойств приложения с помощью NSMicrophoneUsageDescription. Задайте связанное значение строке, включенной в диалоговое окно, которое система использует для запроса доступа от пользователя.

Щелкните правой кнопкой мыши запись Info.plist дерева проекта и выберите "Открыть как>исходный код". Добавьте в раздел верхнего уровня <dict> следующие строки, а затем сохраните файл.

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

Настройка платформы приложения

Откройте файл проекта ContentView.swift . import Добавьте объявление в начало файла для импорта библиотекиAzureCommunicationCalling. Кроме того, импортируйте AVFoundation. Он необходим для запросов на разрешение звука в коде.

import AzureCommunicationCalling
import AVFoundation

Инициализация CallAgent

Чтобы создать экземпляр CallAgent из CallClient, необходимо использовать метод callClient.createCallAgent, который асинхронно возвращает объект CallAgent после его инициализации.

Чтобы создать клиент вызова, передайте 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)
}

CommunicationTokenCredential Передайте созданный CallClientобъект и задайте отображаемое имя:

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

С помощью пакета SDK для iOS вы можете подписаться на большинство свойств и коллекций, чтобы получать уведомления при изменении значений.

Свойства

Чтобы подписаться на события property changed, используйте следующий код.

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

Коллекции

Чтобы подписаться на события collection updated, используйте следующий код.

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

Следующие шаги