Sottoscrivere eventi dell'SDK
Servizi di comunicazione di Azure SDK sono dinamici e contengono molte proprietà. Quando cambiano, gli sviluppatori potrebbero voler sapere quando e cosa cambiano di più. Ecco come!
Eventi in Azure Communication Calling SDK
Questa guida descrive i vari eventi o le modifiche apportate alle proprietà che l'app può sottoscrivere. La sottoscrizione a tali eventi consente all'app di essere informati sulla modifica dello stato nell'SDK chiamante e reagire di conseguenza.
Il rilevamento degli eventi è fondamentale perché consente allo stato dell'applicazione di rimanere sincronizzati con lo stato del framework ACSCalling, tutto senza che sia necessario implementare un meccanismo pull sugli oggetti SDK.
Questa guida presuppone che sia stata eseguita la guida introduttiva o che sia stata implementata un'applicazione in grado di effettuare e ricevere chiamate. Se la guida introduttiva non è stata completata, vedere la guida introduttiva.
Ogni oggetto nell'SDK chiamante JavaScript ha properties
e collections
. I valori cambiano per tutta la durata dell'oggetto.
Utilizzare il on()
metodo per sottoscrivere gli eventi degli oggetti e usare il metodo per annullare la off()
sottoscrizione agli eventi degli oggetti.
Proprietà
È possibile sottoscrivere l'evento '<property>Changed'
per ascoltare le modifiche al valore nella proprietà .
Esempio di sottoscrizione in una proprietà
In questo esempio si sottoscrivono le modifiche apportate al valore della isLocalVideoStarted
proprietà .
call.on('isLocalVideoStartedChanged', () => {
// At that point the value call.isLocalVideoStarted is updated
console.log(`isLocalVideoStarted changed: ${call.isLocalVideoStarted}`);
});
Raccolte
È possibile sottoscrivere l'evento '<collection Updated' per ricevere notifiche sulle modifiche in una raccolta>di oggetti. L'evento '<collection>Updated' viene attivato ogni volta che gli elementi vengono aggiunti o rimossi dalla raccolta monitorata.
- Il
'<collection>Updated'
payload dell'evento ha unaadded
matrice che contiene valori aggiunti alla raccolta. - Il
'<collection>Updated'
payload dell'evento include anche unaremoved
matrice che contiene valori rimossi dalla raccolta.
Sottoscrizione di esempio in una raccolta
In questo esempio si sottoscrivono le modifiche apportate ai valori dell'oggetto LocalVideoStream
Call .
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 )
});
});
Eventi nell'oggetto CallAgent
Nome evento: incomingCall
L'evento incomingCall
viene generato quando il client riceve una chiamata in arrivo.
Come deve reagire l'applicazione all'evento?
L'applicazione deve notificare all'utente la chiamata in arrivo. La richiesta di notifica deve proporre all'utente di accettare o rifiutare la chiamata.
Esempio di codice:
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);
}
});
Nome evento: callsUpdated
L'evento callsUpdated
aggiornato viene generato quando una chiamata viene rimossa o aggiunta all'agente di chiamata. Questo evento si verifica quando l'utente effettua, riceve o termina una chiamata.
Come deve reagire l'applicazione all'evento? L'applicazione deve aggiornare l'interfaccia utente in base al numero di chiamate attive per l'istanza di CallAgent.
Nome evento: connectionStateChanged
Evento connectionStateChanged
generato quando viene aggiornato lo stato di segnalazione di CallAgent
.
Come deve reagire l'applicazione all'evento?
L'applicazione deve aggiornare l'interfaccia utente in base al nuovo stato. I possibili valori dello stato di connessione sono Connected
e Disconnected
Esempio di codice:
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
}
});
Eventi nell'oggetto Call
Nome evento: stateChanged
L'evento stateChanged
viene generato quando lo stato della chiamata cambia. Ad esempio, quando una chiamata passa da connected
a disconnected
.
Come deve reagire l'applicazione all'evento?
L'applicazione deve aggiornare di conseguenza l'interfaccia utente. Disabilitazione o abilitazione dei pulsanti appropriati e di altri elementi dell'interfaccia utente in base al nuovo stato della chiamata.
Esempio di codice:
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}}`);
}
});
Evento: idChanged
L'evento idChanged
viene generato quando cambia l'ID di una chiamata. L'ID di una chiamata cambia quando la chiamata passa dallo connecting
stato a connected
. Una volta connessa la chiamata, l'ID della chiamata rimane identico.
In che modo l'applicazione può reagire all'evento?
L'applicazione deve salvare il nuovo ID chiamata, ma può anche essere recuperato dall'oggetto chiamata in un secondo momento, se necessario.
Esempio di codice:
let callId = "";
call.on('idChanged', (async (callIdChangedEvent) => {
callId = call.id; // You can log it as the call ID is useful for debugging call issues
});
Evento: isMutedChanged
L'evento isMutedChanged
viene generato quando l'audio locale viene disattivato o non modificato.
In che modo l'applicazione può reagire all'evento?
L'applicazione deve aggiornare il pulsante mute/unmute allo stato corretto.
Esempio di codice:
call.on('isMutedChanged', (async (isMutedChangedEvent) => {
microphoneButton.disabled = call.isMuted;
});
Evento: isScreenSharingOnChanged
L'evento isScreenSharingOnChanged
viene generato quando la condivisione dello schermo per l'utente locale è abilitata o disabilitata.
In che modo l'applicazione può reagire all'evento?
L'applicazione dovrebbe visualizzare un'anteprima e/o un avviso all'utente se la condivisione dello schermo è diventata attiva. Se la condivisione dello schermo è stata disattivata, l'applicazione dovrebbe rimuovere l'anteprima e l'avviso.
Esempio di codice:
call.on('isScreenSharingOnChanged', () => {
if (!this.call.isScreenSharing) {
displayStartScreenSharingButton();
hideScreenSharingWarning()
removeScreenSharingPreview();
} else {
displayScreenSharingWarning()
displayStopScreenSharingButton();
renderScreenSharingPreview();
}
});
Evento: isLocalVideoStartedChanged
L'evento isLocalVideoStartedChanged
viene generato quando l'utente ha abilitato il video locale disabilitato.
In che modo l'applicazione può reagire all'evento?
L'applicazione dovrebbe visualizzare un'anteprima del video locale e abilitare o disabilitare il pulsante di attivazione della fotocamera.
Esempio di codice:
call.on('isLocalVideoStartedChanged', () => {
showdDisableCameraButton(call.isLocalVideoStarted);
});
Evento: remoteParticipantsUpdated
L'applicazione deve sottoscrivere l'evento per ogni evento aggiunto RemoteParticipants
e annullare la sottoscrizione degli eventi per i partecipanti che hanno lasciato la chiamata.
In che modo l'applicazione può reagire all'evento? L'applicazione dovrebbe visualizzare un'anteprima del video locale e abilitare o disabilitare il pulsante di attivazione della fotocamera.
Esempio di codice:
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);
});
});
Evento: localVideoStreamsUpdated
L'evento localVideoStreamsUpdated
viene generato quando cambia l'elenco del flusso video locale. Queste modifiche si verificano all'avvio o alla rimozione di un flusso video.
In che modo l'applicazione può reagire all'evento?
L'applicazione dovrebbe visualizzare le anteprime per ognuna delle LocalVideoStream
aggiunte. L'applicazione deve rimuovere l'anteprima e arrestare l'elaborazione per ogni LocalVideoStream
rimosso.
Esempio di codice:
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)
});
});
Evento: remoteAudioStreamsUpdated
L'evento remoteAudioStreamsUpdated
viene generato quando cambia l'elenco di flussi audio remoti. Queste modifiche si verificano quando i partecipanti remoti aggiungono o rimuovono flussi audio alla chiamata.
In che modo l'applicazione può reagire all'evento?
Se un flusso è in corso di elaborazione e ora viene rimosso, l'elaborazione deve essere arrestata. D'altra parte, se viene aggiunto un flusso, la ricezione dell'evento è un buon punto di partenza per avviare l'elaborazione del nuovo flusso audio.
Evento: totalParticipantCountChanged
Viene totalParticipantCountChanged
generato quando il numero di totalParticipant è cambiato in una chiamata.
In che modo l'applicazione può reagire all'evento?
Se l'applicazione visualizza un contatore dei partecipanti, l'applicazione può aggiornare il contatore dei partecipanti al momento della ricezione dell'evento.
Esempio di codice:
call.on('totalParticipantCountChanged', () => {
participantCounterElement.innerText = call.totalParticipantCount;
});
Evento: roleChanged
Il roleChanged
partecipante viene attivato quando i ruoli localParticipant cambiano nella chiamata. Un esempio è quando il partecipante locale diventa relatore ACSCallParticipantRolePresenter
in una chiamata.
In che modo l'applicazione può reagire all'evento? L'applicazione deve abilitare o disabilitare il pulsante in base al nuovo ruolo dell'utente.
Esempio di codice:
call.on('roleChanged', () => {
this.roleElement = call.role;
});
Evento: mutedByOthers
L'evento mutedByOthers
si verifica quando altri partecipanti alla chiamata vengono disattivati dal partecipante locale.
In che modo l'applicazione può reagire all'evento? L'applicazione dovrebbe visualizzare un messaggio all'utente che informa che è stato disattivato.
Esempio di codice:
call.on('mutedByOthers', () => {
messageBanner.innerText = "You have been muted by other participant in this call";
});
Eventi nell'oggetto RemoteParticipant
Evento: roleChanged
L'evento roleChanged
viene generato quando il RemotePartipant
ruolo cambia nella chiamata. Un esempio è quando remoteParticipant diventa relatore ACSCallParticipantRolePresenter
in una chiamata.
In che modo l'applicazione può reagire all'evento?
L'applicazione deve aggiornare l'interfaccia utente in base al RemoteParticipant
nuovo ruolo.
Esempio di codice:
remoteParticipant.on('roleChanged', () => {
updateRole(remoteParticipant);
});
Evento: isMutedChanged
L'evento isMutedChanged
viene generato quando uno dei disattiva o annulla l'audio RemoteParticipant
del microfono.
In che modo l'applicazione può reagire all'evento?
L'applicazione può visualizzare un'icona vicino alla visualizzazione che visualizza il partecipante.
Esempio di codice:
remoteParticipant.on('isMutedChanged', () => {
updateMuteStatus(remoteParticipant); // Update the UI based on the mute state of the participant
});
Evento: displayNameChanged
Oggetto displayNameChanged
quando viene aggiornato il nome dell'oggetto RemoteParticipant
.
In che modo l'applicazione può reagire all'evento?
L'applicazione deve aggiornare il nome del partecipante se viene visualizzato nell'interfaccia utente.
Esempio di codice:
remoteParticipant.on('displayNameChanged', () => {
remoteParticipant.nameLabel.innerText = remoteParticipant.displayName;
});
Evento: isSpeakingChanged
Oggetto isSpeakingChanged
quando cambia l'altoparlante dominante in una chiamata.
In che modo l'applicazione può reagire all'evento?
L'interfaccia utente dell'applicazione deve dare priorità alla visualizzazione dell'altoparlante RemotePartipant
dominante.
Esempio di codice:
remoteParticipant.on('isSpeakingChanged', () => {
showAsRemoteSpeaker(remoteParticipant) // Display a speaking icon near the participant
});
Evento: videoStreamsUpdated
Oggetto videoStreamsUpdated
quando un partecipante remoto aggiunge o rimuove un oggetto VideoStream da/verso la chiamata.
In che modo l'applicazione può reagire all'evento?
Se l'applicazione stava elaborando un flusso rimosso. L'applicazione deve arrestare l'elaborazione. Quando viene aggiunto un nuovo flusso, l'applicazione potrebbe voler eseguire il rendering o elaborarlo.
Esempio di codice:
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)
});
});
Evento nell'oggetto AudioEffectsFeature
Evento: effectsStarted
Questo evento si verifica quando l'effetto audio selezionato viene applicato al flusso audio. Ad esempio, quando qualcuno attiva l'eliminazione del rumore, effectsStarted
verrà licenziato.
In che modo l'applicazione può reagire all'evento?
L'applicazione può visualizzare o abilitare un pulsante che consente all'utente di disabilitare l'effetto audio.
Esempio di codice:
audioEffectsFeature.on('effectsStarted', (effects) => {
stopEffectButton.style.visibility = "visible";
});
Evento: effectsStopped
Questo evento si verifica quando l'effetto audio selezionato viene applicato al flusso audio. Ad esempio, quando qualcuno disattiva l'eliminazione del rumore, effectsStopped
verrà licenziato.
In che modo l'applicazione può reagire all'evento?
L'applicazione può visualizzare o abilitare un pulsante che consente all'utente di abilitare l'effetto audio.
Esempio di codice:
audioEffectsFeature.on('effectsStopped', (effects) => {
startEffectButton.style.visibility = "visible";
});
Evento: effectsError
Questo evento si verifica quando si verifica un errore durante l'avvio o l'applicazione di un effetto audio.
In che modo l'applicazione può reagire all'evento?
L'applicazione dovrebbe visualizzare un avviso o un messaggio di errore che indica che l'effetto audio non funziona come previsto.
Esempio di codice:
audioEffectsFeature.on('effectsError', (error) => {
console.log(`Error with the audio effect ${error}`);
alert(`Error with the audio effect`);
});
Installazione dell'SDK
Individuare il file a livello build.gradle
di progetto e aggiungere mavenCentral()
all'elenco dei repository in buildscript
e allprojects
:
buildscript {
repositories {
...
mavenCentral()
...
}
}
allprojects {
repositories {
...
mavenCentral()
...
}
}
Quindi, nel file a livello build.gradle
di modulo aggiungere le righe seguenti alla dependencies
sezione :
dependencies {
...
implementation 'com.azure.android:azure-communication-calling:1.0.0'
...
}
Inizializzare gli oggetti necessari
Per creare un'istanza CallAgent
, è necessario chiamare il metodo createCallAgent
in un'istanza CallClient
. Questa chiamata restituisce in modo asincrono un oggetto istanza CallAgent
.
Il metodo createCallAgent
accetta CommunicationUserCredential
come argomento, che incapsula un token di accesso.
Per accedere a DeviceManager
, è prima necessario creare un'istanza callAgent
. Quindi è possibile usare il metodo CallClient.getDeviceManager
per ottenere 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();
Per impostare nome visualizzato per il chiamante, usare questo metodo alternativo:
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();
Con Android SDK è possibile sottoscrivere la maggior parte delle proprietà e delle raccolte per ricevere una notifica quando i valori cambiano.
Proprietà
Per sottoscrivere property changed
gli eventi:
// 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);
Quando si usano listener di eventi definiti all'interno della stessa classe, associare il listener a una variabile. Passare la variabile come argomento per aggiungere e rimuovere i metodi del listener.
Se si tenta di passare il listener direttamente come argomento, si perderà il riferimento a tale listener. Java crea nuove istanze di questi listener e non fa riferimento a quelle create in precedenza. Verranno ancora spenti correttamente, ma non possono essere rimossi perché non si avrà più un riferimento a loro.
Raccolte
Per sottoscrivere collection updated
gli eventi:
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);
Configurare il sistema
Seguire questa procedura per configurare il sistema.
Creare il progetto Xcode
In Xcode creare un nuovo progetto iOS e selezionare il modello Single View Application. Questo articolo usa il framework SwiftUI, quindi è consigliabile impostare Language su Swift e impostare Interface su SwiftUI.
In questo articolo non verranno creati test. È possibile deselezionare la casella di controllo Includi i test.
Installare il pacchetto e le dipendenze usando CocoaPods
Creare un file Podfile per l'applicazione, come questo esempio:
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 1.0.0' end
Eseguire
pod install
.Aprire
.xcworkspace
con Xcode.
Richiedere l'accesso al microfono
Per accedere al microfono del dispositivo, è necessario aggiornare l'elenco delle proprietà informazioni dell'app usando NSMicrophoneUsageDescription
. Impostare il valore associato su una stringa inclusa nella finestra di dialogo usata dal sistema per richiedere l'accesso dall'utente.
Fare clic con il pulsante destro del mouse sulla voce info.plist dell'albero del progetto, quindi selezionare Apri come>codice sorgente. Aggiungere le righe seguenti nella sezione di primo livello <dict>
e quindi salvare il file.
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
Configurare il framework dell'app
Aprire il file del ContentView.swift
progetto. Aggiungere una dichiarazione import
all'inizio del file per importare la libreria AzureCommunicationCalling
. Inoltre, importare AVFoundation
: È necessario per le richieste di autorizzazione audio nel codice.
import AzureCommunicationCalling
import AVFoundation
Inizializzare CallAgent
Per creare un'istanza CallAgent
da CallClient
, è necessario usare un metodo callClient.createCallAgent
che restituisce in modo asincrono un oggetto CallAgent
dopo l'inizializzazione.
Per creare un client di chiamata, passare un oggetto 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)
}
Passare l'oggetto CommunicationTokenCredential
creato in CallClient
e impostare il nome visualizzato:
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")
}
})
Con iOS SDK è possibile sottoscrivere la maggior parte delle proprietà e delle raccolte per ricevere una notifica quando i valori cambiano.
Proprietà
Per sottoscrivere property changed
gli eventi, usare il codice seguente.
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
Raccolte
Per sottoscrivere collection updated
gli eventi, usare il codice seguente.
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