SDK 이벤트 구독

Azure Communication Services SDK는 동적이며 많은 속성을 포함합니다. 이러한 변경이 있을 때 개발자는 시기 및 더 중요한 변경 사항을 알고 싶을 수 있습니다. 방법은 다음과 같습니다.

Azure 통신 통화 SDK의 이벤트

이 가이드에서는 앱이 구독할 수 있는 다양한 이벤트 또는 속성 변경에 대해 설명합니다. 해당 이벤트를 구독하면 앱이 통화 SDK의 상태 변경에 대한 정보를 받고 이에 따라 반응할 수 있습니다.

추적 이벤트는 SDK 개체에 풀 메커니즘을 구현할 필요 없이 애플리케이션 상태가 ACSCalling 프레임워크의 상태와 동기화된 상태를 유지할 수 있도록 해주기 때문에 매우 중요합니다.

이 가이드에서는 사용자가 QuickStart를 진행했거나 전화를 걸고 받을 수 있는 애플리케이션을 구현했다고 가정합니다. 시작 가이드를 완료하지 않은 경우 빠른 시작을 참조하세요.

JavaScript 통화 SDK의 각 개체에는 propertiescollections가 있습니다. 해당 값은 개체의 수명 동안 변경됩니다. 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' 이벤트의 페이로드에는 컬렉션에 추가된 값을 포함하는 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

CallAgent의 신호 상태가 업데이트되면 connectionStateChanged 이벤트가 시작됩니다.

애플리케이션은 이벤트에 어떻게 반응해야 하나요?

애플리케이션은 새로운 상태에 따라 UI를 업데이트해야 합니다. 가능한 연결 상태 값은 ConnectedDisconnected입니다.

코드 샘플:

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

통화 ID가 변경되면 idChanged 이벤트가 시작됩니다. 통화가 connecting 상태에서 connected 상태로 이동하면 통화 ID가 변경됩니다. 통화가 연결되면 통화 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

통화에서 totalParticipant 수가 변경되면 totalParticipantCountChanged가 실행됩니다.

애플리케이션이 이벤트에 어떻게 반응하나요?

애플리케이션이 참가자 카운터를 표시하는 경우 이벤트가 수신되면 애플리케이션은 참가자 카운터를 업데이트할 수 있습니다.

코드 샘플:

call.on('totalParticipantCountChanged', () => {
    participantCounterElement.innerText = call.totalParticipantCount;
});

이벤트: roleChanged

통화에서 localParticipant 역할이 변경되면 roleChanged 참가자가 실행됩니다. 로컬 참가자가 통화에서 발표자 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

통화에서 RemotePartipant 역할이 변경되면 roleChanged 이벤트가 시작됩니다. 예를 들어, 통화에서 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

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 파일을 찾아 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();

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 프레임워크를 사용하므로 언어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 항목을 마우스 오른쪽 단추로 클릭한 다음 Open As>Source Code를 선택합니다. 최상위 <dict> 섹션에 다음 줄을 추가한 다음, 파일을 저장합니다.

<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>

앱 프레임워크 설정

프로젝트의 ContentView.swift 파일을 엽니다. AzureCommunicationCalling 라이브러리를 가져오려면 파일 상단에 import 선언을 추가합니다. 추가로 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

다음 단계