Compartir vía


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

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 de Call 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 error connectionIssue.

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 de CommunicationIdentifier:
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 a Disconnected tras dos minutos.
  • callEndReason: para saber por qué el participante dejó la llamada, compruebe la propiedad callEndReason:

    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 propiedad isMuted. Devuelve Boolean.

    const isMuted = remoteParticipant.isMuted;
    
  • Estado isSpeaking: para averiguar si un participante remoto está hablando, compruebe la propiedad isSpeaking. Devuelve Boolean.

    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ón videoStreams: Contiene objetos RemoteVideoStream.

    const videoStreams = remoteParticipant.videoStreams; // [RemoteVideoStream, ...]
    
  • displayName: para obtener el nombre para mostrar de este participante remoto, revise la propiedad displayName que devuelve la cadena.

    const displayName = remoteParticipant.displayName;
    
  • endpointDetails: obtenga los detalles de todos los puntos de conexión de este participante remoto

        const 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. Es Incoming 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 estado Disconnected.
  • Disconnected: estado final de la llamada. Si se pierde la conexión de red, el estado cambia a Disconnected 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.

Captura de pantalla que muestra la ventana para crear un proyecto en Xcode.

Instalación del paquete y las dependencias mediante CocoaPods

  1. 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
    
  2. Ejecute pod install.

  3. 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:

  1. Abra el Administrador de paquetes NuGet desde Herramientas>Administrador de paquetes NuGet>Administrar paquetes NuGet para la solución.
  2. Seleccione Explorar y, después, escriba Azure.Communication.Calling.WindowsClient en el cuadro de búsqueda.
  3. Asegúrese de que la casilla Incluir versión preliminar esté activada.
  4. 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.
  5. Seleccione la casilla correspondiente al proyecto de Azure Communication Services en el panel derecho.
  6. 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.

  1. En el panel Solution Explorer, haga doble clic en el archivo con la extensión .appxmanifest.
  2. Haga clic en la pestaña Capabilities.
  3. 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.

  1. En el Solution Explorer panel, haz doble clic en el archivo denominado MainPage.xaml para UWP, o MainWindows.xaml en WinUI 3.
  2. En el panel central, busque el código XAML en la versión preliminar de la interfaz de usuario.
  3. 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.

  1. En el panel Solution Explorer, haga clic en la flecha del lado izquierdo del archivo denominado MainPage.xaml para UWP, o MainWindows.xaml para WinUI 3.
  2. Haga doble clic en el archivo denominado MainPage.xaml.cs o MainWindows.xaml.cs.
  3. 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.

Pasos siguientes