建議您訂閱呼叫 SDK 事件。 Azure 通訊服務 SDK 是動態的,且包含可能會隨著時間變更的屬性。 您可以訂閱這些事件,以事先收到任何變更的通知。 請遵循本文中的指示來訂閱 Azure 通訊服務 SDK 事件。
Azure 通訊通話 SDK 上的事件
本節說明您的應用程式可以訂閱的事件和屬性變更。 訂閱這些事件可讓您的應用程式得知呼叫 SDK 中的狀態變更,並據此做出反應。
追蹤事件非常重要,因為它可讓應用程式的狀態與 Azure 通訊服務呼叫架構的狀態保持同步。 追蹤事件可協助您在不需要在 SDK 物件上實作提取機制的情況下,追蹤變更。
本節假設您已完成快速入門,或您已實作能夠撥打和接聽呼叫的應用程式。 如果您未完成入門指南,請參閱 將語音通話新增至您的應用程式。
JavaScript 呼叫 SDK 中的每個物件都有 properties
和 collections
。 其值會在物件的存留期內變更。
使用on()
方法來訂閱物件事件。 使用 off()
方法來取消訂閱物件事件。
屬性
您可以訂閱 '<property>Changed'
事件,以接聽 屬性上的值變更。
屬性上的訂用帳戶範例
在此範例中,我們會訂閱 屬性值的 isLocalVideoStarted
變更。
call.on('isLocalVideoStartedChanged', () => {
// At that point the value call.isLocalVideoStarted is updated
console.log(`isLocalVideoStarted changed: ${call.isLocalVideoStarted}`);
});
集合
您可以訂閱 \<collection>Updated
事件,以接收物件集合中變更的相關通知。 每當您監視的集合中新增或移除元素時,就會觸發\<collection>Updated
事件。
-
'<collection>Updated'
事件的裝載具有added
陣列,其中包含已新增至集合的值。 -
'<collection>Updated'
事件的裝載也有removed
陣列,其中包含從集合中移除的值。
集合上的範例訂用帳戶
在此範例中,我們會訂閱 Call 物件的 LocalVideoStream
值變更。
call.on('localVideoStreamsUpdated', updateEvent => {
updateEvent.added.forEach(async (localVideoStream) => {
// Contains an array of LocalVideoStream that were added to the call
// Add a preview and start any processing if needed
handleAddedLocalVideoStream(localVideoStream )
});
updateEvent.removed.forEach(localVideoStream => {
// Contains an array of LocalVideoStream that were removed from the call
// Remove the preview and stop any processing if needed
handleRemovedLocalVideoStream(localVideoStream )
});
});
物件上的 CallAgent
事件
事件名稱: incomingCall
當用戶端收到來電時,就會引發 incomingCall
事件。
您的應用程式對事件有何反應?
您的應用程式必須通知收件者來電。 通知提示必須讓收件者接受或拒絕通話。
程式代碼範例:
callClient.on('incomingCall', (async (incomingCallEvent) => {
try {
// Store a reference to the call object
incomingCall = incomingCallEvent.incomingCall;
// Update your UI to allow
acceptCallButton.disabled = false;
callButton.disabled = true;
} catch (error) {
console.error(error);
}
});
事件名稱: callsUpdated
當通話遭到移除或新增至通話代理程式時,就會引發 callsUpdated
更新的事件。 當用戶進行、接收或終止呼叫時,就會發生此事件。
您的應用程式對事件有何反應?
您的應用程式必須根據 CallAgent 實例的作用中呼叫數目來更新其 UI。
事件名稱: connectionStateChanged
更新 connectionStateChanged
的訊號狀態 CallAgent
時引發的事件。
您的應用程式對事件有何反應?
您的應用程式必須根據新狀態更新其UI。 可能的連線狀態值為 Connected
和 Disconnected
。
程式代碼範例:
callClient.on('connectionStateChanged', (async (connectionStateChangedEvent) => {
if (connectionStateChangedEvent.newState === "Connected") {
enableCallControls() // Enable all UI element that allow user to make a call
}
if (connectionStateChangedEvent.newState === 'Disconnected') {
if (typeof connectionStateChangedEvent.reason !== 'undefined') {
alert(`Disconnected reason: ${connectionStateChangedEvent.reason}`)
}
disableCallControls() // Disable all the UI element that allows the user to make a call
}
});
物件上的 Call
事件
事件名稱: stateChanged
當呼叫狀態變更時,就會引發 stateChanged
事件。 例如,當呼叫從 connected
到 disconnected
時。
您的應用程式對事件有何反應?
您的應用程式必須據以更新其UI。 根據新的呼叫狀態停用或啟用適當的按鈕和其他UI元素。
程式代碼範例:
call.on('stateChanged', (async (connectionStateChangedEvent) => {
if(call.state === 'Connected') {
connectedLabel.hidden = false;
acceptCallButton.disabled = true;
startCallButton.disabled = true;
startVideoButton.disabled = false;
stopVideoButton.disabled = false
} else if (call.state === 'Disconnected') {
connectedLabel.hidden = true;
startCallButton.disabled = false;
console.log(`Call ended, call end reason={code=${call.callEndReason.code}, subCode=${call.callEndReason.subCode}}`);
}
});
事件:idChanged
當呼叫的標識碼變更時,就會引發 idChanged
事件。 當呼叫從connecting
狀態移至 時,呼叫的標識符會變更。connected
聯機呼叫之後,呼叫的標識符會維持不變。
您的應用程式對事件有何反應?
您的應用程式可以儲存新的呼叫標識碼,或在需要時從呼叫物件擷取它。
程式代碼範例:
let callId = "";
call.on('idChanged', (async (callIdChangedEvent) => {
callId = call.id; // You can log it as the call ID is useful for debugging call issues
});
事件:isMutedChanged
當本機音訊被靜音或取消靜音時,就會觸發isMutedChanged
事件。
您的應用程式對事件有何反應?
您的應用程式必須將靜音/取消靜音按鈕更新為適當的狀態。
程式代碼範例:
call.on('isMutedChanged', (async (isMutedChangedEvent) => {
microphoneButton.disabled = call.isMuted;
});
事件:isScreenSharingOnChanged
啟用或停用本機使用者的螢幕畫面分享時,就會引發 isScreenSharingOnChanged
事件。
您的應用程式對事件有何反應?
如果螢幕共享開啟,您的應用程式必須向用戶顯示預覽和/或警告。
如果螢幕共用關閉,應用程式必須移除預覽和警告。
程式代碼範例:
call.on('isScreenSharingOnChanged', () => {
if (!this.call.isScreenSharing) {
displayStartScreenSharingButton();
hideScreenSharingWarning()
removeScreenSharingPreview();
} else {
displayScreenSharingWarning()
displayStopScreenSharingButton();
renderScreenSharingPreview();
}
});
事件:isLocalVideoStartedChanged
當使用者啟用我們停用的其本機視訊時,就會引發 isLocalVideoStartedChanged
事件。
您的應用程式對事件有何反應?
您的應用程式必須顯示本機視訊的預覽,並啟用或停用相機啟用按鈕。
程式代碼範例:
call.on('isLocalVideoStartedChanged', () => {
showDisableCameraButton(call.isLocalVideoStarted);
});
事件:remoteParticipantsUpdated
您的應用程式必須訂閱每個新增 RemoteParticipants
的事件,並取消訂閱離開通話的參與者的事件。
您的應用程式對事件有何反應?
您的應用程式必須顯示本機視訊的預覽,並啟用或停用相機啟用按鈕。
程式代碼範例:
call.on('remoteParticipantsUpdated', (remoteParticipantsUpdatedEvent) => {
remoteParticipantsUpdatedEvent.added.forEach(participant => {
// handleParticipant should
// - subscribe to the remote participants events
// - update the UI
handleParticipant(participant);
});
remoteParticipantsUpdatedEvent.removed.forEach(participant => {
// removeParticipant should
// - unsubscribe from the remote participants events
// - update the UI
removeParticipant(participant);
});
});
事件:localVideoStreamsUpdated
當本機視訊串流清單變更時,就會引發 localVideoStreamsUpdated
事件。 當用戶啟動或移除視訊串流時,就會發生這些變更。
您的應用程式對事件有何反應?
您的應用程式必須針對每個 LocalVideoStream
新增項目顯示預覽。 您的應用程式必須移除預覽,並在每個 LocalVideoStream
被移除時停止處理。
程式代碼範例:
call.on('localVideoStreamsUpdated', (localVideoStreamUpdatedEvent) => {
localVideoStreamUpdatedEvent.added.forEach(addedLocalVideoStream => {
// Add a preview and start any processing if needed
handleAddedLocalVideoStream(addedLocalVideoStream)
});
localVideoStreamUpdatedEvent.removed.forEach(removedLocalVideoStream => {
// Remove the preview and stop any processing if needed
this.handleRemovedLocalVideoStream(removedLocalVideoStream)
});
});
事件:remoteAudioStreamsUpdated
當遠端音訊串流清單變更時,就會引發 remoteAudioStreamsUpdated
事件。 當遠端參與者將音訊串流新增或移除至通話時,就會發生這些變更。
您的應用程式對事件有何反應?
如果正在處理數據流且現在已移除,則必須停止處理。 另一方面,如果新增數據流,則事件接收是開始處理新音訊數據流的好位置。
事件:totalParticipantCountChanged
在 totalParticipantCountChanged
呼叫中變更 totalParticipant 數目時引發。
您的應用程式對事件有何反應?
如果您的應用程式顯示參與者計數器,您的應用程式可以在收到事件時更新其參與者計數器。
程式代碼範例:
call.on('totalParticipantCountChanged', () => {
participantCounterElement.innerText = call.totalParticipantCount;
});
事件:roleChanged
參與者 roleChanged
會在呼叫中localParticipant角色變更時引發。 例如,當本機參與者在通話中成為演示者 ACSCallParticipantRolePresenter
時。
您的應用程式對事件有何反應?
您的應用程式必須根據使用者的新角色來啟用或停用按鈕。
程式代碼範例:
call.on('roleChanged', () => {
this.roleElement = call.role;
});
事件:mutedByOthers
當本機參與者將通話中的其他參與者設為靜音時,就會發生 mutedByOthers
事件。
您的應用程式對事件有何反應?
您的應用程式必須向使用者顯示訊息,通知他們已靜音。
程式代碼範例:
call.on('mutedByOthers', () => {
messageBanner.innerText = "You have been muted by other participant in this call";
});
事件:callerInfoChanged
當呼叫端資訊更新時,就會 callerInfoChanged
發生此事件。 當呼叫端變更其顯示名稱時,就會發生這種情況。
您的應用程式對事件有何反應? 應用程式可以更新呼叫端資訊。
程式代碼範例:
call.on('callerInfoChanged', () => {
showCallerInfo(call.callerInfo)
});
事件:transferorInfoChanged
更新傳送者資訊時,就會 transferorInfoChanged
發生此事件。 當傳送器變更其顯示名稱時,就會發生這種情況。
您的應用程式對事件有何反應? 應用程式可以更新傳送者資訊。
程式代碼範例:
call.on('transferorInfoChanged', () => {
showTransferorInfo(call.transferorInfo)
});
物件上的 RemoteParticipant
事件
事件:roleChanged
當角色在呼叫中變更時roleChanged
,就會RemoteParticipant
引發 事件。 例如,當 RemoteParticipant 在呼叫中成為演示者 ACSCallParticipantRolePresenter
時。
您的應用程式對事件有何反應?
您的應用程式必須根據 RemoteParticipant
新角色更新其UI。
程式代碼範例:
remoteParticipant.on('roleChanged', () => {
updateRole(remoteParticipant);
});
事件:isMutedChanged
當其中一isMutedChanged
個靜音或取消靜音其麥克風時,就會RemoteParticipant
引發事件。
您的應用程式對事件有何反應?
您的應用程式可以在顯示參與者的檢視畫面旁邊顯示圖示。
程式代碼範例:
remoteParticipant.on('isMutedChanged', () => {
updateMuteStatus(remoteParticipant); // Update the UI based on the mute state of the participant
});
事件:displayNameChanged
displayNameChanged
更新的名稱RemoteParticipant
時。
您的應用程式對事件有何反應?
如果參與者的姓名顯示在用戶界面中,您的應用程式必須進行更新。
程式代碼範例:
remoteParticipant.on('displayNameChanged', () => {
remoteParticipant.nameLabel.innerText = remoteParticipant.displayName;
});
remoteParticipant.on('displayNameChanged', (args: {newValue?: string, oldValue?: string, reason?: DisplayNameChangedReason}) => {
remoteParticipant.nameLabel.innerText = remoteParticipant.displayName;
console.log(`Display name changed from ${oldValue} to ${newValue} due to ${reason}`);
});
事件:isSpeakingChanged
當 isSpeakingChanged
通話中佔主導地位的說話者變更時。
您的應用程式對事件有何反應?
您的應用程式 UI 必須優先顯示 RemoteParticipant
成為主要說話者的人員。
程式代碼範例:
remoteParticipant.on('isSpeakingChanged', () => {
showAsRemoteSpeaker(remoteParticipant) // Display a speaking icon near the participant
});
事件:videoStreamsUpdated
當 videoStreamsUpdated
遠端參與者在通話中新增或移除 VideoStream 時。
您的應用程式對事件有何反應?
如果您的應用程式正在處理已移除的數據流,您的應用程式必須停止處理。 新增數據流時,我們建議您的應用程式開始轉譯或處理它。
程式代碼範例:
remoteParticipant.on('videoStreamsUpdated', (videoStreamsUpdatedEvent) => {
videoStreamsUpdatedEvent.added.forEach(addedRemoteVideoStream => {
// Remove a renderer and start processing the stream if any processing is needed
handleAddedRemoteVideoStream(addedRemoteVideoStream)
});
videoStreamsUpdatedEvent.removed.forEach(removedRemoteVideoStream => {
// Remove the renderer and stop processing the stream if any processing is ongoing
this.handleRemovedRemoteVideoStream(removedRemoteVideoStream)
});
});
物件上的 AudioEffectsFeature
事件
事件:effectsStarted
當選取的音訊效果套用至音訊數據流時,就會發生這個事件。 例如,當某人開啟噪音抑制時,就會引發 effectsStarted
。
您的應用程式對事件有何反應?
您的應用程式可以顯示或啟用按鈕,讓使用者停用音訊效果。
程式代碼範例:
audioEffectsFeature.on('effectsStarted', (effects) => {
stopEffectButton.style.visibility = "visible";
});
事件:effectsStopped
當選取的音訊效果套用至音訊數據流時,就會發生這個事件。 例如,當某人關閉噪音抑制時,就會引發 effectsStopped
。
您的應用程式對事件有何反應?
您的應用程式可以顯示或啟用按鈕,讓使用者啟用音訊效果。
程式代碼範例:
audioEffectsFeature.on('effectsStopped', (effects) => {
startEffectButton.style.visibility = "visible";
});
事件:effectsError
當音訊效果啟動或套用時發生錯誤時,就會發生這個事件。
您的應用程式對事件有何反應?
您的應用程式必須顯示警示或錯誤訊息,指出音訊效果未如預期般運作。
程式代碼範例:
audioEffectsFeature.on('effectsError', (error) => {
console.log(`Error with the audio effect ${error}`);
alert(`Error with the audio effect`);
});
安裝 SDK
找出您的項目層級build.gradle
檔案,並將 新增mavenCentral()
至 和buildscript
下的allprojects
存放庫清單:
buildscript {
repositories {
...
mavenCentral()
...
}
}
allprojects {
repositories {
...
mavenCentral()
...
}
}
然後,在您的模組層級 build.gradle
檔案中,將下列幾行新增至 dependencies
區段:
dependencies {
...
implementation 'com.azure.android:azure-communication-calling:1.0.0'
...
}
初始化必要的物件
若要建立 CallAgent
執行個體,您必須在 createCallAgent
執行個體上呼叫 CallClient
方法。 此呼叫會以非同步方式傳回 CallAgent
執行個體物件。
createCallAgent
方法會採用 CommunicationUserCredential
作為引數,用來封裝存取權杖。
若要存取 DeviceManager
,您必須先建立 callAgent
執行個體。 然後,您可以使用 CallClient.getDeviceManager
方法取得 DeviceManager
。
String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential).get();
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
若要設定來電者的顯示名稱,請使用下列替代方法:
String userToken = '<user token>';
CallClient callClient = new CallClient();
CommunicationTokenCredential tokenCredential = new CommunicationTokenCredential(userToken);
android.content.Context appContext = this.getApplicationContext(); // From within an activity, for instance
CallAgentOptions callAgentOptions = new CallAgentOptions();
callAgentOptions.setDisplayName("Alice Bob");
DeviceManager deviceManager = callClient.getDeviceManager(appContext).get();
CallAgent callAgent = callClient.createCallAgent(appContext, tokenCredential, callAgentOptions).get();
現在您已安裝 Android SDK,您可以訂閱大部分的屬性和集合,以在值變更時收到通知。
屬性
若要訂閱 property changed
事件:
// subscribe
PropertyChangedListener callStateChangeListener = new PropertyChangedListener()
{
@Override
public void onPropertyChanged(PropertyChangedEvent args)
{
Log.d("The call state has changed.");
}
}
call.addOnStateChangedListener(callStateChangeListener);
//unsubscribe
call.removeOnStateChangedListener(callStateChangeListener);
使用在相同類別內定義的事件接聽程式時,請將接聽程式繫結至變數。 若要新增和移除接聽程式方法,請將變數當做自變數傳入。
如果您嘗試以引數形式直接傳入接聽程式,則您會失去對該接聽程式的參考。 Java 正在建立這些接聽程式的新執行個體,而不是參考先前建立的接聽程式。 其仍會正常觸引,但無法移除,因為您不再有其參考。
集合
若要訂閱 collection updated
事件:
LocalVideoStreamsChangedListener localVideoStreamsChangedListener = new LocalVideoStreamsChangedListener()
{
@Override
public void onLocalVideoStreamsUpdated(LocalVideoStreamsEvent localVideoStreamsEventArgs) {
Log.d(localVideoStreamsEventArgs.getAddedStreams().size());
Log.d(localVideoStreamsEventArgs.getRemovedStreams().size());
}
}
call.addOnLocalVideoStreamsChangedListener(localVideoStreamsChangedListener);
// To unsubscribe
call.removeOnLocalVideoStreamsChangedListener(localVideoStreamsChangedListener);
設定系統
請遵循下列步驟來設定系統。
建立 Xcode 專案
在 Xcode 中建立新的 iOS 專案,並選取 [單一檢視應用程式] 範本。 本文使用 SwiftUI 架構,因此您應該將 Language 設定為 Swift,並將 Interface 設定為 SwiftUI。
您不會在本文中建立測試。 您可以隨意清除 [包含測試] 核取方塊。
使用 CocoaPods 安裝套件和相依性
為您的應用程式建立 Podfile,如以下範例所示:
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 1.0.0' end
執行
pod install
。使用 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
執行個體,您必須使用 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")
}
})
現在您已安裝 iOS SDK,您可以訂閱大部分的屬性和集合,以在值變更時收到通知。
屬性
若要訂閱 property changed
事件,請使用下列程式碼。
call.delegate = self
// Get the property of the call state by getting on the call's state member
public func call(_ call: Call, didChangeState args: PropertyChangedEventArgs) {
{
print("Callback from SDK when the call state changes, current state: " + call.state.rawValue)
}
// to unsubscribe
self.call.delegate = nil
集合
若要訂閱 collection updated
事件,請使用下列程式碼。
call.delegate = self
// Collection contains the streams that were added or removed only
public func call(_ call: Call, didUpdateLocalVideoStreams args: LocalVideoStreamsUpdatedEventArgs) {
{
print(args.addedStreams.count)
print(args.removedStreams.count)
}
// to unsubscribe
self.call.delegate = nil