共用方式為


管理通話

了解如何使用 Azure 通訊服務 SDK 來管理通話。 我們將了解如何撥打電話,如何管理其參與者和屬性。

必要條件

安裝 SDK

使用 npm install 命令,安裝適用於 JavaScript 的 Azure 通訊服務通用和通話 SDK:

npm install @azure/communication-common --save
npm install @azure/communication-calling --save

初始化必要的物件

大部分通話作業都需要 CallClient 執行個體。 當您建立新的 CallClient 執行個體時,您可以使用自訂選項加以設定,如同 Logger 執行個體一樣。

使用 CallClient 執行個體,您可以藉由呼叫 createCallAgent 來建立 CallAgent 執行個體。 此方法會以非同步的方式傳回 CallAgent 執行個體物件。

createCallAgent 方法會使用 CommunicationTokenCredential 作為引數。 其接受使用者存取權杖

您可以使用 CallClient 執行個體上的 getDeviceManager 方法來存取 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()

如何最好地管理與 Microsoft 基礎結構的 SDK 連線

Call Agent 執行個體可協助您管理通話 (加入或啟動通話)。 若要運作,您的通話 SDK 必須連線到 Microsoft 基礎結構以取得來電通知,並協調其他通話詳細資料。 您的 Call Agent 有兩種可能的狀態:

已連線 - ConnectedCall Agent connectionStatue 值表示用戶端 SDK 已連線且能夠接收來自 Microsoft 基礎結構的通知。

已中斷連線 - Disconnected 狀態的 Call Agent connectionStatue 值指出有問題導致 SDK 無法正確連線。 Call Agent 應該重新建立。

  • invalidToken:如果權杖已過期或無效,Call Agent 執行個體會中斷連線,並出現此錯誤。
  • connectionIssue:如果用戶端連線到 Microsoft 基礎結構時發生問題,在多次重試之後,Call Agent 會公開 connectionIssue 錯誤。

您可以藉由檢查 connectionState 屬性的目前值,檢查本機 Call Agent 是否已連線到 Microsoft 基礎結構。 在作用中通話期間,您可以接聽 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);

撥打電話

若要建立並啟動通話,請在 callAgent 上使用其中一個 API,並提供您透過通訊服務識別 SDK 建立的使用者。

通話的建立和啟動是同步的。 call 執行個體可讓您訂閱通話事件。

對使用者或 PSTN 撥打 1:n 通話

若要打電話給另一個通訊服務使用者,請在 callAgent 上使用 startCall 方法,並傳遞您使用通訊服務管理程式庫建立的收件者 CommunicationUserIdentifier

若要撥打 1:1 通話給使用者,請使用下列程式碼:

const userCallee = { communicationUserId: '<ACS_USER_ID>' }
const oneToOneCall = callAgent.startCall([userCallee]);

若要對公用交換電話網路 (PSTN) 撥打電話,請在 callAgent 上使用 startCall 方法,並傳遞收件者的 PhoneNumberIdentifier。 您的通訊服務資源必須設定為允許 PSTN 通話。

撥打 PSTN 號碼時,請指定替代通話者識別碼。 替代通話者識別碼是用來識別 PSTN 通話者的電話號碼 (根據 E.164 標準)。 這是來電對受話方顯示的電話號碼。

注意

請參閱 PSTN 通話供應項目詳細資料。 若要存取預覽程式,請申請加入早期採用者計畫

若要對 PSTN 號碼撥打 1:1 通話,請使用下列程式碼:

const pstnCallee = { phoneNumber: '<ACS_USER_ID>' }
const alternateCallerId = {phoneNumber: '<ALTERNATE_CALLER_ID>'};
const oneToOneCall = callAgent.startCall([pstnCallee], { alternateCallerId });

若要對使用者和 PSTN 號碼撥打 1:n 通話,請使用下列程式碼:

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 參數會被視為系統中繼資料,且可由 Microsoft 用於執行系統所需的作業。 請勿在 groupId 值中包含個人資料。 Microsoft 不會將此參數視為個人資料,且其內容或許可由 Microsoft 員工檢視,或長期儲存。

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 執行個體。

如果相機在啟動、接聽或加入已啟用視訊的通話時無法使用,Azure 通訊通話 SDK 會觸發 cameraStartFailed: true 的呼叫診斷。 在此情況下,通話會以視訊關閉的狀態開始。 相機可能無法使用,因為其正由另一個程序使用,或在作業系統中遭停用。

保留和繼續通話

注意

在任何指定的時間點,應該只有 1 個作用中的通話 (處於 Connected 狀態,使用主動媒體)。 所有其他通話都應該由使用者保留,或依應用程式以程式設計方式進行。 這種情況常見於連絡中心等案例中,使用者可能需要處理多個連出和連入通話,所有非使用中的通話都應該保持保留,而且使用者應該只在作用中通話中與其他人互動

若要保留或繼續通話,您可以使用 holdresume 非同步 API:

若要保留通話

await call.hold();

hold API 解析時,呼叫狀態會設定為 LocalHold。 在 1:1 通話中,另一個參與者也會保留,而且從該參與者的角度來看,通話的狀態會設定為 'RemoteHold'。 之後,另一位參與者可能會將通話保留,這會導致狀態變更為 LocalHold。 在群組通話或會議中 - hold 是本機作業,不會保留其他通話參與者的通話。 若要繼續通話,所有啟動保留的使用者都必須恢復通話。

若要從保留繼續通話:

await call.resume();

resume API 解析時,呼叫狀態會再次設定為 Connected

將通話靜音和取消靜音

若要將本機端點設為靜音或取消靜音,您可以使用 muteunmute 非同步 API:

//mute local device (microphone / sent audio)
await call.mute();

//unmute local device (microphone / sent audio)
await call.unmute();

將傳入的音訊設為靜音或取消靜音

傳入的音訊靜音時,通話音量會設定為 0。 若要將傳入的音訊設為靜音或取消靜音,您可以使用 muteIncomingAudiounmuteIncomingAudio 非同步 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
    

    注意:

    • 只有在透過 Call.addParticipant() API 新增遠端參與者,而遠端參與者拒絕時,才會設定此屬性。
    • 假設 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;
    

    注意:遠端參與者可能會從多個端點參加通話,而每個端點都有其唯一的 participantIdparticipantId 與 RemoteParticipant.identifier 的原始識別碼不同。

將其他參與者設為靜音

注意

若要使用此 API,請使用 Azure 通訊服務通話 Web SDK 1.26.1 版或更高版本。

若要將所有其他參與者靜音或將通話所連線的特定參與者設為靜音,您可以對通話使用非同步 API muteAllRemoteParticipants,和對遠端參與者使用 mute: 當本機參與者已遭其他人靜音時,就會觸發來自通話的 mutedByOthers 事件。

注意:不支援將 PSTN (電話號碼) 參與者或 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 通訊服務身分識別可以在許多端點中使用 Web 通話 SDK,而且每個端點都有自己的唯一 participantIdparticipantId 與 Azure 通訊服務身分識別原始識別碼不同。

如果加入 Teams 會議,請擷取執行緒識別碼:

const threadId: string | undefined = call.info.threadId;

取得通話的相關資訊:

const callInfo = call.info;

檢查「通話」執行個體上的 remoteParticipants 集合,藉以了解通話中的其他參與者:

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 會傳回 VideoScreenSharingRawMedia 類型的 LocalVideoStream 物件。

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() 新增至 buildscriptallprojects 下的存放庫清單:

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

然後,在您的模組層級 build.gradle 檔案中,將以下幾行新增至 dependencies 區段:

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

初始化必要的物件

若要建立 CallAgent 執行個體,您必須在 CallClient 執行個體上呼叫 createCallAgent 方法。 此呼叫會以非同步方式傳回 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 格式。

通話的建立和啟動是同步的。 通話執行個體可讓您訂閱通話的所有事件。

對使用者撥打 1:1 通話

若要撥打電話給另一個通訊服務使用者,請在 callAgent 上叫用 call 方法,並傳遞具有 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);

對使用者和 PSTN 撥打 1:n 通話

注意

請參閱 PSTN 通話供應項目詳細資料。 若要存取預覽程式,請申請加入早期採用者計畫

若要對使用者和 PSTN 號碼撥打 1:n 通話,您必須指定受話方的電話號碼。 您的通訊服務資源必須設定為允許 PSTN 通話:

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

藉由訂閱 callAgent 物件的 onIncomingCall 事件,即可取得來電:

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

加入會議室通話

藉由指定 roomId,使用 CallAgentRoomCallLocator 加入會議室通話。 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();

若要了解通話中的其他參與者,請檢查 call 執行個體上的 remoteParticipant 集合:

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' - 最終通話狀態
  • '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();

靜音和取消靜音

若要將本機端點設為靜音或取消靜音,您可以使用 muteunmute 非同步 API:

Context appContext = this.getApplicationContext();
call.mute(appContext).get();
call.unmute(appContext).get();

變更通話的音量

在通話期間,手機上的硬體音量鍵應允許使用者變更通話音量。 具體做法是在撥打電話的活動上,使用具有串流類型 AudioManager.STREAM_VOICE_CALL 的方法 setVolumeControlStream。 這會允許硬體音量鍵變更電話音量 (以電話圖示或音量滑桿上的類似項目表示),並防止變更其他聲音設定檔的音量,例如鬧鈴、媒體或全系統的音量。 如需詳細資訊,您可以查看處理音訊輸出中的變更 | 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();

遠端參與者屬性

任何給定的遠端參與者都有一組相關聯的屬性和集合:

  • 取得此遠端參與者的識別碼。 身分識別是其中一個「識別碼」類型

    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 通訊服務通話 Android SDK 2.11.0 版或更高版本。

若要在通話中將所有其他參與者設為靜音,請在通話上使用 muteAllRemoteParticipants API。

call.muteAllRemoteParticipants();

若要將特定遠端參與者設為靜音,請在指定的遠端參與者上使用 mute API。

remoteParticipant.mute();

若要通知本機參與者他們已遭其他人靜音,請訂閱 onMutedByOthers 事件。

使用前景服務

若即使應用程式在背景運作,您仍想要執行使用者可見的工作,您可以使用前景服務

使用前景服務時,舉例來說,您可以在應用程式當下有通話時持續顯示使用者可見的通知。 如此,即便使用者移至主畫面,或從最近的畫面中移除了應用程式,通話仍會繼續。

如果您在通話期間未使用前景服務,則在瀏覽至主畫面時,通話將可繼續,但若從最近的畫面中移除了應用程式,且 Android OS 終止了應用程式的程序,則通話可能會停止。

您應在啟動/加入通話時啟動前景服務,例如:

call = callAgent.startCall(context, participants, options);
startService(yourForegroundServiceIntent);

在掛斷電話,或通話的狀態為「已中斷連線」時,應停止前景服務,例如:

call.hangUp(new HangUpOptions()).get();
stopService(yourForegroundServiceIntent);

使用前景服務的注意事項

請記住,若您在從最近的清單中移除應用程式時停止了執行中的前景服務,或是在案例下,使用者可見的通知將會移除,而 Android OS 可讓您的應用程式程序再保持一段時間的運作,這表示在此期間仍可繼續通話。

例如,如果您的應用程式在服務 onTaskRemoved 方法上停止了前景服務,應用程式將可根據活動生命週期來啟動/停止音訊和視訊,例如,在使用 onDestroy 方法覆寫終結了活動時停止音訊和視訊。

設定系統

建立 Xcode 專案

在 Xcode 中建立新的 iOS 專案,並選取 [單一檢視應用程式] 範本。 本快速入門使用 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. 使用 Xcode 開啟 .xcworkspace

要求存取麥克風

若要存取裝置的麥克風,您必須使用 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

若要從 CallClient 建立 CallAgent 執行個體,您必須使用 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")
        }
})

注意

應用程式在實作事件委派時,必須保有需要事件訂閱之物件的強式參考。 例如,若在叫用 call.addParticipant 方法時傳回了 RemoteParticipant 物件,且應用程式將委派設定為接聽 RemoteParticipantDelegate,則應用程式必須保有對 RemoteParticipant 物件的強式參考。 否則,如果收集了此物件,在通話 SDK 嘗試叫用物件時,委派將會擲回嚴重例外狀況。

撥出電話

若要建立並啟動通話,您必須在 CallAgent 上呼叫其中一個 API,並提供您使用通訊服務管理 SDK 佈建之使用者的通訊服務識別。

通話的建立和啟動是同步的。 您會收到可讓您訂閱所有通話事件的通話執行個體。

對使用者撥打 1:1 通話,或對使用者和 PSTN 撥打 1:n 通話

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

對使用者和 PSTN 撥打 1:n 通話

注意

請參閱 PSTN 通話供應項目詳細資料。 若要存取預覽程式,請申請加入早期採用者計畫

若要對 PSTN 撥打電話,您必須指定透過通訊服務取得的電話號碼。

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,您可以閱讀概念文件,或遵循快速入門指南

加入群組通話

若要加入通話,您必須在 CallAgent 上呼叫其中一個 API。

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

接聽來電

若要接聽電話,請在 IncomingCall 物件上呼叫 accept 方法。

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

執行通話中作業

您可以在通話期間執行多種作業,以管理視訊和音訊的相關設定。

靜音和取消靜音

若要將本機端點設為靜音或取消靜音,您可以使用 muteunmute 非同步 API。

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

從通話中移除參與者

若要從通話中移除參與者 (使用者或電話號碼),您可以叫用 removeParticipant API。 這會以非同步方式進行解析。

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 通訊服務通話 iOS SDK 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 專案

針對 UWP 應用程式,在 Visual Studio 2022 中建立新的空白應用程式 (通用 Windows) 專案。 在輸入專案名稱之後,隨意選擇高於 10.0.17763.0 的任何 Windows SDK。

針對 WinUI 3 應用程式,使用空白應用程式、封裝 (桌面中的 WinUI 3) 範本建立新專案,以設定單頁 WinUI 3 應用程式。 需要 Windows App SDK 1.3 版或更新版本。

使用 NuGet 套件管理員來安裝套件和相依性

通話 SDK API 和程式庫可透過 NuGet 套件公開取得。

下列步驟示範如何尋找、下載及安裝通話 SDK NuGet 套件:

  1. 藉由選取 [工具]>[NuGet 套件管理員]>[管理解決方案的 NuGet 套件],開啟 NuGet 套件管理員。
  2. 選取 [瀏覽],然後在搜尋方塊中輸入 Azure.Communication.Calling.WindowsClient
  3. 確定已選取 [包含發行前版本] 核取方塊。
  4. 選取 Azure.Communication.Calling.WindowsClient 套件,然後選取 Azure.Communication.Calling.WindowsClient 1.4.0-beta.1 或更新版本。
  5. 選取與右側索引標籤上的「通訊服務」專案相對應的核取方塊。
  6. 選取 [安裝] 按鈕。

要求存取麥克風

應用程式需要存取麥克風才能正常執行。 在 UWP 應用程式中,應於應用程式資訊清單檔中宣告麥克風功能。

下列步驟會示範如何達成此目的。

  1. Solution Explorer 面板中,按兩下副檔名為 .appxmanifest 的檔案。
  2. 按一下 Capabilities 索引標籤。
  3. 從功能清單中選取 Microphone 核取方塊。

建立 UI 按鈕以撥打和掛斷通話

這個簡單的範例應用程式包含兩個按鈕。 一個用於撥打電話,另一個用於掛斷通話。 下列步驟示範如何將這兩個按鈕新增至應用程式。

  1. Solution Explorer 面板中,按兩下名為 MainPage.xaml 的檔案 (若為 UWP) 或名為 MainWindows.xaml 的檔案 (若為 WinUI 3)。
  2. 在中央面板中,尋找 UI 預覽下的 XAML 程式碼。
  3. 依照下列摘錄修改 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>

使用通話 SDK API 設定應用程式

通話 SDK API 位於兩個不同的命名空間中。 下列步驟會向 C# 編譯器告知這兩個命名空間的資訊,讓 Visual Studio 的 Intellisense 能夠協助開發程式碼。

  1. Solution Explorer 面板中,按一下名為 MainPage.xaml 的檔案 (若為 UWP) 左側的箭號,或名為 MainWindows.xaml 的檔案 (若為 WinUI 3) 左側的箭號。
  2. 按兩下名為 MainPage.xaml.csMainWindows.xaml.cs 的檔案。
  3. 在目前的 using 陳述式底部新增下列命令。
using Azure.Communication.Calling.WindowsClient;

MainPage.xaml.csMainWindows.xaml.cs 保持開啟。 後續步驟會在其中新增更多程式碼。

允許應用程式互動

先前新增的 UI 按鈕需要在放置的 CommunicationCall 頂端運作。 這表示您應該將 CommunicationCall 資料成員新增至 MainPageMainWindow 類別。 此外,為了讓建立 CallAgent 的非同步作業成功,也應該將 CallAgent 資料成員新增至相同的類別。

將下列資料成員新增至 MainPageMainWindow 類別:

CallAgent callAgent;
CommunicationCall call;

建立按鈕處理常式

先前已將兩個 UI 按鈕新增至 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

若要從 CallClient 建立 CallAgent 執行個體,必須使用 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 通訊服務回應 Bot 交談。

靜音和取消靜音

若要將傳出的音訊設為靜音或取消靜音,您可以使用 MuteOutgoingAudioAsyncUnmuteOutgoingAudioAsync 非同步 API:

// mute outgoing audio
await this.call.MuteOutgoingAudioAsync();

// unmute outgoing audio
await this.call.UnmuteOutgoingAudioAsync();

將其他參與者設為靜音

注意

若要使用此 API,請使用 Azure 通訊服務通話 Windows SDK 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 事件。

結束通話

撥打電話後,應使用 CommunicationCall 物件的 HangupAsync 方法來掛斷通話。

此外也應使用 HangupOptions 的執行個體,告知是否必須向所有參與者終止通話。

請在 HangupButton_Click 內新增下列程式碼。

this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions() { ForEveryone = false });

執行程式碼

請確定 Visual Studio 會針對 x64x86ARM64 建置應用程式,然後按 F5 開始執行應用程式。 然後,按一下 Call 按鈕,向已定義的受話方撥打電話。

請記住,應用程式首次執行時,系統會提示使用者授與麥克風的存取權。

下一步