Управление вызовами
Узнайте, как управлять вызовами с помощью пакетов SDK Службы коммуникации Azure. Мы научимся размещать вызовы, управлять своими участниками и свойствами.
Необходимые компоненты
- Учетная запись Azure с активной подпиской. Создайте учетную запись бесплатно .
- Развернутый ресурс Служб коммуникации. Создайте ресурс Служб коммуникации.
User Access Token
для включения клиента вызова. Дополнительные сведения о том, как получитьUser Access Token
- (Необязательно) Выполните инструкции из краткого руководства Добавление функции голосового вызова в приложение.
Установка пакета SDK
npm install
Используйте команду для установки пакета SDK Службы коммуникации Azure Common and Calling SDK для JavaScript:
npm install @azure/communication-common --save
npm install @azure/communication-calling --save
Инициализация обязательных объектов
Экземпляр CallClient
требуется для большинства операций вызова. При создании нового CallClient
экземпляра его можно настроить с помощью пользовательских параметров, таких как Logger
экземпляр.
С помощью экземпляра CallClient
можно создать CallAgent
экземпляр, вызвав его createCallAgent
. Этот метод асинхронно возвращает объект экземпляра CallAgent
.
Метод createCallAgent
использует CommunicationTokenCredential
в качестве аргумента. Он принимает маркер доступа пользователя.
Можно применить метод getDeviceManager
для экземпляра CallClient
, чтобы получить доступ к deviceManager
.
const { CallClient } = require('@azure/communication-calling');
const { AzureCommunicationTokenCredential} = require('@azure/communication-common');
const { AzureLogger, setLogLevel } = require("@azure/logger");
// Set the logger's log level
setLogLevel('verbose');
// Redirect log output to console, file, buffer, REST API, or whatever location you want
AzureLogger.log = (...args) => {
console.log(...args); // Redirect log output to console
};
const userToken = '<USER_TOKEN>';
callClient = new CallClient(options);
const tokenCredential = new AzureCommunicationTokenCredential(userToken);
const callAgent = await callClient.createCallAgent(tokenCredential, {displayName: 'optional Azure Communication Services user name'});
const deviceManager = await callClient.getDeviceManager()
Управление подключением пакета SDK к инфраструктуре Майкрософт
Экземпляр Call Agent
помогает управлять вызовами (для присоединения или запуска вызовов). Для работы пакета SDK для вызова необходимо подключиться к инфраструктуре Майкрософт для получения уведомлений о входящих звонках и координации других сведений о вызове. У вас Call Agent
есть два возможных состояния:
Подключено — Call Agent
значение Connected
connectionStatue означает, что клиентский пакет SDK подключен и способен получать уведомления из инфраструктуры Майкрософт.
Отключено — Call Agent
значение connectionStatue состояний Disconnected
возникает проблема, которая препятствует правильному подключению пакета SDK. Call Agent
необходимо повторно создать.
invalidToken
: если срок действия маркера истек или является недопустимымCall Agent
экземпляром, отключается с этой ошибкой.connectionIssue
: если возникла проблема с клиентом, подключающимся к инфраструктуре Майкрософт, после многих повторных попытокCall Agent
возникаетconnectionIssue
ошибка.
Вы можете проверить, подключен ли локальный сервер Call Agent
к инфраструктуре Майкрософт, проверив текущее значение connectionState
свойства. Во время активного вызова можно прослушивать connectionStateChanged
событие, чтобы определить, изменяются ли Call Agent
изменения из подключенного к отключенном состоянию.
const connectionState = callAgentInstance.connectionState;
console.log(connectionState); // it may return either of 'Connected' | 'Disconnected'
const connectionStateCallback = (args) => {
console.log(args); // it will return an object with oldState and newState, each of having a value of either of 'Connected' | 'Disconnected'
// it will also return reason, either of 'invalidToken' | 'connectionIssue'
}
callAgentInstance.on('connectionStateChanged', connectionStateCallback);
Осуществление вызовов
Чтобы создать и запустить вызов, используйте один из API callAgent
и укажите пользователя, созданного с помощью пакета SDK удостоверений служб коммуникации.
Операции создания и начала вызовов выполняются синхронно. Экземпляр call
позволяет подписываться на события вызова.
Осуществление вызова 1:n к пользователю или ТСОП
Чтобы осуществить вызов к другому пользователю Служб коммуникации, вызовите метод startCall
для callAgent
и передайте CommunicationUserIdentifier
получателя, который вы создали с помощью библиотеки администрирования Служб коммуникации.
Для вызова пользователя "1:1" используйте следующий код:
const userCallee = { communicationUserId: '<ACS_USER_ID>' }
const oneToOneCall = callAgent.startCall([userCallee]);
Чтобы осуществить вызов к телефонной сети общего пользования (ТСОП), вызовите метод startCall
для callAgent
и передайте PhoneNumberIdentifier
получателя. Для осуществления вызовов к ТСОП необходимо настроить ресурс Служб коммуникации.
При вызове номера ТСОП необходимо указать альтернативный идентификатор вызывающего. Альтернативный идентификатор вызывающего обозначает номер телефона (по стандарту E.164), который определяет вызывающую сторону в вызове ТСОП. Это номер телефона, который получатель вызова видит при входящем вызове.
Примечание.
Ознакомьтесь с подробными сведениями о предложении звонков по ТСОП. Для доступа к программе предварительной версии применяется к программе раннего внедрения.
Для осуществления персонального вызова по номеру PSTN используйте следующий код:
const pstnCallee = { phoneNumber: '<ACS_USER_ID>' }
const alternateCallerId = {phoneNumber: '<ALTERNATE_CALLER_ID>'};
const oneToOneCall = callAgent.startCall([pstnCallee], { alternateCallerId });
Для осуществления вызова пользователю с несколькими участниками по номеру PSTN используйте следующий код:
const userCallee = { communicationUserId: '<ACS_USER_ID>' }
const pstnCallee = { phoneNumber: '<PHONE_NUMBER>'};
const alternateCallerId = {phoneNumber: '<ALTERNATE_CALLER_ID>'};
const groupCall = callAgent.startCall([userCallee, pstnCallee], { alternateCallerId });
Присоединение к вызову комнаты
Чтобы присоединиться к вызову room
, можно создать экземпляр объекта контекста с roomId
свойством в качестве идентификатора room
. Чтобы присоединиться к вызову join
, используйте метод и передайте экземпляр контекста.
const context = { roomId: '<RoomId>' }
const call = callAgent.join(context);
Разработчики room
приложений лучше управляют тем, кто может присоединиться к вызову, когда они встречаются и как они сотрудничают. Дополнительные сведения см rooms
. в концептуальной документации или кратком руководстве по началу работы.
Присоединение к групповому вызову
Примечание.
Параметр groupId
считается системными метаданными и может использоваться корпорацией Майкрософт для выполнения операций, необходимых для запуска системы. Не включайте личные данные в значение groupId
. Корпорация Майкрософт не считает этот параметр личными данными, и его содержимое может быть доступно сотрудникам корпорации Майкрософт или отправлено на долгосрочное хранение.
Параметр groupId
требует, чтобы данные имели формат GUID. Рекомендуется использовать созданные случайным образом GUID, которые в ваших системах не считаются личными данными.
Чтобы начать новый групповой вызов или присоединиться к текущему групповому вызову, примените метод join
и передайте ему объект со свойством groupId
. В качестве значения groupId
должен быть указан идентификатор GUID.
const context = { groupId: '<GUID>'};
const call = callAgent.join(context);
Прием входящего вызова
Экземпляр callAgent
создает событие incomingCall
, когда зарегистрированный в системе идентификатор принимает входящий вызов. Чтобы прослушать это событие, подпишитесь с помощью одного из следующих вариантов.
const incomingCallHandler = async (args: { incomingCall: IncomingCall }) => {
const incomingCall = args.incomingCall;
// Get incoming call ID
var incomingCallId = incomingCall.id
// Get information about this Call. This API is provided as a preview for developers
// and may change based on feedback that we receive. Do not use this API in a production environment.
// To use this api please use 'beta' release of Azure Communication Services Calling Web SDK
var callInfo = incomingCall.info;
// Get information about caller
var callerInfo = incomingCall.callerInfo
// Accept the call
var call = await incomingCall.accept();
// Reject the call
incomingCall.reject();
// Subscribe to callEnded event and get the call end reason
incomingCall.on('callEnded', args => {
console.log(args.callEndReason);
});
// callEndReason is also a property of IncomingCall
var callEndReason = incomingCall.callEndReason;
};
callAgentInstance.on('incomingCall', incomingCallHandler);
Событие incomingCall
включает экземпляр incomingCall
, который можно принять или отклонить.
Пакет SDK для вызова связи Azure вызывает камеруStartFailed: диагностику истинного вызова, если камера недоступна при запуске, принятии или присоединении к вызову с включенным видео. В этом случае вызов начинается с видео выключения. Камера может быть недоступна, так как она используется другим процессом или отключена в операционной системе.
Удержание и возобновление вызова
Примечание.
В любой момент времени должно быть только 1 активный вызов (в Connected
состоянии с активным носителем). Все остальные вызовы должны храниться пользователем или программно по приложению. Это обычно в таких сценариях, как центры контактов, где пользователю может потребоваться обрабатывать несколько исходящих и входящих вызовов, все неактивные вызовы должны быть помещены в удержание, и пользователь должен взаимодействовать с другими пользователями только в активном вызове.
Для удержания или возобновления вызова можно использовать hold
асинхронные resume
API:
Удержание вызова
await call.hold();
При hold
разрешении API для состояния вызова задано значение LocalHold
. В вызове 1:1 другой участник также помещается на удержание, а состояние вызова с точки зрения этого участника имеет значение RemoteHold. Позже другой участник может поместить свой вызов на удержание, что приведет к изменению LocalHold
состояния.
В групповом вызове или собрании — hold
это локальная операция, она не проводит звонок для других участников звонка.
Чтобы возобновить вызов всех пользователей, инициирувших удержание, необходимо возобновить его.
Чтобы возобновить вызов из удержания:
await call.resume();
resume
При разрешении API состояние вызова снова задаетсяConnected
.
Отключение и отмена вызова
Чтобы отключить или включить звук для локальной конечной точки, можно использовать асинхронные вызовы API mute
и unmute
:
//mute local device (microphone / sent audio)
await call.mute();
//unmute local device (microphone / sent audio)
await call.unmute();
Отключение и отключение входящего звука
Отключение входящего звука задает для тома вызова значение 0. Чтобы отключить или отменить входящий звук, можно использовать muteIncomingAudio
асинхронные unmuteIncomingAudio
API:
//mute local device (speaker)
await call.muteIncomingAudio();
//unmute local device (speaker)
await call.unmuteIncomingAudio();
При отключении входящего звука пакет SDK клиента участника по-прежнему получает звук вызова (звук удаленного участника). Звук вызова не услышится в динамике, и участник не сможет прослушивать до вызова call.unmuteIncomingAudio(). Однако мы можем применить фильтр к звуку вызова и воспроизвести отфильтрованный звук.
Управление удаленными участниками
Все удаленные участники подробно описаны в RemoteParticipant
объекте и доступны через remoteParticipants
коллекцию в экземпляре вызова. Он remoteParticipants
доступен из экземпляра Call
.
Вывод списка участников в вызове
Коллекция remoteParticipants
возвращает список удаленных участников в вызове:
call.remoteParticipants; // [remoteParticipant, remoteParticipant....]
Добавление участника в вызов
Чтобы добавить участника (пользователя или номер телефона) в звонок, можно использовать addParticipant
API. Предоставьте один из типов Identifier
. Он синхронно возвращает экземпляр remoteParticipant
. Событие remoteParticipantsUpdated
из вызова вызывается при успешном добавлении участника к вызову.
const userIdentifier = { communicationUserId: '<ACS_USER_ID>' };
const pstnIdentifier = { phoneNumber: '<PHONE_NUMBER>' }
const remoteParticipant = call.addParticipant(userIdentifier);
const alternateCallerId = { phoneNumber: '<ALTERNATE_CALLER_ID>' };
const remoteParticipant = call.addParticipant(pstnIdentifier, { alternateCallerId });
Удаление участника из вызова
Чтобы удалить участника (пользователя или номер телефона) из вызова, можно вызвать removeParticipant
. Необходимо передать один из типов Identifier
. Этот метод разрешается асинхронно после удаления участника из вызова. Этот же участник удаляется из коллекции remoteParticipants
.
const userIdentifier = { communicationUserId: '<ACS_USER_ID>' };
const pstnIdentifier = { phoneNumber: '<PHONE_NUMBER>' }
await call.removeParticipant(userIdentifier);
await call.removeParticipant(pstnIdentifier);
Получение доступа к свойствам удаленного участника
С удаленными участниками связаны наборы свойств и коллекций:
CommunicationIdentifier
: получение идентификатора для удаленного участника. Идентификатор имеет один из типовCommunicationIdentifier
:
const identifier = remoteParticipant.identifier;
Может иметь один из следующих типов
CommunicationIdentifier
.{ communicationUserId: '<ACS_USER_ID'> }
: объект, представляющий пользователя Службы коммуникации Azure.{ phoneNumber: '<E.164>' }
: объект, представляющий номер телефона в формате E.164.{ microsoftTeamsUserId: '<TEAMS_USER_ID>', isAnonymous?: boolean; cloud?: "public" | "dod" | "gcch" }
: объект, представляющий пользователя Teams.{ id: string }
: объект, представляющий идентификатор, который не соответствует ни одному из других типов идентификаторов.
state
: получение состояния удаленного участника.
const state = remoteParticipant.state;
Состояние может иметь одно из следующих значений.
Idle
: начальное состояние.Connecting
: переходное состояние во время подключения участника к вызову.Ringing
: для участника звучит сигнал вызова.Connected
: участник подключен к вызову.Hold
: участник находится в режиме ожидания.EarlyMedia
: объявление, которое воспроизводится перед подключением участника к вызову.InLobby
: указывает, что удаленный участник находится в зале ожидания.Disconnected
: конечное состояние. Обозначает завершение вызова для участника. Если у удаленного участника пропадает подключение к сети, через две минуты его состояние меняется наDisconnected
.
callEndReason
: чтобы узнать, почему участник покинул вызов, проверьте свойствоcallEndReason
.const callEndReason = remoteParticipant.callEndReason; const callEndReasonCode = callEndReason.code // (number) code associated with the reason const callEndReasonSubCode = callEndReason.subCode // (number) subCode associated with the reason
Примечание.
- Это свойство задается только при добавлении удаленного участника через API Call.addParticipant(), а удаленный участник отклоняется, например.
- В сценарии, когда UserB запускает UserC, с точки зрения UserA, UserA не видит этот флаг, установленный для UserC. Другими словами, UserA не отображает свойство UserC callEndReason вообще.
Состояние
isMuted
: чтобы узнать, отключен ли звук у удаленного участника, проверьте свойствоisMuted
. Он возвращаетBoolean
.const isMuted = remoteParticipant.isMuted;
Состояние
isSpeaking
: чтобы узнать, говорит ли удаленный участник, проверьте свойствоisSpeaking
. Он возвращаетBoolean
.const isSpeaking = remoteParticipant.isSpeaking;
videoStreams
: чтобы проверить все видеопотоки, отправляемые определенным участником в вызове, проверьте коллекциюvideoStreams
. Она содержит объектыRemoteVideoStream
.const videoStreams = remoteParticipant.videoStreams; // [RemoteVideoStream, ...]
displayName
: чтобы получить отображаемое имя для этого удаленного участника, проверьте свойствоdisplayName
в возвращенной строке.const displayName = remoteParticipant.displayName;
endpointDetails
: получение сведений обо всех конечных точках для этого удаленного участникаconst endpointDetails: EndpointDetails[] = remoteParticipant.endpointDetails;
Примечание. Удаленный участник может находиться в вызове из многих конечных точек, и каждая конечная точка имеет свой собственный уникальный
participantId
.participantId
отличается от необработанного идентификатора RemoteParticipant.identifier.
Отключение звука других участников
Примечание.
Чтобы использовать этот API, используйте Службы коммуникации Azure вызов веб-пакета SDK версии 1.26.1 или более поздней.
Чтобы отключить звук всех остальных участников или отключить определенный участник, подключенный к вызову, можно использовать асинхронные API muteAllRemoteParticipants
для вызова и mute
удаленного участника. Событие mutedByOthers
из вызова возникает, когда локальный участник был отключен другими пользователями.
Примечание. Сценарии отключения ТСОП (номер телефона) участников или участников звонка 1:1 не поддерживаются.
//mute all participants except yourself
await call.muteAllRemoteParticipants();
//mute a specific participant
await call.remoteParticipants[0].mute();
Проверка свойств вызова
Получите уникальный идентификатор (в строковом формате) вызова:
const callId: string = call.id;
Получите идентификатор локального участника:
const participantId: string = call.info.participantId;
Примечание. Удостоверение Службы коммуникации Azure может использовать пакет SDK для веб-вызовов во многих конечных точках, и каждая конечная точка имеет свой собственный уникальныйparticipantId
. participantId
отличается от необработанного идентификатора Службы коммуникации Azure удостоверения.
Получите идентификатор потока при присоединении к собранию Teams:
const threadId: string | undefined = call.info.threadId;
Получение сведений о вызове:
const callInfo = call.info;
Чтобы получить данные о других участниках вызова, просмотрите коллекцию remoteParticipants
в экземпляре Call:
const remoteParticipants = call.remoteParticipants;
Идентифицируйте вызывающего для входящего вызова:
const callerIdentity = call.callerInfo.identifier;
identifier
имеет один из типов CommunicationIdentifier
.
Получите состояние вызова:
const callState = call.state;
Возвращает строку, которая представляет текущее состояние вызова:
None
: исходное состояние любого вызова;Connecting
: исходное переходное состояние после осуществления или приема вызова;Ringing
: для исходящего вызова означает, что на стороне удаленных участников звучит сигнал вызова. На их стороне этоIncoming
;EarlyMedia
: обозначает состояние, при котором перед вызовом воспроизводится объявление;Connected
: указывает, что вызов осуществлен;LocalHold
: указывает, что локальный участник вызова помещает вызов на удержание. Передача мультимедиа между локальной конечной точкой и удаленными участниками не выполняется;RemoteHold
: указывает, что удаленный участник вызова помещает вызов в удержание. Передача мультимедиа между локальной конечной точкой и удаленными участниками не выполняется;InLobby
: указывает, что пользователь находится в зале ожидания.Disconnecting
: переходное состояние перед переходом вызова в состояниеDisconnected
;Disconnected
: конечное состояние вызова. При потере сетевого подключения состояние меняется наDisconnected
через две минуты.
Выясните причину завершения вызова путем изучения свойства callEndReason
:
const callEndReason = call.callEndReason;
const callEndReasonMessage = callEndReason.message // (string) user friendly message
const callEndReasonCode = callEndReason.code // (number) code associated with the reason
const callEndReasonSubCode = callEndReason.subCode // (number) subCode associated with the reason
Чтобы выяснить, является ли текущий вызов входящим или исходящим, проверьте свойство direction
. Он возвращает CallDirection
.
const isIncoming = call.direction == 'Incoming';
const isOutgoing = call.direction == 'Outgoing';
Проверьте активные видеопотоки и активные потоки общего доступа к экранам, проверив коллекцию localVideoStreams
. localVideoStreams
API возвращает LocalVideoStream
объекты типа Video
, ScreenSharing
или RawMedia
.
const localVideoStreams = call.localVideoStreams;
Проверьте, отключен ли текущий микрофон. Он возвращает Boolean
.
const muted = call.isMuted;
Проверьте, отключен ли текущий входящий звук (динамик). Он возвращает Boolean
.
const incomingAudioMuted = call.isIncomingAudioMuted;
Проверьте, включен ли видео. Он возвращает Boolean
.
const isLocalVideoStarted = call.isLocalVideoStarted;
Проверьте, включен общий доступ к экрану. Он возвращает Boolean
.
const isScreenSharingOn = call.isScreenSharingOn;
Установка пакета 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();
Осуществление вызовов
Чтобы создать и начать вызов, необходимо вызвать метод CallAgent.startCall()
и предоставить Identifier
вызываемой стороны.
Чтобы присоединиться к групповому вызову, нужно вызвать метод CallAgent.join()
и предоставить значение groupId. Идентификаторы групп должны иметь формат GUID или UUID.
Операции создания и начала вызовов выполняются синхронно. Экземпляр вызова позволяет подписываться на все события в вызове.
Осуществление персонального вызова к пользователю
Чтобы осуществить вызов к другому пользователю Служб коммуникации, вызовите метод call
для callAgent
и передайте в нем объект с ключом communicationUserId
.
StartCallOptions startCallOptions = new StartCallOptions();
Context appContext = this.getApplicationContext();
CommunicationUserIdentifier acsUserId = new CommunicationUserIdentifier(<USER_ID>);
CommunicationUserIdentifier participants[] = new CommunicationUserIdentifier[]{ acsUserId };
call oneToOneCall = callAgent.startCall(appContext, participants, startCallOptions);
Осуществление группового вызова к пользователям и ТСОП
Примечание.
Ознакомьтесь с подробными сведениями о предложении звонков по ТСОП. Для доступа к программе предварительной версии применяется к программе раннего внедрения.
Чтобы осуществить групповой вызов к пользователю и номеру ТСОП, необходимо указать номер телефона вызываемой стороны. Для осуществления вызовов к ТСОП необходимо настроить ресурс Служб коммуникации.
CommunicationUserIdentifier acsUser1 = new CommunicationUserIdentifier(<USER_ID>);
PhoneNumberIdentifier acsUser2 = new PhoneNumberIdentifier("<PHONE_NUMBER>");
CommunicationIdentifier participants[] = new CommunicationIdentifier[]{ acsUser1, acsUser2 };
StartCallOptions startCallOptions = new StartCallOptions();
Context appContext = this.getApplicationContext();
Call groupCall = callAgent.startCall(participants, startCallOptions);
Прием вызова
Чтобы принять вызов, вызовите метод accept для объекта вызова.
Context appContext = this.getApplicationContext();
IncomingCall incomingCall = retrieveIncomingCall();
Call call = incomingCall.accept(context).get();
Чтобы принять вызов с включенной видеокамерой, сделайте следующее:
Context appContext = this.getApplicationContext();
IncomingCall incomingCall = retrieveIncomingCall();
AcceptCallOptions acceptCallOptions = new AcceptCallOptions();
VideoDeviceInfo desiredCamera = callClient.getDeviceManager().get().getCameraList().get(0);
acceptCallOptions.setVideoOptions(new VideoOptions(new LocalVideoStream(desiredCamera, appContext)));
Call call = incomingCall.accept(context, acceptCallOptions).get();
Чтобы получить входящий вызов, следует подписаться на событие onIncomingCall
в объекте callAgent
:
// Assuming "callAgent" is an instance property obtained by calling the 'createCallAgent' method on CallClient instance
public Call retrieveIncomingCall() {
IncomingCall incomingCall;
callAgent.addOnIncomingCallListener(new IncomingCallListener() {
void onIncomingCall(IncomingCall inboundCall) {
// Look for incoming call
incomingCall = inboundCall;
}
});
return incomingCall;
}
Присоединение к вызову комнаты
CallAgent
Используйте и RoomCallLocator
присоединитесь к вызову комнаты, указав номерroomId
. Метод CallAgent.join
вернет Call
объект:
val roomCallLocator = RoomCallLocator(roomId)
call = callAgent.join(applicationContext, roomCallLocator, joinCallOptions)
Разработчики room
приложений лучше управляют тем, кто может присоединиться к вызову, когда они встречаются и как они сотрудничают. Дополнительные сведения см rooms
. в концептуальной документации или кратком руководстве по началу работы.
Присоединение к групповому вызову
Чтобы начать новый групповой вызов или присоединиться к текущему групповому вызову, необходимо вызвать метод "join" и передать ему объект со свойством groupId
. В качестве значения должен быть указан идентификатор GUID.
Context appContext = this.getApplicationContext();
GroupCallLocator groupCallLocator = new GroupCallLocator("<GUID>");
JoinCallOptions joinCallOptions = new JoinCallOptions();
call = callAgent.join(context, groupCallLocator, joinCallOptions);
Свойства вызова
Получите уникальный идентификатор для вызова:
String callId = call.getId();
Чтобы получить данные о других участниках вызова, просмотрите коллекцию remoteParticipant
для экземпляра call
:
List<RemoteParticipant> remoteParticipants = call.getRemoteParticipants();
Для входящих вызовов это идентификатор вызывающей стороны:
CommunicationIdentifier callerId = call.getCallerInfo().getIdentifier();
Получите состояние вызова:
CallState callState = call.getState();
Возвращается строка, которая представляет текущее состояние вызова:
- NONE — исходное состояние любого вызова;
- EARLY_MEDIA — обозначает состояние, при котором перед вызовом воспроизводится объявление;
- CONNECTING — исходное переходное состояние после осуществления или приема вызова;
- RINGING — для исходящего вызова означает, что на стороне удаленных участников звучит сигнал вызова;
- CONNECTED — вызов осуществлен;
- LOCAL_HOLD — вызов переведен локальным участником в режим ожидания, и потоки мультимедиа не передаются между локальной конечной точкой и удаленными участниками;
- REMOTE_HOLD — вызов переведен удаленным участником в режим ожидания, и потоки мультимедиа не передаются между локальной конечной точкой и удаленными участниками;
- DISCONNECTING — переходное состояние перед тем, как вызов перейдет в состояние DISCONNECTED;
- DISCONNECTED — завершающее состояние вызова.
- IN_LOBBY — в зале ожидания для взаимодействия конференций Teams.
Чтобы узнать, почему вызов завершился, проверьте свойство callEndReason
. Оно содержит основной код и дополнительный код:
CallEndReason callEndReason = call.getCallEndReason();
int code = callEndReason.getCode();
int subCode = callEndReason.getSubCode();
Чтобы узнать, является ли текущий вызов входящим или исходящим, проверьте свойство callDirection
:
CallDirection callDirection = call.getCallDirection();
// callDirection == CallDirection.INCOMING for incoming call
// callDirection == CallDirection.OUTGOING for outgoing call
Чтобы узнать, отключен ли выбранный микрофон, проверьте свойство muted
:
boolean muted = call.isMuted();
Чтобы проверить активные видеопотоки, проверьте коллекцию localVideoStreams
:
List<LocalVideoStream> localVideoStreams = call.getLocalVideoStreams();
Отключить звук и включить звук
Чтобы отключить или включить звук для локальной конечной точки, можно использовать асинхронные вызовы API mute
и unmute
:
Context appContext = this.getApplicationContext();
call.mute(appContext).get();
call.unmute(appContext).get();
Изменение объема вызова
Находясь в вызове, аппаратные ключи регулировки громкости на телефоне должны позволить пользователю изменить громкость вызова.
Это осуществляется с помощью метода setVolumeControlStream
с типом потока AudioManager.STREAM_VOICE_CALL
для действия, куда помещается вызов.
Это позволяет аппаратным ключам регулировки громкости изменить громкость вызова (обозначенную значком телефонной трубки или другим, аналогичным ползунком громкости), предотвращая изменение громкости для других профилей, таких как громкость оповещений, мультимедиа или системных звуков. Дополнительные сведения см. в статье Обработка изменений в выводе аудио | Разработчикам Android.
@Override
protected void onCreate(Bundle savedInstanceState) {
...
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
}
Управление удаленными участниками
Все удаленные участники представлены типом RemoteParticipant
и доступны через коллекцию remoteParticipants
в экземпляре вызова.
Вывод списка участников в вызове
Коллекция remoteParticipants
возвращает список удаленных участников в указанном вызове:
List<RemoteParticipant> remoteParticipants = call.getRemoteParticipants(); // [remoteParticipant, remoteParticipant....]
Добавление участника в вызов
Чтобы добавить в вызов участника (пользователя или номер телефона), можно вызвать addParticipant
.
Этот вызов в синхронном режиме возвращает экземпляр удаленного участника.
const acsUser = new CommunicationUserIdentifier("<acs user id>");
const acsPhone = new PhoneNumberIdentifier("<phone number>");
RemoteParticipant remoteParticipant1 = call.addParticipant(acsUser);
AddPhoneNumberOptions addPhoneNumberOptions = new AddPhoneNumberOptions(new PhoneNumberIdentifier("<alternate phone number>"));
RemoteParticipant remoteParticipant2 = call.addParticipant(acsPhone, addPhoneNumberOptions);
Удаление участника из вызова
Чтобы удалить участника (пользователя или номер телефона) из вызова, можно вызвать removeParticipant
.
Это значение будет разрешаться асинхронно после удаления участника из вызова.
Этот же участник будет удален из коллекции remoteParticipants
.
RemoteParticipant acsUserRemoteParticipant = call.getParticipants().get(0);
RemoteParticipant acsPhoneRemoteParticipant = call.getParticipants().get(1);
call.removeParticipant(acsUserRemoteParticipant).get();
call.removeParticipant(acsPhoneRemoteParticipant).get();
Свойства удаленного участника
С каждым конкретным удаленным участником связан набор свойств и коллекций:
Получите идентификатор для этого удаленного участника. Идентификатор имеет один из типов Identifier.
CommunicationIdentifier participantIdentifier = remoteParticipant.getIdentifier();
Получите состояние удаленного участника.
ParticipantState state = remoteParticipant.getState();
Состояние может иметь одно из следующих значений:
IDLE — исходное состояние;
EARLY_MEDIA — перед подключением к вызову для участника воспроизводится объявление;
RINGING — для участника звучит сигнал вызова;
CONNECTING — переходное состояние во время подключения участника к вызову;
CONNECTED — участник подключен к вызову;
HOLD — участник находится в режиме ожидания;
IN_LOBBY — участник ожидает допуска в зале ожидания. (в настоящее время используется только в сценарии взаимодействия с Teams);
DISCONNECTED — окончательное состояние, которое обозначает завершение вызова для участника.
Чтобы узнать, почему участник покинул вызов, проверьте свойство
callEndReason
:CallEndReason callEndReason = remoteParticipant.getCallEndReason();
Чтобы проверить, отключен ли звук для удаленного участника, проверьте свойство
isMuted
:boolean isParticipantMuted = remoteParticipant.isMuted();
Чтобы проверить, говорит ли сейчас удаленный участник, проверьте свойство
isSpeaking
:boolean isParticipantSpeaking = remoteParticipant.isSpeaking();
Чтобы проверить все видеопотоки, отправляемые определенным участником в вызове, проверьте коллекцию
videoStreams
:List<RemoteVideoStream> videoStreams = remoteParticipant.getVideoStreams(); // [RemoteVideoStream, RemoteVideoStream, ...]
Отключение звука других участников
Примечание.
Чтобы использовать этот API, используйте Службы коммуникации Azure вызов пакета SDK для Android версии 2.11.0 или более поздней.
Чтобы отключить звук всех остальных участников вызова, используйте muteAllRemoteParticipants
API для вызова.
call.muteAllRemoteParticipants();
Чтобы отключить отдельный удаленный участник, используйте mute
API для данного удаленного участника.
remoteParticipant.mute();
Чтобы уведомить локального участника о том, что они были отключены другими пользователями, подпишитесь на onMutedByOthers
событие.
Использование служб переднего плана
В случаях, когда вы хотите запустить пользователь видимую задачу, даже если приложение находится в фоновом режиме, можно использовать службы Foreground.
Например, используя службы Foreground, вы можете сохранить отображаемое пользователем уведомление при активном вызове приложения. Таким образом, даже если пользователь переходит на домашний экран или удаляет приложение из последнего экрана, вызов будет продолжать активно.
Если вы не используете службу переднего плана во время вызова, переход к домашнему экрану может поддерживать активный вызов, но удаление приложения с экрана последних может остановить вызов, если ОС Android убьет процесс приложения.
При запуске или присоединении к вызову необходимо запустить службу переднего плана, например:
call = callAgent.startCall(context, participants, options);
startService(yourForegroundServiceIntent);
И остановите службу переднего плана при зависание вызова или состояние вызова отключено, например:
call.hangUp(new HangUpOptions()).get();
stopService(yourForegroundServiceIntent);
Заметки об использовании служб Foreground
Имейте в виду, что такие сценарии, как остановка уже запущенной службы переднего плана при удалении приложения из списка последних, удалят видимое уведомление пользователя, и ОС Android может поддерживать процесс приложения в течение некоторого дополнительного периода времени, что означает, что вызов все еще может быть активным в течение этого периода.
Если приложение останавливает службу переднего плана в методе службы onTaskRemoved
, например, приложение может запускать и останавливать аудио и видео в соответствии с жизненным циклом действий, например остановкой звука и видео при уничтожении действия с onDestroy
помощью переопределения метода.
Настройка системы
Выполните следующие действия, чтобы настроить систему.
Создайте проект 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")
}
})
Примечание.
Для реализации делегатов событий приложением требуется, чтобы оно содержало строгую ссылку на объекты, которым требуются подписки на события. Например, если объект RemoteParticipant
возвращается при вызове метода call.addParticipant
, а приложение настраивает делегата для прослушивания RemoteParticipantDelegate
, приложение должно содержать строгую ссылку на объект RemoteParticipant
. В противном случае делегат выдаст неустранимое исключение при запросе этого объекта вызывающим пакетом SDK, если объект уже был удален обработчиком мусора.
Осуществление исходящего вызова
Чтобы создать и начать вызов, необходимо вызвать одну из API для объекта CallAgent
и предоставить в вызове удостоверение Служб коммуникации того пользователя, которое вы ранее подготовили к работе с помощью пакета SDK управления Службами коммуникации.
Операции создания и начала вызовов выполняются синхронно. Вы получите экземпляр вызова, который позволяет подписываться на все события в этом вызове.
Осуществление персонального вызова к пользователю или группового вызова к пользователям и ТСОП
let callees = [CommunicationUser(identifier: 'UserId')]
self.callAgent?.startCall(participants: callees, options: StartCallOptions()) { (call, error) in
if error == nil {
print("Successfully started outgoing call")
self.call = call
} else {
print("Failed to start outgoing call")
}
}
Осуществление группового вызова к пользователям и ТСОП
Примечание.
Ознакомьтесь с подробными сведениями о предложении звонков по ТСОП. Для доступа к программе предварительной версии применяется к программе раннего внедрения.
Чтобы создать вызов к ТСОП, необходимо указать номер телефона, полученный от Служб коммуникации.
let pstnCallee = PhoneNumberIdentifier(phoneNumber: '+1999999999')
let callee = CommunicationUserIdentifier('UserId')
self.callAgent?.startCall(participants: [pstnCallee, callee], options: StartCallOptions()) { (groupCall, error) in
if error == nil {
print("Successfully started outgoing call to multiple participants")
self.call = groupCall
} else {
print("Failed to start outgoing call to multiple participants")
}
}
Присоединение к вызову комнаты
Чтобы присоединиться к вызову room
, укажите roomId
свойство в качестве идентификатора room
. Чтобы присоединиться к вызову join
, используйте метод и передайте метод roomCallLocator
.
func joinRoomCall() {
if self.callAgent == nil {
print("CallAgent not initialized")
return
}
if (self.roomId.isEmpty) {
print("Room ID not set")
return
}
// Join a call with a Room ID
let options = JoinCallOptions()
let audioOptions = AudioOptions()
audioOptions.muted = self.muted
options.audioOptions = audioOptions
let roomCallLocator = RoomCallLocator(roomId: roomId)
self.callAgent!.join(with: roomCallLocator, joinCallOptions: options) { (call, error) in
self.setCallAndObserver(call: call, error: error)
}
}
Разработчики room
приложений лучше управляют тем, кто может присоединиться к вызову, когда они встречаются и как они сотрудничают. Дополнительные сведения см rooms
. в концептуальной документации или кратком руководстве по началу работы.
Присоединение к групповому вызову
Чтобы присоединиться к вызову, необходимо вызвать одну из API для объекта CallAgent
.
let groupCallLocator = GroupCallLocator(groupId: UUID(uuidString: "uuid_string")!)
self.callAgent?.join(with: groupCallLocator, joinCallOptions: JoinCallOptions()) { (call, error) in
if error == nil {
print("Successfully joined group call")
self.call = call
} else {
print("Failed to join group call")
}
}
Подписка на входящий вызов
Подписка на событие входящего вызова.
final class IncomingCallHandler: NSObject, CallAgentDelegate, IncomingCallDelegate
{
// Event raised when there is an incoming call
public func callAgent(_ callAgent: CallAgent, didReceiveIncomingCall incomingcall: IncomingCall) {
self.incomingCall = incomingcall
// Subscribe to get OnCallEnded event
self.incomingCall?.delegate = self
}
// Event raised when incoming call was not answered
public func incomingCall(_ incomingCall: IncomingCall, didEnd args: PropertyChangedEventArgs) {
print("Incoming call was not answered")
self.incomingCall = nil
}
}
Прием входящего вызова
Чтобы принять вызов, вызовите метод accept
для объекта IncomingCall
.
self.incomingCall!.accept(options: AcceptCallOptions()) { (call, error) in
if (error == nil) {
print("Successfully accepted incoming call")
self.call = call
} else {
print("Failed to accept incoming call")
}
}
let firstCamera: VideoDeviceInfo? = self.deviceManager!.cameras.first
localVideoStreams = [LocalVideoStream]()
localVideoStreams!.append(LocalVideoStream(camera: firstCamera!))
let acceptCallOptions = AcceptCallOptions()
acceptCallOptions.videoOptions = VideoOptions(localVideoStreams: localVideoStreams!)
if let incomingCall = self.incomingCall {
incomingCall.accept(options: acceptCallOptions) { (call, error) in
if error == nil {
print("Incoming call accepted")
} else {
print("Failed to accept incoming call")
}
}
} else {
print("No incoming call found to accept")
}
Выполнение операций в процессе вызова
Во время вызова вы можете выполнять различные операции для управления параметрами видео и аудио.
Отключить звук и включить звук
Чтобы отключить или включить звук для локальной конечной точки, можно использовать асинхронные вызовы API mute
и unmute
.
call!.mute { (error) in
if error == nil {
print("Successfully muted")
} else {
print("Failed to mute")
}
}
Используйте следующий код для асинхронного отключения локальной конечной точки.
call!.unmute { (error) in
if error == nil {
print("Successfully un-muted")
} else {
print("Failed to unmute")
}
}
Управление удаленными участниками
Все удаленные участники представлены типом RemoteParticipant
и доступны через коллекцию remoteParticipants
в экземпляре вызова.
Вывод списка участников в вызове
call.remoteParticipants
Добавление участника в вызов
Чтобы добавить в вызов участника (пользователя или номер телефона), можно вызвать addParticipant
. Вызов этой команды возвращает в синхронном режиме экземпляр удаленного участника.
let remoteParticipantAdded: RemoteParticipant = call.add(participant: CommunicationUserIdentifier(identifier: "userId"))
Удаление участника из вызова
Чтобы удалить участника (пользователя или номер телефона) из вызова, можно воспользоваться вызовом API removeParticipant
. Разрешение выполняется асинхронно.
call!.remove(participant: remoteParticipantAdded) { (error) in
if (error == nil) {
print("Successfully removed participant")
} else {
print("Failed to remove participant")
}
}
Получение свойств удаленного участника
// [RemoteParticipantDelegate] delegate - an object you provide to receive events from this RemoteParticipant instance
var remoteParticipantDelegate = remoteParticipant.delegate
// [CommunicationIdentifier] identity - same as the one used to provision a token for another user
var identity = remoteParticipant.identifier
// ParticipantStateIdle = 0, ParticipantStateEarlyMedia = 1, ParticipantStateConnecting = 2, ParticipantStateConnected = 3, ParticipantStateOnHold = 4, ParticipantStateInLobby = 5, ParticipantStateDisconnected = 6
var state = remoteParticipant.state
// [Error] callEndReason - reason why participant left the call, contains code/subcode/message
var callEndReason = remoteParticipant.callEndReason
// [Bool] isMuted - indicating if participant is muted
var isMuted = remoteParticipant.isMuted
// [Bool] isSpeaking - indicating if participant is currently speaking
var isSpeaking = remoteParticipant.isSpeaking
// RemoteVideoStream[] - collection of video streams this participants has
var videoStreams = remoteParticipant.videoStreams // [RemoteVideoStream, RemoteVideoStream, ...]
Отключение звука других участников
Примечание.
Чтобы использовать этот API, используйте Службы коммуникации Azure пакет SDK для iOS версии 2.13.0 или более поздней версии.
Чтобы отключить звук всех остальных участников вызова, используйте muteAllRemoteParticipants
API для вызова.
call!.muteAllRemoteParticipants { (error) in
if error == nil {
print("Successfully muted all remote participants.")
} else {
print("Failed to mute remote participants.")
}
}
Чтобы отключить отдельный удаленный участник, используйте mute
API для данного удаленного участника.
remoteParticipant.mute { (error) in
if error == nil {
print("Successfully muted participant.")
} else {
print("Failed to mute participant.")
}
}
Чтобы уведомить локального участника о том, что они были отключены другими пользователями, подпишитесь на onMutedByOthers
событие.
Настройка системы
Выполните следующие действия, чтобы настроить систему.
Создание проекта Visual Studio
Для приложения универсальная платформа Windows в Visual Studio 2022 создайте проект пустого приложения (универсального приложения Windows). После ввода имени проекта вы можете выбрать любой пакет SDK для Windows позже 10.0.17763.0.
Для приложения WinUI 3 создайте проект с шаблоном "Пустое приложение" (WinUI 3 в классическом приложении) для настройки одностраничного приложения WinUI 3. Требуется пакет SDK для приложений Windows версии 1.3 или более поздней.
Установка пакета и зависимостей с помощью NuGet диспетчер пакетов
Api и библиотеки пакета SDK для вызовов общедоступны через пакет NuGet.
Чтобы найти, скачать и установить пакет NuGet пакета Sdk для вызовов:
- Откройте nuGet диспетчер пакетов, выбрав инструменты>NuGet диспетчер пакетов> Manage NuGet Packages for Solution.
- Выберите "Обзор" и введите Azure.Communication.Calling.WindowsClient в поле поиска.
- Убедитесь, что установлен флажок "Включить предварительную версию ".
- Выберите пакет Azure.Communication.Calling.WindowsClient, а затем выберите Azure.Communication.Calling.WindowsClient 1.4.0-beta.1 или более позднюю версию.
- Установите флажок, соответствующий проекту Службы коммуникации Azure на правой панели.
- Выберите Установить.
Запрос доступа к микрофону
Приложению требуется доступ к микрофону для правильного выполнения. В приложениях UWP возможность использования микрофона должна быть объявлена в файле манифеста приложения.
В следующих шагах показано, как это сделать.
- На панели
Solution Explorer
дважды щелкните файл с расширением.appxmanifest
. - Щелкните вкладку
Capabilities
. - Установите флажок
Microphone
в списке возможностей.
Создание кнопок пользовательского интерфейса для совершения и завершения вызова
Это простое пример приложения содержит две кнопки. одну для выполнения вызова, а другую для его завершения. Следующие шаги демонстрируют, как добавить такие кнопки в приложение.
Solution Explorer
На панели дважды щелкните файл с именемMainPage.xaml
UWP илиMainWindows.xaml
WinUI 3.- На центральной панели найдите код XAML в предварительной версии пользовательского интерфейса.
- Измените код XAML следующим фрагментом:
<TextBox x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" />
<StackPanel>
<Button x:Name="CallButton" Content="Start/Join call" Click="CallButton_Click" />
<Button x:Name="HangupButton" Content="Hang up" Click="HangupButton_Click" />
</StackPanel>
Настройка приложения с помощью API пакета SDK для вызовов
API пакета SDK для вызовов находятся в двух разных пространствах имен. С помощью следующих шагов можно сообщить компилятору C# об этих пространствах имен, что позволяет IntelliSense в Visual Studio упростить разработку кода.
Solution Explorer
На панели щелкните стрелку в левой части файла с именемMainPage.xaml
UWP илиMainWindows.xaml
WinUI 3.- Дважды щелкните файл с именем
MainPage.xaml.cs
илиMainWindows.xaml.cs
. - Добавьте следующие команды в конце текущих инструкций
using
.
using Azure.Communication.Calling.WindowsClient;
Сохранение MainPage.xaml.cs
или MainWindows.xaml.cs
открытие. Вы добавите в него дополнительный код с помощью последующих действий.
Разрешение взаимодействий с приложением
Добавленные ранее кнопки пользовательского интерфейса должны работать на основе размещенного вызова (CommunicationCall
). Это означает, что CommunicationCall
член данных должен быть добавлен в MainPage
класс или MainWindow
класс.
Кроме того, чтобы обеспечить успешное выполнение асинхронной операции для создания CallAgent
, элемент данных CallAgent
также необходимо добавить в тот же класс.
Добавьте в класс pr MainWindow
следующие элементы MainPage
данных:
CallAgent callAgent;
CommunicationCall call;
Создание обработчиков кнопок
Ранее в код XAML были добавлены две кнопки пользовательского интерфейса. Следующий код добавляет обработчики, которые будут выполняться при нажатии кнопки. Следующий код нужно добавить после элементов данных из предыдущего раздела.
private async void CallButton_Click(object sender, RoutedEventArgs e)
{
// Start call
}
private async void HangupButton_Click(object sender, RoutedEventArgs e)
{
// End the current call
}
Объектная модель
Следующие классы и интерфейсы реализуют некоторые основные функции клиентской библиотеки вызовов в Службах коммуникации Azure для UWP:
Имя | Описание |
---|---|
CallClient |
Это CallClient основная точка входа в клиентную библиотеку вызовов. |
CallAgent |
Используется CallAgent для запуска и присоединения вызовов. |
CommunicationCall |
Используется CommunicationCall для управления размещенными или присоединенными вызовами. |
CommunicationTokenCredential |
Используется CommunicationTokenCredential в качестве учетных данных маркера для создания экземпляра CallAgent . |
CallAgentOptions |
Содержит CallAgentOptions сведения для идентификации вызывающего объекта. |
HangupOptions |
Сообщает HangupOptions , следует ли прервать звонок всем участникам. |
Инициализация CallAgent
Чтобы создать CallAgent
экземпляр, CallClient
необходимо использовать CallClient.CreateCallAgentAsync
метод, который асинхронно возвращает CallAgent
объект после инициализации.
Для создания CallAgent
необходимо передать объект CallTokenCredential
и объект CallAgentOptions
. Помните, что CallTokenCredential
выдает исключение при передаче неправильного маркера.
Следующий код должен быть добавлен внутри вспомогательной функции, которую необходимо вызвать в инициализации приложения.
var callClient = new CallClient();
this.deviceManager = await callClient.GetDeviceManagerAsync();
var tokenCredential = new CallTokenCredential("<AUTHENTICATION_TOKEN>");
var callAgentOptions = new CallAgentOptions()
{
DisplayName = "<DISPLAY_NAME>"
};
this.callAgent = await callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);
Измените <AUTHENTICATION_TOKEN>
допустимый маркер учетных данных для ресурса. Если вам необходимо получить маркер учетных данных, см. документацию по маркеру доступа пользователя.
Создание CallAgent и совершение вызова
Объекты, необходимые для создания CallAgent
, теперь готовы. Пришло время асинхронно создавать CallAgent
и размещать вызов.
Следующий код следует добавить после обработки исключения из предыдущего шага.
var startCallOptions = new StartCallOptions();
var callees = new [] { new UserCallIdentifier(CalleeTextBox.Text.Trim()) };
this.call = await this.callAgent.StartCallAsync(callees, startCallOptions);
this.call.OnStateChanged += Call_OnStateChangedAsync;
Вы можете поговорить 8:echo123
с Службы коммуникации Azure эхо-ботом.
Отключить звук и включить звук
Чтобы отключить или отменить исходящий звук, можно использовать MuteOutgoingAudioAsync
асинхронные UnmuteOutgoingAudioAsync
API:
// mute outgoing audio
await this.call.MuteOutgoingAudioAsync();
// unmute outgoing audio
await this.call.UnmuteOutgoingAudioAsync();
Отключение звука других участников
Примечание.
Чтобы использовать этот API, используйте Службы коммуникации Azure вызове пакета SDK для Windows версии 1.9.0 или более поздней.
Чтобы отключить звук всех остальных участников или отключить определенный участник, можно использовать асинхронные API MuteAllRemoteParticipantsAsync
для вызова и MuteAsync
удаленного участника:
// mute all participants except yourself
await this.call.MuteAllRemoteParticipantsAsync();
// mute specific participant in the call
await this.call.RemoteParticipants.FirstOrDefault().MuteAsync();
Чтобы уведомить локального участника о том, что они были отключены другими пользователями, подпишитесь на MutedByOthers
событие.
Завершение вызова
После совершения вызова используйте метод HangupAsync
объекта CommunicationCall
, чтобы завершить вызов.
Экземпляр HangupOptions
также следует использовать для сообщения всем участникам о необходимости завершения вызова.
Следующий код нужно добавить в HangupButton_Click
.
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions() { ForEveryone = false });
Выполнение кода
Убедитесь, что Visual Studio создает приложение для x64
, x86
или ARM64
нажмите, F5
чтобы запустить приложение. После этого нажмите кнопку Call
, чтобы совершить вызов к определенному вызываемому.
Помните, что при первом запуске приложения система предложит пользователю предоставить доступ к микрофону.