SDK イベントをサブスクライブする
Azure Communication Services SDK は動的であり、多数のプロパティが含まれています。 これらの変更が発生した場合、開発者は、変更が発生した時点と、変更内容が何であるかを知る必要があります。 ご覧ください。
Azure Communication Calling 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' イベントは、監視対象のコレクションに要素が追加または削除されるたびにトリガーされます。
'<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
イベントは、呼び出しの ID が変更されたときに発生します。 呼び出しの ID は、呼び出しが connecting
状態から connected
に移行すると変更されます。 呼び出しが接続されると、呼び出しの ID は同じままになります。
このイベントのアプリケーションでの対処方法
アプリケーションで新しい呼び出し ID を保存する必要がありますが、必要に応じて後で呼び出しオブジェクトから取得することもできます。
コード サンプル:
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";
});
RemoteParticipant
オブジェクトのイベント
イベント: roleChanged
roleChanged
イベントは、呼び出しの中で RemotePartipant
ロールが変更されたときに発生します。 たとえば、リモート参加者が通話の発表者 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
RemoteParticipant
の名前が更新されたときの displayNameChanged
。
このイベントのアプリケーションでの対処方法
アプリケーションの 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
リモート参加者が呼び出しに対して VideoStream を追加または削除したときの videoStreamsUpdated
。
このイベントのアプリケーションでの対処方法
アプリケーションが削除されたストリームを処理中だった場合。 アプリケーションは処理を停止する必要があります。 新しいストリームが追加されると、アプリケーションでストリームをレンダリングまたは処理する場合があります。
コード サンプル:
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
ファイルを見つけて、buildscript
と allprojects
の下のリポジトリの一覧に mavenCentral()
を追加します。
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] に設定する必要があります。
この記事では、テストは作成しません。 [Include Tests] チェック ボックスはオフにしてもかまいません。
CocoaPods を使用してパッケージと依存関係をインストールする
この例のように、アプリケーション用の Podfile を作成します。
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 1.0.0' end
pod install
を実行します。Xcode を使用して
.xcworkspace
を開きます。
マイクへのアクセスを要求する
デバイスのマイクにアクセスするには、NSMicrophoneUsageDescription
を使用してアプリの情報プロパティ一覧を更新する必要があります。 関連付けられる値には、システムがユーザーにアクセスを要求するために使用するダイアログに含まれる文字列を設定します。
プロジェクト ツリーの [Info.plist] エントリを右クリックし、[Open As]>[Source Code] を選択します。 最上位の <dict>
セクションに以下の行を追加してから、ファイルを保存します。
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
アプリのフレームワークを設定する
プロジェクトの ContentView.swift
ファイルを開きます。 ファイルの先頭に import
宣言を追加して、AzureCommunicationCalling
ライブラリをインポートします。 さらに、AVFoundation
をインポートします。 これは、コードでのオーディオ アクセス許可の要求に必要です。
import AzureCommunicationCalling
import AVFoundation
CallAgent を初期化する
CallClient
から CallAgent
インスタンスを作成するには、初期化された後に CallAgent
オブジェクトを非同期に返す callClient.createCallAgent
メソッドを使用する必要があります。
通話クライアントを作成するには、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