Administración de llamadas
Aprenda a administrar llamadas con los SDK de Azure Communication Services. Aquí se va a aprender a realizar llamadas y a administrar sus participantes y sus propiedades.
Requisitos previos
- Una cuenta de Azure con una suscripción activa. Cree una cuenta gratuita.
- Un recurso de Communication Services implementado. Cree un recurso de Communication Services.
User Access Token
para habilitar el cliente de llamada. Para más información sobre cómo obtenerUser Access Token
- Opcional: Realice la guía Inicio rápido: adición de la llamada de voz a su aplicación.
Instalación del SDK
Use el comando npm install
para instalar los SDK comunes y de llamada de Azure Communication Services para JavaScript:
npm install @azure/communication-common --save
npm install @azure/communication-calling --save
Inicialización de los objetos necesarios
Se requiere una instancia de CallClient
para la mayoría de las operaciones de llamada. Al crear una nueva instancia de CallClient
, puede configurarla con opciones personalizadas, como una instancia de Logger
.
Con la instancia de CallClient
, puede crear una instancia de CallAgent
llamando al createCallAgent
. Este método devuelve un objeto de instancia CallAgent
de manera asincrónica.
El método createCallAgent
utiliza CommunicationTokenCredential
como argumento. Acepta un token de acceso de usuario.
Puede usar el método getDeviceManager
en la instancia de CallClient
para acceder a deviceManager
.
const { CallClient } = require('@azure/communication-calling');
const { AzureCommunicationTokenCredential} = require('@azure/communication-common');
const { AzureLogger, setLogLevel } = require("@azure/logger");
// Set the logger's log level
setLogLevel('verbose');
// Redirect log output to console, file, buffer, REST API, or whatever location you want
AzureLogger.log = (...args) => {
console.log(...args); // Redirect log output to console
};
const userToken = '<USER_TOKEN>';
callClient = new CallClient(options);
const tokenCredential = new AzureCommunicationTokenCredential(userToken);
const callAgent = await callClient.createCallAgent(tokenCredential, {displayName: 'optional Azure Communication Services user name'});
const deviceManager = await callClient.getDeviceManager()
Cuál es la mejor forma de administrar la conectividad del SDK en la infraestructura de Microsoft
La instancia de Call Agent
le ayuda a administrar llamadas (para unirse o iniciar llamadas). Para trabajar con el SDK de llamadas, debe conectarse a la infraestructura de Microsoft para obtener notificaciones de llamadas entrantes y coordinar otros detalles de la llamada. Call Agent
tiene dos posibles estados:
Conectado: un valor connectionStatue Call Agent
con estado Connected
significa que el SDK de cliente está conectado y es capaz de recibir notificaciones de la infraestructura de Microsoft.
Desconectado: un valor connectionStatue Call Agent
con estado Disconnected
indica que hay un problema que impide que el SDK se conecte correctamente. Call Agent
se debe volver a crear.
invalidToken
: si un token ha expirado o no es válido, la instancia deCall Agent
se desconecta con este error.connectionIssue
: si hay un problema cuando el cliente se conecta a la infraestructura de Microsoft, después de muchos reintentos,Call Agent
expone el errorconnectionIssue
.
Para comprobar si el Call Agent
local está conectado a la infraestructura de Microsoft, inspeccione el valor actual de la propiedad connectionState
. Durante una llamada activa, puede escuchar el evento connectionStateChanged
para determinar si Call Agent
cambia de Conectado a estado Desconectado.
const connectionState = callAgentInstance.connectionState;
console.log(connectionState); // it may return either of 'Connected' | 'Disconnected'
const connectionStateCallback = (args) => {
console.log(args); // it will return an object with oldState and newState, each of having a value of either of 'Connected' | 'Disconnected'
// it will also return reason, either of 'invalidToken' | 'connectionIssue'
}
callAgentInstance.on('connectionStateChanged', connectionStateCallback);
Realización de una llamada
Para crear e iniciar una llamada, use una de las API en callAgent
y proporcione un usuario que creó a través del SDK de identidad de Communication Services.
La creación y el inicio de la llamada son sincrónicos. La instancia call
le permite suscribirse a eventos de llamada.
Realización de una llamada 1:n a un usuario o RTC
Para llamar a otro usuario de Communication Services, invoque el método startCall
en callAgent
y pase la instancia de CommunicationUserIdentifier
que ha creado con la biblioteca de administración de Communication Services.
Para una llamada "1:1" a un usuario, utilice el código siguiente:
const userCallee = { communicationUserId: '<ACS_USER_ID>' }
const oneToOneCall = callAgent.startCall([userCallee]);
Para realizar una llamada a una red telefónica conmutada (RTC) pública, use el método startCall
en callAgent
y pase el PhoneNumberIdentifier
del destinatario. El recurso de Communication Services debe estar configurado para permitir llamadas de RTC.
Cuando llame a un número de RTC, debe especificar su identificador alternativo de autor de llamada. Un identificador del autor de llamada alternativo es un número de teléfono (basado en el estándar E.164), que identifica al autor de llamada en una llamada RTC. Es el número de teléfono que el destinatario de la llamada ve en una llamada entrante.
Nota:
Consulte los detalles de la oferta de llamadas RTC. Para acceder al programa de versión preliminar, suscríbase al programa de usuarios pioneros.
Para una llamada 1:1 a un número de RTC, utilice el código siguiente:
const pstnCallee = { phoneNumber: '<ACS_USER_ID>' }
const alternateCallerId = {phoneNumber: '<ALTERNATE_CALLER_ID>'};
const oneToOneCall = callAgent.startCall([pstnCallee], { alternateCallerId });
Para una llamada 1:n a un usuario y a un número RTC, utilice el código siguiente:
const userCallee = { communicationUserId: '<ACS_USER_ID>' }
const pstnCallee = { phoneNumber: '<PHONE_NUMBER>'};
const alternateCallerId = {phoneNumber: '<ALTERNATE_CALLER_ID>'};
const groupCall = callAgent.startCall([userCallee, pstnCallee], { alternateCallerId });
Unión a una llamada de una sala
Para unirse a una llamada a room
, puede crear una instancia de un objeto de contexto con la propiedad roomId
como identificador de room
. Para unirse a la llamada, use el método join
y pase la instancia de contexto.
const context = { roomId: '<RoomId>' }
const call = callAgent.join(context);
Un objeto room
ofrece a los desarrolladores de aplicaciones un mejor control sobre quién puede unirse a una llamada, cuándo se reúnen y cómo colaboran. Para obtener más información sobre rooms
, puede leer la documentación conceptual o seguir la guía de inicio rápido.
Unirse a una llamada grupal
Nota:
El parámetro groupId
se considera metadatos del sistema y Microsoft puede usarlo para las operaciones necesarias para ejecutar el sistema. No incluya datos personales en el valor groupId
. Microsoft no trata este parámetro como datos personales y su contenido puede ser visible para los empleados de Microsoft o almacenarse a largo plazo.
El parámetro groupId
requiere que los datos estén en formato GUID. Se recomienda usar GUID generados de forma aleatoria que no se consideran datos personales en los sistemas.
Para iniciar una llamada grupal nueva o unirse a una en curso, use el método join
y pase un objeto con una propiedad groupId
. El valor groupId
debe ser un GUID.
const context = { groupId: '<GUID>'};
const call = callAgent.join(context);
Recibir llamadas entrantes
La instancia de callAgent
emite un evento incomingCall
cuando la identidad que ha iniciado sesión recibe una llamada entrante. Para escuchar este evento, suscríbase mediante una de estas opciones:
const incomingCallHandler = async (args: { incomingCall: IncomingCall }) => {
const incomingCall = args.incomingCall;
// Get incoming call ID
var incomingCallId = incomingCall.id
// Get information about this Call. This API is provided as a preview for developers
// and may change based on feedback that we receive. Do not use this API in a production environment.
// To use this api please use 'beta' release of Azure Communication Services Calling Web SDK
var callInfo = incomingCall.info;
// Get information about caller
var callerInfo = incomingCall.callerInfo
// Accept the call
var call = await incomingCall.accept();
// Reject the call
incomingCall.reject();
// Subscribe to callEnded event and get the call end reason
incomingCall.on('callEnded', args => {
console.log(args.callEndReason);
});
// callEndReason is also a property of IncomingCall
var callEndReason = incomingCall.callEndReason;
};
callAgentInstance.on('incomingCall', incomingCallHandler);
El evento incomingCall
incluye una instancia de incomingCall
que puede aceptar o rechazar.
El SDK de llamadas de comunicación de Azure genera un diagnóstico de llamadas cameraStartFailed: true si la cámara no está disponible al iniciar, aceptar o unirse a una llamada con vídeo habilitado. En este caso, la llamada comienza con el vídeo desactivado. Es posible que la cámara no esté disponible porque está siendo utilizada por otro proceso o porque está deshabilitada en el sistema operativo.
Suspensión y reanudación de la llamada
Nota:
En un momento dado, solo debe haber 1 llamada activa (en estado Connected
, con medios activos). Todas las demás llamadas deben ser puestas en espera por un usuario, o de forma programada por la aplicación. Esto es común en escenarios como los centros de contacto, donde un usuario puede necesitar manejar múltiples llamadas salientes y entrantes, todas las llamadas inactivas deben ser puestas en espera, y el usuario debe interactuar con otros solo en la llamada activa
Para retener o reanudar la llamada, puede utilizar las API asincrónicas hold
y resume
:
Para retener la llamada
await call.hold();
Cuando la API hold
se resuelve, el estado de la llamada se establece en LocalHold
. En una llamada 1:1, el otro participante también está en espera y el estado de la llamada desde la perspectiva de ese participante se establece en "RemoteHold". Más adelante, el otro participante podría poner su llamada en espera, lo que daría lugar a un cambio de estado a LocalHold
.
En una llamada o reunión de grupo: hold
es una operación local, no mantiene la llamada a otros participantes de la llamada.
Para reanudar esa llamada, todos los usuarios que la iniciaron deben reanudarla.
Para reanudar la llamada desde la suspensión:
await call.resume();
Cuando se resuelve la API de resume
, el estado de llamada se establecerá de nuevo en Connected
.
Activar y desactivar el audio de una llamada
Para silenciar o reactivar el sonido del punto de conexión local, puede usar las API asincrónicas mute
y unmute
:
//mute local device (microphone / sent audio)
await call.mute();
//unmute local device (microphone / sent audio)
await call.unmute();
Silenciar y reactivar el audio entrante
Silenciar el audio entrante hace que el volumen de llamada se establezca en 0. Para silenciar o reactivar el audio entrante, puede usar las API asincrónicas muteIncomingAudio
y unmuteIncomingAudio
:
//mute local device (speaker)
await call.muteIncomingAudio();
//unmute local device (speaker)
await call.unmuteIncomingAudio();
Cuando se silencia el audio entrante, el SDK del cliente participante seguirá recibiendo el audio de llamada (audio del participante remoto). El audio de llamada no se escuchará en el hablante y el participante no podrá escuchar hasta que se llame a "call.unmuteIncomingAudio()". Sin embargo, podemos aplicar filtros en el audio de la llamada y reproducir el audio filtrado.
Administración de participantes remotos
Todos los participantes remotos se detallan en el objeto RemoteParticipant
y están disponibles a través de la colección remoteParticipants
en una instancia de llamada. remoteParticipants
es accesible desde una instancia de Call
.
Enumeración de los participantes en una llamada
La colección remoteParticipants
devuelve una lista de los participantes remotos en una llamada:
call.remoteParticipants; // [remoteParticipant, remoteParticipant....]
Incorporación de un participante a una llamada
Para agregar un participante (ya sea un usuario o un número de teléfono) a una llamada, puede usar la API addParticipant
. Proporcione uno de los tipos de Identifier
. Devuelve la instancia de remoteParticipant
de forma sincrónica. El evento remoteParticipantsUpdated
de Call se genera cuando un participante se agrega correctamente a la llamada.
const userIdentifier = { communicationUserId: '<ACS_USER_ID>' };
const pstnIdentifier = { phoneNumber: '<PHONE_NUMBER>' }
const remoteParticipant = call.addParticipant(userIdentifier);
const alternateCallerId = { phoneNumber: '<ALTERNATE_CALLER_ID>' };
const remoteParticipant = call.addParticipant(pstnIdentifier, { alternateCallerId });
Eliminación de un participante de una llamada
Para quitar un participante (ya sea un usuario o un número de teléfono) de una llamada, puede invocar removeParticipant
. Tiene que pasar uno de los tipos de Identifier
. Este método se resolverá de manera asincrónica una vez que el participante se quite de la llamada. El participante también se quitará de la colección remoteParticipants
.
const userIdentifier = { communicationUserId: '<ACS_USER_ID>' };
const pstnIdentifier = { phoneNumber: '<PHONE_NUMBER>' }
await call.removeParticipant(userIdentifier);
await call.removeParticipant(pstnIdentifier);
Acceso a las propiedades de los participantes remotos
Los participantes remotos tienen un conjunto de propiedades y colecciones asociadas:
CommunicationIdentifier
: obtenga el identificador de este participante remoto. "Identity" es uno de los tipos deCommunicationIdentifier
:
const identifier = remoteParticipant.identifier;
Puede ser uno de los siguientes tipos de
CommunicationIdentifier
:{ communicationUserId: '<ACS_USER_ID'> }
: objeto que representa al usuario de Azure Communication Services.{ phoneNumber: '<E.164>' }
: objeto que representa el número de teléfono en formato E.164.{ microsoftTeamsUserId: '<TEAMS_USER_ID>', isAnonymous?: boolean; cloud?: "public" | "dod" | "gcch" }
: objeto que representa al usuario de Teams.{ id: string }
: objeto que representa el identificador que no se ajusta a ninguno de los otros tipos de identificadores.
state
: obtenga el estado de este participante remoto.
const state = remoteParticipant.state;
El estado puede ser:
Idle
: estado inicial.Connecting
: estado de transición mientras el participante se conecta a la llamada.Ringing
: el participante está sonando.Connected
: el participante se conecta a la llamada.Hold
: el participante está en espera.EarlyMedia
: anuncio que se reproduce antes de que un participante se conecte a la llamada.InLobby
: indica que el participante remoto está en sala de espera.Disconnected
: estado final. El participante se desconecta de la llamada. Si el participante remoto pierde la conectividad de red, su estado cambia aDisconnected
tras dos minutos.
callEndReason
: para saber por qué el participante dejó la llamada, compruebe la propiedadcallEndReason
:const callEndReason = remoteParticipant.callEndReason; const callEndReasonCode = callEndReason.code // (number) code associated with the reason const callEndReasonSubCode = callEndReason.subCode // (number) subCode associated with the reason
Nota:
- Esta propiedad solo se establece cuando al agregar un participante remoto a través de la API Call.addParticipant(), el participante remoto no acepta, por ejemplo.
- En el escenario en el que el Usuario B echa al Usuario C, desde la perspectiva del Usuario A, el Usuario A no verá que esta marca se establezca para el Usuario C. En otras palabras, el Usuario A no verá en ningún caso que la propiedad callEndReason se establezca para el Usuario C.
Estado
isMuted
: para averiguar si un participante remoto está silenciado, compruebe la propiedadisMuted
. DevuelveBoolean
.const isMuted = remoteParticipant.isMuted;
Estado
isSpeaking
: para averiguar si un participante remoto está hablando, compruebe la propiedadisSpeaking
. DevuelveBoolean
.const isSpeaking = remoteParticipant.isSpeaking;
videoStreams
: para revisar todas las secuencias de vídeo que un participante determinado envía en esta llamada, compruebe la colecciónvideoStreams
: Contiene objetosRemoteVideoStream
.const videoStreams = remoteParticipant.videoStreams; // [RemoteVideoStream, ...]
displayName
: para obtener el nombre para mostrar de este participante remoto, revise la propiedaddisplayName
que devuelve la cadena.const displayName = remoteParticipant.displayName;
endpointDetails
: obtenga los detalles de todos los puntos de conexión de este participante remotoconst endpointDetails: EndpointDetails[] = remoteParticipant.endpointDetails;
Nota: Un participante remoto podría estar en la llamada desde muchos puntos de conexión y cada punto de conexión tendrá su propio
participantId
único.participantId
es diferente del identificador sin procesar de RemoteParticipant.identifier.
Silenciar a otros participantes
Nota:
Para usar esta API, use el SDK web de llamadas de Azure Communication Services, versión 1.26.1 o posterior.
Para silenciar a todos los demás participantes o silenciar a un participante específico que está conectado a una llamada, puede usar las API asincrónicas muteAllRemoteParticipants
en la llamada y mute
en el participante remoto. El evento mutedByOthers
de la llamada se genera cuando otros usuarios han silenciado al participante local.
Nota: No se admiten los escenarios para silenciar a los participantes RTC (con número de teléfono) o a los participantes de llamadas 1:1.
//mute all participants except yourself
await call.muteAllRemoteParticipants();
//mute a specific participant
await call.remoteParticipants[0].mute();
Comprobación de las propiedades de llamada
Obtenga el identificador único (cadena) de una llamada:
const callId: string = call.id;
Obtenga el identificador del participante local:
const participantId: string = call.info.participantId;
Nota: Una identidad de Azure Communication Services puede usar el SDK de llamada web en muchos puntos de conexión y cada punto de conexión tendrá su propio participantId
único. participantId
es diferente del identificador sin procesar de identidad de Azure Communication Services.
Recupere el identificador de subproceso si se une a una reunión de Teams:
const threadId: string | undefined = call.info.threadId;
Obtenga información acerca de la llamada:
const callInfo = call.info;
Para más información sobre los demás participantes de la llamada, revise la colección remoteParticipants
de la instancia "call".
const remoteParticipants = call.remoteParticipants;
Identifique al autor de la llamada de una llamada entrante:
const callerIdentity = call.callerInfo.identifier;
identifier
es uno de los tipos de CommunicationIdentifier
.
Obtenga el estado de una llamada:
const callState = call.state;
Esto devuelve una cadena que representa el estado actual de una llamada:
None
: estado inicial de la llamada.Connecting
: estado de transición inicial cuando se realiza o acepta la llamada.Ringing
: en el caso de una llamada saliente, indica que se está llamando a los participantes remotos. EsIncoming
en su lado.EarlyMedia
: indica un estado en el que se reproduce un anuncio antes de conectar la llamada.Connected
: indica que la llamada está conectada.LocalHold
: indica que un participante local ha puesto en espera la llamada. No hay flujo de medios entre el punto de conexión local y los participantes remotos.RemoteHold
: indica que un participante remoto ha puesto en espera la llamada. No hay flujo de medios entre el punto de conexión local y los participantes remotos.InLobby
: indica que el usuario está en sala de espera.Disconnecting
: estado de la transición antes de que la llamada pase a un estadoDisconnected
.Disconnected
: estado final de la llamada. Si se pierde la conexión de red, el estado cambia aDisconnected
después de dos minutos.
Averigüe por qué finalizó una llamada mediante la inspección de la propiedad callEndReason
:
const callEndReason = call.callEndReason;
const callEndReasonMessage = callEndReason.message // (string) user friendly message
const callEndReasonCode = callEndReason.code // (number) code associated with the reason
const callEndReasonSubCode = callEndReason.subCode // (number) subCode associated with the reason
Obtenga información sobre si la llamada actual es entrante o saliente mediante la inspección de la propiedad direction
. Devuelve CallDirection
.
const isIncoming = call.direction == 'Incoming';
const isOutgoing = call.direction == 'Outgoing';
Inspeccione las secuencias de vídeo activas y las secuencias de uso compartido de pantalla activas comprobando la colección localVideoStreams
. La API de localVideoStreams
devuelve objetos LocalVideoStream
o tipo Video
, ScreenSharing
o RawMedia
.
const localVideoStreams = call.localVideoStreams;
Compruebe si el micrófono actual está silenciado. Devuelve Boolean
.
const muted = call.isMuted;
Compruebe si el audio entrante actual (altavoz) está silenciado. Devuelve Boolean
.
const incomingAudioMuted = call.isIncomingAudioMuted;
Compruebe si el vídeo está activado. Devuelve Boolean
.
const isLocalVideoStarted = call.isLocalVideoStarted;
Compruebe si el uso compartido de pantalla está activado. Devuelve Boolean
.
const isScreenSharingOn = call.isScreenSharingOn;
Instalación del SDK
Busque el archivo build.gradle
de nivel de proyecto y agregue mavenCentral()
a la lista de repositorios en buildscript
y allprojects
:
buildscript {
repositories {
...
mavenCentral()
...
}
}
allprojects {
repositories {
...
mavenCentral()
...
}
}
Luego, en el archivo build.gradle
de nivel de módulo, agregue las siguientes líneas a la sección dependencies
:
dependencies {
...
implementation 'com.azure.android:azure-communication-calling:1.0.0'
...
}
Inicialización de los objetos necesarios
Para crear una instancia de CallAgent
, debe llamar al método createCallAgent
en una instancia de CallClient
. Esta llamada devuelve un objeto de instancia de CallAgent
de manera asincrónica.
El método createCallAgent
toma CommunicationUserCredential
como argumento, que encapsula un token de acceso.
Para acceder a DeviceManager
, primero debe crear una instancia de callAgent
. A continuación, puede usar el método CallClient.getDeviceManager
para obtener 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();
Para establecer un nombre para mostrar para el autor de la llamada, use este método 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();
Realización de una llamada
Para crear e iniciar una llamada, es necesario llamar al método CallAgent.startCall()
y proporcionar el Identifier
de los destinatarios.
Para unirse a una llamada grupal, debe llamar al método CallAgent.join()
y proporcionar el groupId. Los identificadores de grupo deben tener el formato GUID o UUID.
La creación y el inicio de la llamada son sincrónicos. La instancia de llamada le permite suscribirse a todos los eventos de la llamada.
Realización de una llamada 1:1 a un usuario
Para realizar una llamada a otro usuario de Communication Services, invoque el método call
en callAgent
y pase un objeto con la clave communicationUserId
.
StartCallOptions startCallOptions = new StartCallOptions();
Context appContext = this.getApplicationContext();
CommunicationUserIdentifier acsUserId = new CommunicationUserIdentifier(<USER_ID>);
CommunicationUserIdentifier participants[] = new CommunicationUserIdentifier[]{ acsUserId };
call oneToOneCall = callAgent.startCall(appContext, participants, startCallOptions);
Realice una llamada de uno a varios con usuarios y RTC
Nota:
Consulte los detalles de la oferta de llamadas RTC. Para acceder al programa de versión preliminar, suscríbase al programa de usuarios pioneros.
Para realizar una llamada 1:n a un usuario y un número de RTC, debe especificar el número de teléfono del destinatario. El recurso de Communication Services debe estar configurado para permitir llamadas RTC:
CommunicationUserIdentifier acsUser1 = new CommunicationUserIdentifier(<USER_ID>);
PhoneNumberIdentifier acsUser2 = new PhoneNumberIdentifier("<PHONE_NUMBER>");
CommunicationIdentifier participants[] = new CommunicationIdentifier[]{ acsUser1, acsUser2 };
StartCallOptions startCallOptions = new StartCallOptions();
Context appContext = this.getApplicationContext();
Call groupCall = callAgent.startCall(participants, startCallOptions);
Aceptar una llamada
Para aceptar una llamada, llame al método "accept" en un objeto de llamada.
Context appContext = this.getApplicationContext();
IncomingCall incomingCall = retrieveIncomingCall();
Call call = incomingCall.accept(context).get();
Para aceptar una llamada con la cámara de vídeo activada:
Context appContext = this.getApplicationContext();
IncomingCall incomingCall = retrieveIncomingCall();
AcceptCallOptions acceptCallOptions = new AcceptCallOptions();
VideoDeviceInfo desiredCamera = callClient.getDeviceManager().get().getCameraList().get(0);
acceptCallOptions.setVideoOptions(new VideoOptions(new LocalVideoStream(desiredCamera, appContext)));
Call call = incomingCall.accept(context, acceptCallOptions).get();
La llamada entrante se puede obtener mediante la suscripción al evento onIncomingCall
en el objeto callAgent
:
// Assuming "callAgent" is an instance property obtained by calling the 'createCallAgent' method on CallClient instance
public Call retrieveIncomingCall() {
IncomingCall incomingCall;
callAgent.addOnIncomingCallListener(new IncomingCallListener() {
void onIncomingCall(IncomingCall inboundCall) {
// Look for incoming call
incomingCall = inboundCall;
}
});
return incomingCall;
}
Unión a una llamada de una sala
Use CallAgent
y RoomCallLocator
para unirse a una llamada de sala especificando roomId
. El método CallAgent.join
devolverá un objeto Call
:
val roomCallLocator = RoomCallLocator(roomId)
call = callAgent.join(applicationContext, roomCallLocator, joinCallOptions)
Un objeto room
ofrece a los desarrolladores de aplicaciones un mejor control sobre quién puede unirse a una llamada, cuándo se reúnen y cómo colaboran. Para obtener más información sobre rooms
, puede leer la documentación conceptual o seguir la guía de inicio rápido.
Unirse a una llamada grupal
Para iniciar una llamada grupal nueva o unirse a una en curso, debe llamar al método "join" y pasar un objeto con una propiedad groupId
. El valor debe ser un GUID.
Context appContext = this.getApplicationContext();
GroupCallLocator groupCallLocator = new GroupCallLocator("<GUID>");
JoinCallOptions joinCallOptions = new JoinCallOptions();
call = callAgent.join(context, groupCallLocator, joinCallOptions);
Propiedades de llamada
Obtenga el id. único de esta llamada:
String callId = call.getId();
Para información sobre los demás participantes de la llamada, revise la colección remoteParticipant
de la instancia de call
:
List<RemoteParticipant> remoteParticipants = call.getRemoteParticipants();
La identidad del autor de la llamada si la llamada es entrante:
CommunicationIdentifier callerId = call.getCallerInfo().getIdentifier();
Obtenga el estado de la llamada:
CallState callState = call.getState();
Devuelve una cadena que representa el estado actual de una llamada:
- "NONE": estado inicial de la llamada.
- "EARLY_MEDIA": indica un estado en el que se reproduce un anuncio antes de conectar la llamada.
- "CONNECTING": estado de transición inicial una vez que se realiza o acepta la llamada.
- "RINGING": en el caso de una llamada saliente, indica que se está llamando a los participantes remotos.
- "CONNECTED": la llamada está conectada.
- "LOCAL_HOLD": el participante local ha puesto la llamada en espera; no fluye ningún elemento multimedia entre el punto de conexión local y los participantes remotos.
- "REMOTE_HOLD": un participante remoto ha puesto la llamada en espera; no fluye ningún elemento multimedia entre el punto de conexión local y los participantes remotos.
- "DISCONNECTING": estado de transición antes de que la llamada pase al estado "Desconectado".
- "DISCONNECTED": estado final de la llamada.
- "IN_LOBBY": en busca de interoperabilidad de una reunión de Teams.
Para saber por qué ha finalizado una llamada, revise la propiedad callEndReason
. Contiene código o subcódigo:
CallEndReason callEndReason = call.getCallEndReason();
int code = callEndReason.getCode();
int subCode = callEndReason.getSubCode();
Para ver si la llamada actual es una llamada entrante o saliente, revise la propiedad callDirection
:
CallDirection callDirection = call.getCallDirection();
// callDirection == CallDirection.INCOMING for incoming call
// callDirection == CallDirection.OUTGOING for outgoing call
Para ver si el micrófono actual está silenciado, revise la propiedad muted
:
boolean muted = call.isMuted();
Para revisar las secuencias de vídeo activas, compruebe la colección localVideoStreams
:
List<LocalVideoStream> localVideoStreams = call.getLocalVideoStreams();
Silenciar y Reactivar audio
Para silenciar o reactivar el sonido del punto de conexión local, puede usar las API asincrónicas mute
y unmute
:
Context appContext = this.getApplicationContext();
call.mute(appContext).get();
call.unmute(appContext).get();
Cambio del volumen de la llamada
Mientras se encuentra en una llamada, las teclas de volumen de hardware en el teléfono deben permitir al usuario cambiar el volumen de llamada.
Esto se consigue mediante el método setVolumeControlStream
con el tipo de secuencia AudioManager.STREAM_VOICE_CALL
en la actividad donde se realiza la llamada.
Esto permite que las teclas de volumen de hardware cambien el volumen de la llamada (que se indica mediante un icono de teléfono o algo similar en el control deslizante del volumen) e impide que se cambie el volumen de otros perfiles de sonido, como alarmas, multimedia o el volumen de todo el sistema. Para obtener más información, puede consultar Cómo controlar cambios en la salida de audio | Desarrolladores de Android.
@Override
protected void onCreate(Bundle savedInstanceState) {
...
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
}
Administración de participantes remotos
El tipo RemoteParticipant
representa a todos los participantes remotos y estos están disponibles a través de la colección remoteParticipants
en una instancia de llamada.
Lista de los participantes en una llamada
La colección remoteParticipants
devuelve una lista de los participantes remotos en una llamada determinada:
List<RemoteParticipant> remoteParticipants = call.getRemoteParticipants(); // [remoteParticipant, remoteParticipant....]
Incorporación de un participante a una llamada
Para agregar un participante a una llamada (ya sea un usuario o un número de teléfono), puede invocar addParticipant
.
Esto devolverá de manera sincrónica la instancia del participante remoto.
const acsUser = new CommunicationUserIdentifier("<acs user id>");
const acsPhone = new PhoneNumberIdentifier("<phone number>");
RemoteParticipant remoteParticipant1 = call.addParticipant(acsUser);
AddPhoneNumberOptions addPhoneNumberOptions = new AddPhoneNumberOptions(new PhoneNumberIdentifier("<alternate phone number>"));
RemoteParticipant remoteParticipant2 = call.addParticipant(acsPhone, addPhoneNumberOptions);
Eliminación del participante de una llamada
Para quitar un participante de una llamada (ya sea un usuario o un número de teléfono), puede invocar removeParticipant
.
Esto se resolverá de manera asincrónica una vez que el participante se quite de la llamada.
El participante también se quitará de la colección remoteParticipants
.
RemoteParticipant acsUserRemoteParticipant = call.getParticipants().get(0);
RemoteParticipant acsPhoneRemoteParticipant = call.getParticipants().get(1);
call.removeParticipant(acsUserRemoteParticipant).get();
call.removeParticipant(acsPhoneRemoteParticipant).get();
Propiedades de los participantes remotos
Todo participante remoto especificado tiene un conjunto de propiedades y colecciones asociadas:
Obtenga el identificador de este participante remoto. "Identity" es uno de los tipos de "Identifier":
CommunicationIdentifier participantIdentifier = remoteParticipant.getIdentifier();
Obtenga el estado de este participante remoto.
ParticipantState state = remoteParticipant.getState();
El estado puede ser uno de los siguientes:
"IDLE": estado inicial.
"EARLY_MEDIA": se reproduce un anuncio antes de que el participante se conecte a la llamada.
"RINGING": la llamada del participante está sonando.
"CONNECTING": estado de transición mientras el participante se conecta a la llamada.
"CONNECTED": el participante se conecta a la llamada.
"HOLD": el participante está en espera.
"IN_LOBBY": el participante está esperando que se admita en la sala. Actualmente solo se usa en el escenario de interoperabilidad de Teams
"DISCONNECTED": estado final; el participante se desconecta de la llamada.
Para saber por qué el participante dejó la llamada, revise la propiedad
callEndReason
:CallEndReason callEndReason = remoteParticipant.getCallEndReason();
Para comprobar si este participante remoto está silenciado o no, revise la propiedad
isMuted
:boolean isParticipantMuted = remoteParticipant.isMuted();
Para comprobar si este participante remoto está hablando o no, revise la propiedad
isSpeaking
:boolean isParticipantSpeaking = remoteParticipant.isSpeaking();
Para revisar todas las secuencias de vídeo que un participante determinado envía en esta llamada, compruebe la colección
videoStreams
:List<RemoteVideoStream> videoStreams = remoteParticipant.getVideoStreams(); // [RemoteVideoStream, RemoteVideoStream, ...]
Silenciar a otros participantes
Nota:
Para usar esta API, use la versión 2.11.0 o posterior del SDK de Azure Communication Services para Llamadas a Android.
Para silenciar a todos los demás participantes de una llamada, use la API muteAllRemoteParticipants
en la llamada.
call.muteAllRemoteParticipants();
Para silenciar a un participante remoto específico, use la API mute
en un participante remoto determinado.
remoteParticipant.mute();
Para notificar al participante local que otros usuarios han silenciado, suscríbase al evento onMutedByOthers
.
Uso de los servicios en primer plano
En los casos en los que quiera ejecutar una tarea visible del usuario incluso cuando la aplicación esté en segundo plano, puede usar los servicios en primer plano.
Por ejemplo, con los servicios en primer plano, puede mantener una notificación visible para el usuario cuando la aplicación tiene una llamada activa. De este modo, incluso si el usuario va a la pantalla principal o quita la aplicación de la pantalla de aplicaciones recientes, la llamada seguirá estando activa.
Si no usa un servicio en primer plano mientras está en una llamada, si navega a la pantalla principal puede mantener activa la llamada, pero al quitar la aplicación de la pantalla de aplicaciones recientes puede significar que se interrumpe la llamada si el SO Android elimina el proceso de la aplicación.
Debe iniciar el servicio en primer plano al iniciar una llamada o unirse a una, por ejemplo:
call = callAgent.startCall(context, participants, options);
startService(yourForegroundServiceIntent);
Y debe detener este servicio al terminar la llamada o cuando el estado de la llamada sea Desconectado, por ejemplo:
call.hangUp(new HangUpOptions()).get();
stopService(yourForegroundServiceIntent);
Notas sobre el uso de los servicios en primer plano
Tenga en cuenta que en escenarios como detener un servicio en primer plano que ya está en ejecución cuando la aplicación se quita de la lista de aplicaciones recientes, se quitará la notificación visible para el usuario y el sistema operativo Android puede mantener activo el proceso de la aplicación durante un período de tiempo adicional, lo que significa que la llamada puede seguir activa durante este período.
Por ejemplo, si la aplicación detiene el servicio en primer plano en el método onTaskRemoved
del servicio, la aplicación puede iniciar o detener el audio y el vídeo según el ciclo de vida de la actividad, como detener el audio y vídeo cuando se destruye la actividad con la invalidación del método onDestroy
.
Configuración del sistema
Siga estos pasos para configurar el sistema.
Creación del proyecto de Xcode
En Xcode, cree un nuevo proyecto de iOS y seleccione la plantilla Aplicación de una vista. En este artículo se usa el marco SwiftUI, por lo que debe establecer el Lenguaje en Swift y la Interfaz en SwiftUI.
No va a crear pruebas en este artículo. Puede desactivar la casilla Incluir pruebas.
Instalación del paquete y las dependencias mediante CocoaPods
Cree un Podfile para la aplicación, como en este ejemplo:
platform :ios, '13.0' use_frameworks! target 'AzureCommunicationCallingSample' do pod 'AzureCommunicationCalling', '~> 1.0.0' end
Ejecute
pod install
.Abra
.xcworkspace
mediante Xcode.
Solicitud de acceso al micrófono
Para acceder al micrófono del dispositivo, debe actualizar la lista de propiedades de información de la aplicación mediante NSMicrophoneUsageDescription
. Establezca el valor asociado en una cadena que se incluye en el cuadro de diálogo empleado por el sistema para solicitar acceso al usuario.
Haga clic con el botón derecho en la entrada Info.plist del árbol del proyecto y seleccione Abrir como>Código fuente. Agregue las líneas siguientes a la sección <dict>
de nivel superior y guarde el archivo.
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for VOIP calling.</string>
Instalación del marco de la aplicación
Abra el archivo ContentView.swift
del proyecto. Agregue una declaración import
a la parte superior del archivo para importar la biblioteca AzureCommunicationCalling
. Además, importe AVFoundation
. Lo necesitará para las solicitudes de permiso de audio en el código.
import AzureCommunicationCalling
import AVFoundation
Inicialización de CallAgent
Para crear una instancia de CallAgent
a partir de CallClient
, debe usar el método callClient.createCallAgent
, que devuelve de manera asincrónica un objeto CallAgent
después de que se inicializa.
Para crear un cliente de llamada, pase un objeto 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)
}
Pase el objeto CommunicationTokenCredential
que ha creado a CallClient
y establezca el nombre para mostrar:
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")
}
})
Nota:
Cuando la aplicación implementa delegados de eventos, tiene que mantener una referencia segura a los objetos que requieren suscripciones a eventos. Por ejemplo, cuando se devuelve un objeto RemoteParticipant
al invocar el método call.addParticipant
y la aplicación establece que el delegado escuche en RemoteParticipantDelegate
, la aplicación debe contener una referencia segura al objeto RemoteParticipant
. De lo contrario, si se recopila este objeto, el delegado generará una excepción irrecuperable cuando el SDK de llamadas intente invocar al objeto.
Realización de una llamada saliente
Para crear e iniciar una llamada, debe llamar a una de las API en CallAgent
y proporcionar la identidad de Communication Services de un usuario que haya aprovisionado mediante el SDK de administración de Communication Services.
La creación y el inicio de la llamada son sincrónicos. Recibirá una instancia de la llamada que le permitirá suscribirse a todos los eventos de la llamada.
Realice una llamada de uno a uno a un usuario o una llamada de uno a varios con usuarios y RTC
let callees = [CommunicationUser(identifier: 'UserId')]
self.callAgent?.startCall(participants: callees, options: StartCallOptions()) { (call, error) in
if error == nil {
print("Successfully started outgoing call")
self.call = call
} else {
print("Failed to start outgoing call")
}
}
Realice una llamada de uno a varios con usuarios y RTC
Nota:
Consulte los detalles de la oferta de llamadas RTC. Para acceder al programa de versión preliminar, suscríbase al programa de usuarios pioneros.
Para realizar la llamada con RTC, debe especificar el número de teléfono adquirido con Communication Services.
let pstnCallee = PhoneNumberIdentifier(phoneNumber: '+1999999999')
let callee = CommunicationUserIdentifier('UserId')
self.callAgent?.startCall(participants: [pstnCallee, callee], options: StartCallOptions()) { (groupCall, error) in
if error == nil {
print("Successfully started outgoing call to multiple participants")
self.call = groupCall
} else {
print("Failed to start outgoing call to multiple participants")
}
}
Unión a una llamada de una sala
Para unirse a una llamada a room
, especifique la propiedad roomId
como identificador de room
. Para unirse a la llamada, use el método join
y pase roomCallLocator
.
func joinRoomCall() {
if self.callAgent == nil {
print("CallAgent not initialized")
return
}
if (self.roomId.isEmpty) {
print("Room ID not set")
return
}
// Join a call with a Room ID
let options = JoinCallOptions()
let audioOptions = AudioOptions()
audioOptions.muted = self.muted
options.audioOptions = audioOptions
let roomCallLocator = RoomCallLocator(roomId: roomId)
self.callAgent!.join(with: roomCallLocator, joinCallOptions: options) { (call, error) in
self.setCallAndObserver(call: call, error: error)
}
}
Un objeto room
ofrece a los desarrolladores de aplicaciones un mejor control sobre quién puede unirse a una llamada, cuándo se reúnen y cómo colaboran. Para obtener más información sobre rooms
, puede leer la documentación conceptual o seguir la guía de inicio rápido.
Unirse a una llamada grupal
Para unirse a una llamada, debe llamar a una de las API en CallAgent
.
let groupCallLocator = GroupCallLocator(groupId: UUID(uuidString: "uuid_string")!)
self.callAgent?.join(with: groupCallLocator, joinCallOptions: JoinCallOptions()) { (call, error) in
if error == nil {
print("Successfully joined group call")
self.call = call
} else {
print("Failed to join group call")
}
}
Suscripción a una llamada entrante
Suscríbase a un evento de llamada entrante.
final class IncomingCallHandler: NSObject, CallAgentDelegate, IncomingCallDelegate
{
// Event raised when there is an incoming call
public func callAgent(_ callAgent: CallAgent, didReceiveIncomingCall incomingcall: IncomingCall) {
self.incomingCall = incomingcall
// Subscribe to get OnCallEnded event
self.incomingCall?.delegate = self
}
// Event raised when incoming call was not answered
public func incomingCall(_ incomingCall: IncomingCall, didEnd args: PropertyChangedEventArgs) {
print("Incoming call was not answered")
self.incomingCall = nil
}
}
Aceptar una llamada entrante
Para aceptar una llamada, llame al método accept
en un objeto IncomingCall
.
self.incomingCall!.accept(options: AcceptCallOptions()) { (call, error) in
if (error == nil) {
print("Successfully accepted incoming call")
self.call = call
} else {
print("Failed to accept incoming call")
}
}
let firstCamera: VideoDeviceInfo? = self.deviceManager!.cameras.first
localVideoStreams = [LocalVideoStream]()
localVideoStreams!.append(LocalVideoStream(camera: firstCamera!))
let acceptCallOptions = AcceptCallOptions()
acceptCallOptions.videoOptions = VideoOptions(localVideoStreams: localVideoStreams!)
if let incomingCall = self.incomingCall {
incomingCall.accept(options: acceptCallOptions) { (call, error) in
if error == nil {
print("Incoming call accepted")
} else {
print("Failed to accept incoming call")
}
}
} else {
print("No incoming call found to accept")
}
Realización de operaciones durante la llamada
Durante una llamada, puede realizar varias operaciones para administrar la configuración relacionada con el vídeo y el audio.
Silenciar y Reactivar audio
Para silenciar o reactivar el sonido del punto de conexión local, puede usar las API asincrónicas mute
y unmute
.
call!.mute { (error) in
if error == nil {
print("Successfully muted")
} else {
print("Failed to mute")
}
}
Use el código siguiente para silenciar el punto de conexión local de forma asincrónica.
call!.unmute { (error) in
if error == nil {
print("Successfully un-muted")
} else {
print("Failed to unmute")
}
}
Administración de participantes remotos
El tipo RemoteParticipant
representa a todos los participantes remotos y estos están disponibles mediante la colección remoteParticipants
en una instancia de llamada.
Lista de los participantes en una llamada
call.remoteParticipants
Incorporación de un participante a una llamada
Para agregar un participante a una llamada (ya sea un usuario o un número de teléfono), puede invocar a addParticipant
. Este comando devolverá de manera sincrónica la instancia de un participante remoto.
let remoteParticipantAdded: RemoteParticipant = call.add(participant: CommunicationUserIdentifier(identifier: "userId"))
Eliminación de un participante de una llamada
Para quitar un participante de una llamada (ya sea un usuario o un número de teléfono), puede invocar a la API removeParticipant
. Esto se resolverá de manera asincrónica.
call!.remove(participant: remoteParticipantAdded) { (error) in
if (error == nil) {
print("Successfully removed participant")
} else {
print("Failed to remove participant")
}
}
Obtención de las propiedades de los participantes remotos
// [RemoteParticipantDelegate] delegate - an object you provide to receive events from this RemoteParticipant instance
var remoteParticipantDelegate = remoteParticipant.delegate
// [CommunicationIdentifier] identity - same as the one used to provision a token for another user
var identity = remoteParticipant.identifier
// ParticipantStateIdle = 0, ParticipantStateEarlyMedia = 1, ParticipantStateConnecting = 2, ParticipantStateConnected = 3, ParticipantStateOnHold = 4, ParticipantStateInLobby = 5, ParticipantStateDisconnected = 6
var state = remoteParticipant.state
// [Error] callEndReason - reason why participant left the call, contains code/subcode/message
var callEndReason = remoteParticipant.callEndReason
// [Bool] isMuted - indicating if participant is muted
var isMuted = remoteParticipant.isMuted
// [Bool] isSpeaking - indicating if participant is currently speaking
var isSpeaking = remoteParticipant.isSpeaking
// RemoteVideoStream[] - collection of video streams this participants has
var videoStreams = remoteParticipant.videoStreams // [RemoteVideoStream, RemoteVideoStream, ...]
Silenciar a otros participantes
Nota:
Para usar esta API, use la versión 2.13.0 o posterior del SDK de Azure Communication Services para Llamadas a iOS.
Para silenciar a todos los demás participantes de una llamada, use la API muteAllRemoteParticipants
en la llamada.
call!.muteAllRemoteParticipants { (error) in
if error == nil {
print("Successfully muted all remote participants.")
} else {
print("Failed to mute remote participants.")
}
}
Para silenciar a un participante remoto específico, use la API mute
en un participante remoto determinado.
remoteParticipant.mute { (error) in
if error == nil {
print("Successfully muted participant.")
} else {
print("Failed to mute participant.")
}
}
Para notificar al participante local que otros usuarios han silenciado, suscríbase al evento onMutedByOthers
.
Configuración del sistema
Siga estos pasos para configurar el sistema.
Creación del proyecto de Visual Studio
En el caso de una aplicación para la Plataforma universal de Windows, en Visual Studio 2022, cree un proyecto de Aplicación vacía (Universal Windows). Después de escribir el nombre del proyecto, puede elegir cualquier Windows SDK posterior a 10.0.17763.0.
En el caso de una aplicación WinUI 3, cree un nuevo proyecto con la plantilla Aplicación vacía, empaquetada (WinUI 3 en escritorio) para configurar una aplicación WinUI 3 de una sola página. Se requiere la versión 1.3 o posterior del SDK de aplicaciones de Windows.
Instalación del paquete y las dependencias mediante el Administrador de paquetes NuGet
Las API y bibliotecas de SDK de llamadas están disponibles públicamente a través de un paquete NuGet.
Para buscar, descargar e instalar el paquete NuGet del SDK de llamadas:
- Abra el Administrador de paquetes NuGet desde Herramientas>Administrador de paquetes NuGet>Administrar paquetes NuGet para la solución.
- Seleccione Explorar y, después, escriba Azure.Communication.Calling.WindowsClient en el cuadro de búsqueda.
- Asegúrese de que la casilla Incluir versión preliminar esté activada.
- Seleccione el paquete Azure.Communication.Calling.WindowsClient y, después, Azure.Communication.Calling.WindowsClient 1.4.0-beta.1 o una versión más reciente.
- Seleccione la casilla correspondiente al proyecto de Azure Communication Services en el panel derecho.
- Seleccione Instalar.
Solicitud de acceso al micrófono
La aplicación requiere acceso al micrófono para ejecutarse correctamente. En las aplicaciones para UWP, la funcionalidad de micrófono debe estar declarada en el archivo de manifiesto de la aplicación.
Los siguientes pasos ejemplifican cómo lograrlo.
- En el panel
Solution Explorer
, haga doble clic en el archivo con la extensión.appxmanifest
. - Haga clic en la pestaña
Capabilities
. - Active la casilla
Microphone
de la lista de funcionalidades.
Creación de botones de UI para realizar la llamada y colgar
Esta sencilla aplicación de ejemplo incluye dos botones. Uno para realizar la llamada y otro para colgar una llamada realizada. Los pasos siguientes ejemplifican cómo agregar estos botones a la aplicación.
- En el
Solution Explorer
panel, haz doble clic en el archivo denominadoMainPage.xaml
para UWP, oMainWindows.xaml
en WinUI 3. - En el panel central, busque el código XAML en la versión preliminar de la interfaz de usuario.
- Reemplace el código XAML por el fragmento siguiente:
<TextBox x:Name="CalleeTextBox" PlaceholderText="Who would you like to call?" />
<StackPanel>
<Button x:Name="CallButton" Content="Start/Join call" Click="CallButton_Click" />
<Button x:Name="HangupButton" Content="Hang up" Click="HangupButton_Click" />
</StackPanel>
Configuración de la aplicación con las API de Calling SDK
Las API de Calling SDK se encuentran en dos espacios de nombres diferentes. Los pasos siguientes informan al compilador de C# sobre estos espacios de nombres, lo que permite a IntelliSense de Visual Studio ayudar con el desarrollo del código.
- En el panel
Solution Explorer
, haga clic en la flecha del lado izquierdo del archivo denominadoMainPage.xaml
para UWP, oMainWindows.xaml
para WinUI 3. - Haga doble clic en el archivo denominado
MainPage.xaml.cs
oMainWindows.xaml.cs
. - Agregue los siguientes comandos al final de las instrucciones
using
actuales.
using Azure.Communication.Calling.WindowsClient;
Mantenga abierto MainPage.xaml.cs
o MainWindows.xaml.cs
. En los pasos siguientes se le agregará más código.
Habilitación de interacciones de aplicaciones
Los botones de la interfaz de usuario agregados anteriormente tienen que funcionar sobre un CommunicationCall
colocado. Esto significa que un miembro de datos CommunicationCall
debe agregarse a la clase MainPage
o MainWindow
.
Además, para permitir que la operación asincrónica que crea CallAgent
se complete correctamente, también tiene que agregar un miembro de datos CallAgent
a la misma clase.
Agregue los siguientes miembros de datos a la clase MainPage
oMainWindow
:
CallAgent callAgent;
CommunicationCall call;
Creación de controladores de botones
Anteriormente, se agregaron dos botones de interfaz de usuario al código XAML. En el código siguiente, se agregan los controladores que se ejecutarán cuando un usuario seleccione el botón. El código siguiente debe agregarse después de los miembros de datos de la sección anterior.
private async void CallButton_Click(object sender, RoutedEventArgs e)
{
// Start call
}
private async void HangupButton_Click(object sender, RoutedEventArgs e)
{
// End the current call
}
Modelo de objetos
Las clases e interfaces siguientes controlan algunas de las características principales de la biblioteca cliente para llamadas de Azure Communication Services para UWP.
Nombre | Descripción |
---|---|
CallClient |
CallClient es el punto de entrada principal a la biblioteca cliente de llamadas. |
CallAgent |
CallAgent se usa para iniciar llamadas y unirse a estas. |
CommunicationCall |
CommunicationCall se usa para administrar las llamadas realizadas o a las que se ha unido. |
CommunicationTokenCredential |
CommunicationTokenCredential se usa como la credencial del token para crear una instancia de CallAgent . |
CallAgentOptions |
El CallAgentOptions contiene información para identificar al autor de la llamada. |
HangupOptions |
El HangupOptions informa sobre si se debe finalizar una llamada a todos los participantes. |
Inicialización de CallAgent
Para crear una instancia de CallAgent
a partir de CallClient
, tiene que usar el método CallClient.CreateCallAgentAsync
que devuelve de manera asincrónica un objeto CallAgent
una vez que se inicializa.
Para crear CallAgent
, tiene que pasar un objeto CallTokenCredential
y un objeto CallAgentOptions
. Tenga en cuenta que se produce un error de CallTokenCredential
si se pasa un token con formato incorrecto.
Se debe agregar dentro el código siguiente y se debe llamar a la función auxiliar en la inicialización de la aplicación.
var callClient = new CallClient();
this.deviceManager = await callClient.GetDeviceManagerAsync();
var tokenCredential = new CallTokenCredential("<AUTHENTICATION_TOKEN>");
var callAgentOptions = new CallAgentOptions()
{
DisplayName = "<DISPLAY_NAME>"
};
this.callAgent = await callClient.CreateCallAgentAsync(tokenCredential, callAgentOptions);
Cambie el <AUTHENTICATION_TOKEN>
con un token de credencial válido para el recurso. Consulte la documentación sobre tokens de acceso de usuario si es necesario proporcionar un token de credencial.
Creación de CallAgent y realización de una llamada
Los objetos necesarios para crear CallAgent
ya están listos. Es el momento de crear CallAgent
de manera asincrónica y realizar una llamada.
El código siguiente debe agregarse después de controlar la excepción del paso anterior.
var startCallOptions = new StartCallOptions();
var callees = new [] { new UserCallIdentifier(CalleeTextBox.Text.Trim()) };
this.call = await this.callAgent.StartCallAsync(callees, startCallOptions);
this.call.OnStateChanged += Call_OnStateChangedAsync;
No dude en usar 8:echo123
para hablar con el bot de chat de Azure Communication Services.
Silenciar y Reactivar audio
Para silenciar o reactivar el audio saliente, puede usar las API asincrónicas MuteOutgoingAudioAsync
y UnmuteOutgoingAudioAsync
:
// mute outgoing audio
await this.call.MuteOutgoingAudioAsync();
// unmute outgoing audio
await this.call.UnmuteOutgoingAudioAsync();
Silenciar a otros participantes
Nota:
Para usar esta API, use la versión 1.9.0 o posterior del SDK de Azure Communication Services para Llamadas a Windows.
Para silenciar a todos los demás participantes o silenciar a un participante específico, puede usar las API asincrónicas MuteAllRemoteParticipantsAsync
en la llamada y MuteAsync
en el participante remoto:
// mute all participants except yourself
await this.call.MuteAllRemoteParticipantsAsync();
// mute specific participant in the call
await this.call.RemoteParticipants.FirstOrDefault().MuteAsync();
Para notificar al participante local que otros usuarios han silenciado, suscríbase al evento MutedByOthers
.
Finalizar una llamada
Una vez realizada una llamada, se debe usar el método HangupAsync
del objeto CommunicationCall
para colgar la llamada.
También se debe usar una instancia de HangupOptions
para informar sobre si la llamada se debe finalizar a todos sus participantes.
El código siguiente debe agregarse dentro de HangupButton_Click
.
this.call.OnStateChanged -= Call_OnStateChangedAsync;
await this.call.HangUpAsync(new HangUpOptions() { ForEveryone = false });
Ejecución del código
Asegúrese de que Visual Studio compila la aplicación para x64
, x86
o ARM64
, y presione F5
para empezar a ejecutar la aplicación. Después de esto, haga clic en el botón Call
para realizar una llamada al destinatario definido.
Tenga en cuenta que la primera vez que se ejecute la aplicación, el sistema solicita al usuario que conceda acceso al micrófono.