Подписка на события 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
, в котором содержатся значения, удаленные из коллекции.
Пример подписки в коллекции
В этом примере мы подписываемся на изменения значений объекта LocalVideoStream
Call.
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
состояния.
Как приложение должно реагировать на событие?
Приложение должно обновить пользовательский интерфейс на основе нового состояния. Возможные значения состояния подключения:Connected
Disconnected
Пример кода:
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.
Вы не собираетесь создавать тесты в этой статье. Снимите флажок "Включить тесты ".
Установка пакета и зависимостей с помощью CocoaPods
Создайте Podfile для приложения, как показано в следующем примере:
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 1.0.0' end
Запустите
pod install
.Откройте
.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