管理通話

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

必要條件

安裝 SDK

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

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

初始化必要的物件

CallClient大部分呼叫作業都需要 實例。 當您建立新的 CallClient 實例時,您可以使用實例之類的 Logger 自定義選項進行設定。

CallClient透過 實例,您可以藉由呼叫 createCallAgent來建立 CallAgent 實例。 這個方法會以異步方式傳 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()

撥打電話

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

呼叫建立和啟動是同步的。 實例 call 可讓您訂閱呼叫事件。

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

若要呼叫另一個通訊服務使用者,請使用 startCall 方法,callAgent並使用通訊服務系統管理連結庫來傳遞您建立的CommunicationUserIdentifier收件者。

針對對使用者的 「1:1」 呼叫,請使用下列程式代碼:

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

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

當您呼叫 PSTN 號碼時,請指定替代的來電者識別碼。 替代來電者標識碼是一個電話號碼(根據 E.164 標準),可識別 PSTN 通話中的來電者。 這是來電收件者看到的來電電話號碼。

注意

請檢查 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,這些 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();

當 API 解析時 hold ,呼叫狀態會設定為 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()' 之前無法接聽。 不過,我們可以在通話音訊上套用篩選,並播放篩選的音訊。

將其他參與者設為靜音

注意

此 API 僅供開發人員預覽,而且可能會根據收到的意見反應變更。 若要使用此 API,請使用 Azure 通訊服務 呼叫 Web SDK 1.18.1 版或更高版本的『beta』版本。

若要讓所有其他參與者靜音或將特定參與者設為靜音,您可以在呼叫和mute遠端參與者上使用異步 APImuteAllRemoteParticipants

//mute all participants except yourself
await call.muteAllRemoteParticipants();

//mute a specific participant
await call.remoteParticipants[0].mute();

管理遠端參與者

所有遠端參與者都會在 對象中 RemoteParticipant 詳述,而且可透過 remoteParticipants 呼叫實例上的集合取得。 remoteParticipants可從 Call 實體存取 。

列出通話中的參與者

集合 remoteParticipants 會傳回呼叫中遠端參與者的清單:

call.remoteParticipants; // [remoteParticipant, remoteParticipant....]

將參與者新增至通話

若要將參與者(用戶或電話號碼)新增至通話,您可以使用 addParticipant API。 提供其中 Identifier 一種類型。 它會同步傳 remoteParticipant 回 實例。 remoteParticipantsUpdated成功將參與者新增至呼叫時,就會引發來自 Call 的事件。

const userIdentifier = { communicationUserId: '<ACS_USER_ID>' };
const pstnIdentifier = { phoneNumber: '<PHONE_NUMBER>' }
const remoteParticipant = call.addParticipant(userIdentifier);
const remoteParticipant = call.addParticipant(pstnIdentifier, {alternateCallerId: '<ALTERNATE_CALLER_ID>'});

從通話中移除參與者

若要從通話中移除參與者(使用者或電話號碼),您可以叫用 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 status:若要找出遠端參與者是否靜音,請檢查 isMuted 屬性。 它會傳回 Boolean

    const isMuted = remoteParticipant.isMuted;
    
  • isSpeaking status:若要找出遠端參與者是否正在說話,請檢查 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 的原始標識碼不同。

檢查呼叫屬性

取得呼叫的唯一識別碼(字串):

const callId: string = call.id;

取得本機參與者識別碼:

const participantId: string = call.info.participantId;

注意:Azure 通訊服務 身分識別可以在許多端點中使用 Web 呼叫 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 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 作用中的視訊串流和使用中的螢幕畫面共用串流。 API 會localVideoStreamsLocalVideoStream回、 或RawMedia類型的VideoScreenSharing物件。

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()至 和 allprojects下的buildscript存放庫清單:

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 通話

若要呼叫另一個通訊服務使用者,請在 上callAgentcall用 方法,並使用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 通話供應專案的詳細數據。 如需預覽計劃存取, 請套用至早期採用者計劃

若要對使用者撥打 1:n 通話和 PSTN 號碼,您必須指定被呼叫端的電話號碼。 您的通訊服務資源必須設定為允許 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();

透過訂閱 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;
}

加入會議室通話

藉由指定 roomIdCallAgent使用和 RoomCallLocator 加入會議室通話。 方法 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();

將其他參與者設為靜音

注意

此 API 是以開發人員公開預覽的形式提供,而且可能會根據我們收到的意見反應而變更。 若要使用此 API,請使用 Azure 通訊服務 呼叫 Android SDK 2.6.0-beta.5 版或更高版本的『beta』版本。

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

call.muteAllRemoteParticipants();

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

remoteParticipant.mute();

變更呼叫的磁碟區

當您在通話時,電話上的硬體音量密鑰應該允許使用者變更通話音量。 做法是在呼叫所在的 Activity 上使用 方法 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();

遠端參與者屬性

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

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

    CommunicationIdentifier participantIdentifier = remoteParticipant.getIdentifier();
    
  • 取得此遠端參與者的狀態。

    ParticipantState state = remoteParticipant.getState();
    

狀態可以是下列其中一項

  • 'IDLE' - 初始狀態

  • 'EARLY_MEDIA' - 在參與者連線到通話之前播放公告

  • 'RINGING' - 參與者通話正在響鈴

  • 'CONNECTING' - 當參與者連線到通話時轉換狀態

  • 'CONNECTED' - 參與者已連線到通話

  • 'HOLD' - 參與者處於保留狀態

  • “IN_LOBBY” - 參與者正在等候大廳接受。 目前僅適用於Teams Interop案例

  • 'DISCONNECTED' - 最終狀態 - 參與者與通話中斷連線

  • 若要了解參與者為何離開通話,請檢查 callEndReason 屬性:

    CallEndReason callEndReason = remoteParticipant.getCallEndReason();
    
  • 若要檢查此遠端參與者是否設為靜音,請檢查 isMuted 屬性:

    boolean isParticipantMuted = remoteParticipant.isMuted();
    
  • 若要檢查此遠端參與者是否說話,請檢查 isSpeaking 屬性:

    boolean isParticipantSpeaking = remoteParticipant.isSpeaking();
    
  • 若要檢查指定參與者在此呼叫中傳送的所有視訊串流,請檢查 videoStreams 集合:

    List<RemoteVideoStream> videoStreams = remoteParticipant.getVideoStreams(); // [RemoteVideoStream, RemoteVideoStream, ...]
    

使用前景服務

如果您想要執行用戶可見的工作,即使應用程式位於背景,您也可以使用 Foreground Services

例如,使用 Foreground Services 時,您可以讓使用者在應用程式有作用中呼叫時顯示通知。 如此一來,即使使用者前往主畫面或從 最近畫面移除應用程式,呼叫仍會繼續作用中。

如果您在通話中未使用 Foreground 服務,流覽至主畫面可能會讓呼叫保持作用中,但如果 Android OS 終止應用程式的程式,則從最近畫面移除應用程式可能會停止呼叫。

當您啟動/加入呼叫時,您應該啟動 Foreground 服務,例如:

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

當您停止呼叫或呼叫的狀態為已中斷連線時,請停止 Foreground 服務,例如:

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

使用 Foreground Services 的注意事項

請記住,當應用程式從最近清單移除時停止已執行中的Foreground Service 等案例,將會移除使用者可見的通知,而 Android OS 可以讓應用程式進程保持運作一段時間,這表示此期間仍可作用中的呼叫。

例如,如果您的應用程式在服務 onTaskRemoved 方法上停止 Foreground Service,您的應用程式可以根據活動 生命周期 啟動/停止音訊和視訊,例如在活動被方法 onDestroy 覆寫終結時停止音訊和視訊。

設定系統

建立 Xcode 專案

在 Xcode 中,建立新的 iOS 專案,然後選取 [單一檢視應用程式 ] 範本。 本快速入門使用 SwiftUI 架構,因此您應該將 Language 設定Swift,並將 Interface 設定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

若要從 建立 CallAgent 實例,您必須使用callClient.createCallAgent方法,以異步方式在物件初始化之後傳回CallAgent物件。CallClient

若要建立呼叫用戶端,請傳遞 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")
        }
})

注意

當應用程式實作事件委派時,它必須保存需要事件訂閱之物件的強式參考。 例如,在 RemoteParticipantcall.addParticipant 用 方法時傳回 物件,而應用程式會設定要接 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")
    }
}

將其他參與者設為靜音

注意

此 API 是以開發人員公開預覽的形式提供,而且可能會根據我們收到的意見反應而變更。 若要使用此 API,請使用 Azure 通訊服務 呼叫 iOS SDK 2.7.0-beta.3 版或更高版本的『beta』版本。

若要在呼叫中將所有其他參與者設為靜音,請在 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.")
    }
}

管理遠端參與者

所有遠端參與者都會以 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, ...]

設定系統

建立 Visual Studio 專案

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

針對 WinUI 3 應用程式,使用 [空白應用程式]、[傳統型] 範本建立新的專案,以設定單頁 WinUI 3 應用程式。 需要 Windows 應用程式 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.WindowsClient1.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面板中,按兩下針對UWP或 MainWindows.xaml WinUI 3 命名MainPage.xaml之檔案左側的箭號。
  2. 按兩下名為 MainPage.xaml.cs 或的 MainWindows.xaml.cs檔案。
  3. 在目前 using 語句底部新增下列命令。
using Azure.Communication.Calling.WindowsClient;

保持 MainPage.xaml.csMainWindows.xaml.cs 開啟。 後續步驟會將更多程序代碼新增至其中。

允許應用程式互動

先前新增的 UI 按鈕需要在放置 CommunicationCall的 頂端操作。 這表示 CommunicationCall 數據成員應該新增至 MainPageMainWindow 類別。 此外,若要允許建立 CallAgent 異步操作成功, CallAgent 數據成員也應該新增至相同的類別。

將下列資料成員新增至 MainPage pr MainWindow 類別:

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
}

物件模型

下列類別和介面會處理適用於UWP Azure 通訊服務呼叫用戶端連結庫的一些主要功能。

名稱 描述
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 是以開發人員公開預覽的形式提供,而且可能會根據我們收到的意見反應而變更。 若要使用此 API,請使用 Azure 通訊服務 呼叫 Windows SDK 1.4.0-beta.1 版或更高版本的『beta』版本。

若要讓所有其他參與者靜音或將特定參與者設為靜音,您可以在呼叫和MuteAsync遠端參與者上使用異步 APIMuteAllRemoteParticipantsAsync

// mute all participants except yourself
await this.call.MuteAllRemoteParticipantsAsync();

// mute specific participant in the call
await this.call.RemoteParticipants.FirstOrDefault().MuteAsync();

結束通話

呼叫之後, HangupAsync 應該使用 物件的方法 CommunicationCall 來掛斷呼叫。

HangupOptions 實例也應該用來通知呼叫是否必須終止給其所有參與者。

應該在內 HangupButton_Click新增下列程序代碼。

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

執行程式碼

請確定 Visual Studio 會建置、 x64x86ARM64的應用程式,然後按兩下 F5 以開始執行應用程式。 之後,按下 Call 按鈕以呼叫已定義的被呼叫者。

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

下一步