訂閱 SDK 事件
Azure 通訊服務 SDK 是動態的,而且包含許多屬性。 當這些變更時,身為開發人員,您可能會想要知道何時和更重要的是有哪些變更。 方法如下!
Azure 通訊通話 SDK 上的事件
本指南說明應用程式可訂閱的各種事件或屬性變更。 訂閱這些事件可讓您的應用程式得知呼叫 SDK 中的狀態變更,並據此做出反應。
追蹤事件很重要,因為它可讓應用程式的狀態與 ACSCalling 架構的狀態保持同步,而不需要您在 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'
事件的裝載具有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 (incomimgCallEvent) => {
try {
// Store a reference to the call object
incomingCall = incomimgCallEvent.incomingCall;
// Update your UI to allow
acceptCallButton.disabled = false;
callButton.disabled = true;
} catch (error) {
console.error(error);
}
});
事件名稱: callsUpdated
當 callsUpdated
呼叫移除或新增至呼叫代理程式時,就會引發更新的事件。 當用戶進行、接收或終止呼叫時,就會發生此事件。
您的應用程式應該如何回應事件? 您的應用程式應該根據 CallAgent 實例的作用中呼叫數目來更新其 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', () => {
showdDisableCameraButton(call.isLocalVideoStarted);
});
事件:remoteParticipantsUpdated
您的應用程式應該針對已離開呼叫的參與者,訂閱每個已新增 RemoteParticipants
和取消訂閱的事件。
您的應用程式對事件的反應如何? 您的應用程式應該會顯示本機視訊的預覽,並啟用或停用相機啟用按鈕。
程式代碼範例:
call.on('remoteParticipantsUpdated', (remoteParticipantsUpdatedEvent) => {
remoteParticipantsUpdatedEvent.added.forEach(participant => {
// handleParticipant should
// - subscribe to the remote participants events
// - update the UI
handleParticipant(participant);
});
remoteParticipantsUpdatedEvent.removed.forEach(participant => {
// removeParticipant should
// - unsubcribe from the remote participants events
// - update the UI
removeParticipant(participant);
});
});
事件:localVideoStreamsUpdated
當 localVideoStreamsUpdated
本機視訊串流清單變更時,就會引發 事件。 當用戶啟動或移除視訊串流時,就會發生這些變更。
您的應用程式對事件的反應如何?
您的應用程式應該會顯示每個新增的 LocalVideoStream
預覽。 您的應用程式應該移除預覽,並停止每個 LocalVideoStream
已移除的處理。
程式代碼範例:
call.on('localVideoStreamsUpdated', (localVideoStreamUpdatedEvent) => {
localVideoStreamUpdatedEvent.added.forEach(addedLocalVideoStream => {
// Add a preview and start any processing if needed
handleAddedLocalVideoStream(addedLocalVideoStream)
});
localVideoStreamUpdatedEvent.removed.forEach(removedLocalVideoStream => {
// Remove the preview and stop any processing if needed
this.handleRemovedLocalVideoStream(removedLocalVideoStream)
});
});
事件:remoteAudioStreamsUpdated
當 remoteAudioStreamsUpdated
遠端音訊數據流清單變更時,就會引發 事件。 當遠端參與者將音訊串流新增或移除至通話時,就會發生這些變更。
您的應用程式對事件的反應如何?
如果正在處理數據流且現在已移除,則應該停止處理。 另一方面,如果新增數據流,則事件接收是開始處理新音訊數據流的好位置。
事件:totalParticipantCountChanged
在 totalParticipantCountChanged
呼叫中變更 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
當角色在呼叫中變更時RemotePartipant
,就會roleChanged
引發 事件。 例如,當 RemoteParticipant 在呼叫中成為演示者 ACSCallParticipantRolePresenter
時。
您的應用程式對事件的反應如何?
您的應用程式應該根據 RemoteParticipant
新角色來更新其UI。
程式代碼範例:
remoteParticipant.on('roleChanged', () => {
updateRole(remoteParticipant);
});
事件:isMutedChanged
當其中一RemoteParticipant
個靜音或取消靜音其麥克風時,就會isMutedChanged
引發事件。
您的應用程式對事件的反應如何?
您的應用程式可能會在顯示參與者的檢視附近顯示圖示。
程式代碼範例:
remoteParticipant.on('isMutedChanged', () => {
updateMuteStatus(remoteParticipant); // Update the UI based on the mute state of the participant
});
事件:displayNameChanged
displayNameChanged
更新的名稱RemoteParticipant
時。
您的應用程式對事件的反應如何?
如果您的應用程式顯示在UI中,則應用程式應該更新參與者名稱。
程式代碼範例:
remoteParticipant.on('displayNameChanged', () => {
remoteParticipant.nameLabel.innerText = remoteParticipant.displayName;
});
事件:isSpeakingChanged
當 isSpeakingChanged
通話中佔主導地位的說話者變更時。
您的應用程式對事件的反應如何?
您的應用程式 UI 應優先顯示 RemotePartipant
成為主要說話者的人員。
程式代碼範例:
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()
至 和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();
透過我們的 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
若要從 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")
}
})
透過我們的 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