
Compartir:
Abdul es desarrollador de Vonage. Ha trabajado en productos de consumo como ingeniero de iOS. En su tiempo libre, le gusta andar en bicicleta, escuchar música y asesorar a aquellos que están comenzando su viaje en la tecnología.
Cómo hacer llamadas telefónicas con SwiftUI
Tiempo de lectura: 15 minutos
En este tutorial, crearás una aplicación SwiftUI que pueda realizar llamadas a un número de teléfono especificado utilizando el Vonage Client SDK para iOS. SwiftUI es un marco de interfaz de usuario lanzado por Apple en 2019, que ayuda a crear aplicaciones en todas las plataformas de Apple con menos código que sus predecesores. Como verás, SwiftUI tiene una sintaxis declarativa que te permite declarar lo que debe hacer la interfaz de usuario, lo que facilita la lectura de la aplicación.
Requisitos previos
Una Account API de Vonage. Si aún no tienes una, puedes inscribirte hoy.
Xcode 12 y Swift 5 o superior.
Cocoapods para instalar el Client SDK de Vonage para iOS.
La CLI de Vonage. Si aún no la tiene, puede instalarla con
npm install -g @vonage/cli.
Visión general
Este proyecto consta de 3 partes, la aplicación de Vonage, el servidor webhook y la aplicación de iOS. La aplicación de Vonage es cómo puedes usar los productos de Vonage, en este caso, la Voice API. La aplicación de Vonage que crearás requiere 2 URL, una answer_url y una event_url. La dirección answer_url debe devolver un objeto de control de llamadas, que le indicará a Vonage cómo manejar la llamada. La parte del servidor del proyecto devolverá un objeto de control de llamadas basado en el número especificado en la aplicación iOS.
Creación del servidor
Como se mencionó anteriormente, es necesario crear un servidor webhook que expone dos direcciones URL, una de las cuales devuelve un objeto de control de llamada Objeto de control de llamada. Contendrá una acción de conexión que reenviará la llamada al número de teléfono PSTN. Para ello, extraerá el número de destino del parámetro de consulta to y devolviéndolo en la respuesta.
Cree un nuevo directorio de proyecto en un destino de su elección y cambie a él:
Dentro de la carpeta, inicializa un nuevo proyecto Node.js ejecutando este comando:
Necesitarás un número de Vonage. Puedes comprar un número usando la CLI de Vonage. El siguiente comando compra un número disponible en los EE. UU. Especifica un código de país alternativo de dos caracteres para comprar un número en otro país.
Dentro de la carpeta del proyecto, cree un archivo llamado server.js y agrega el código como se muestra a continuación; asegúrate de reemplazar NUMBER por tu número de Vonage (en E.164 ), así como SUBDOMAIN con un valor único. El valor utilizado formará parte de las URL que establecerás como webhooks en el siguiente paso.
Creación de la aplicación de Vonage
En este paso, crearás una aplicación de Vonage Vonage con capacidad para casos de uso de comunicación de voz dentro de la aplicación.
Crear una aplicación
Crea una aplicación de Vonage copiando y pegando el siguiente comando en el terminal. Asegúrate de cambiar los valores de --voice_answer_url y --voice_event_url sustituyendo SUBDOMAIN por el valor real utilizado en el paso anterior:
Se crea un archivo llamado vonage_app.json en el directorio de tu proyecto y contiene el nuevo ID de aplicación de Vonage y la clave privada. También se crea un archivo de clave privada llamado SwiftUICall.key también se creará. Ahora que tu aplicación está creada, vincula tu número de Vonage a tu aplicación:
Crear un usuario
La Conversation API de Vonage tiene el concepto de usuarios. Un usuario representa un usuario único de tu aplicación y, por lo tanto, tiene un ID único. Así es como tu aplicación iOS se autenticará con los servidores de Vonage y será identificada por ellos. Puedes usar la CLI para crear un usuario:
Esto añadirá un usuario, con el nombre de usuario Alice, a tu aplicación y mostrará su ID único.
Crear un JWT
Los SDK para clientes de Vonage utilizan tokens web JSON (JWT) para la autenticación. Los JWT son un método para representar reclamos de manera segura entre dos partes. Puedes leer más sobre los JWT en JWT.io o las reclamaciones que admite la Conversation API admite. Utilizaremos la clave privada, el ID de la aplicación y el nombre de usuario de las secciones anteriores para crear el JWT necesario para tu aplicación iOS. Una vez más, esto se hace a través de la CLI. Sustituye la variable APPLICATION_ID con el id de tu aplicación y PRIVATE_KEY con el nombre de su archivo de clave privada.
Esto mostrará el JWT para el usuario Alice que ha sido firmado utilizando su clave privada. Guarde esto, ya que lo necesitará más adelante.
Creación de la aplicación iOS
Ahora que el servidor y la aplicación de Vonage están configurados, es hora de crear la aplicación para iOS.
Crear un proyecto Xcode
Para empezar, abre Xcode y crea un nuevo proyecto yendo a Archivo > Nuevo > Proyecto. Selecciona una plantilla de App y dale un nombre. Seleccione, SwiftUI para la interfaz, SwiftUI App para el ciclo de vida, y Swift para el lenguaje, por último, una ubicación para guardar el proyecto.

Instala el Vonage Client SDK
Ahora que el proyecto está creado, puedes agregar el Vonage Client SDK como dependencia. Navega a la ubicación donde guardaste el proyecto en tu terminal y ejecuta los siguientes comandos.
Ejecute el comando
pod initpara crear un nuevo Podfile para su proyecto.Abra el Podfile en Xcode utilizando
open -a Xcode Podfile.Actualiza el Podfile para que tenga
VonageClientSDKVoicecomo dependencia.
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'SwiftUICall' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for SwiftUICall
pod 'VonageClientSDKVoice'
endInstale el SDK con
pod install.Abra el nuevo xcworkspace en Xcode con
open SwiftUICall.xcworkspace.
Permisos de micrófono
Dado que la aplicación utilizará el micrófono para realizar llamadas, es necesario pedir permiso explícitamente para hacerlo. El primer paso es editar el archivo Info.plist archivo. Se trata de un archivo que contiene todos los metadatos necesarios para la aplicación. Añada una nueva entrada al archivo pasando el ratón por encima de la última entrada de la lista y haciendo clic en el pequeño botón + que aparece. Elija Privacy - Microphone Usage Description de la lista desplegable y añada Microphone access required to make and receive audio calls. como valor. Usted hará el segundo paso para solicitar permisos de micrófono más adelante en el tutorial.
Creación de la clase modelo
Antes de empezar a construir la interfaz de usuario (UI) de la aplicación, construirás primero una clase modelo. Esta clase se utiliza para separar la lógica de la aplicación del código de la vista. En este caso, la clase modelo manejará las llamadas delegadas desde el Client SDK y cuándo debe mostrarse el botón de llamada. En la parte superior del archivo ContentView.swift importe el Client SDK y AVFoundation.
import SwiftUI
import AVFoundation
import VonageClientSDKVoiceA continuación, en la parte inferior del archivo, crear una nueva clase llamada CallModel:
final class CallModel: NSObject, ObservableObject, VGVoiceClientDelegate {
}Dentro de esta clase, defina las propiedades y funciones de ayuda necesarias:
final class CallModel: NSObject, ObservableObject, VGVoiceClientDelegate {
@Published var status: String = ""
@Published var isCalling: Bool = false
let client = VGVoiceClient()
var number: String = ""
private var callId: String?
private let audioSession = AVAudioSession.sharedInstance()
func updateStatus(_ text: String) {
DispatchQueue.main.async {
self.status = text
}
}
func resetState() {
DispatchQueue.main.async {
self.callId = nil
self.isCalling = false
self.number = ""
}
}
}La envoltura de la propiedad @Published es la forma en que la interfaz de usuario sabrá cuándo reaccionar a los cambios de la clase modelo. Todo esto se maneja para usted como la clase se ajusta a la ObservedObject protocolo. La propiedad client es para el cliente de voz de Vonage, que te permitirá realizar llamadas. callId se utiliza para almacenar el objeto de llamada, y audioSession se utiliza para solicitar los permisos del micrófono. Configura el Client SDK:
func initializeClient() {
let config = VGClientConfig(region: .US)
client.setConfig(config)
client.delegate = self
}Para completar la solicitud de permisos de micrófono para la aplicación, añada la siguiente función a la clase CallModel clase
func requestPermissionsIfNeeded() {
if audioSession.recordPermission != .granted {
audioSession.requestRecordPermission { (isGranted) in
print("Microphone permissions \(isGranted)")
}
}
}Esto primero comprobará si los permisos ya han sido concedidos; si no, los solicitará e imprimirá el resultado en la consola. A continuación, tienes que iniciar sesión como el usuario Alice con el Client SDK. Para ello, añade la siguiente función a la clase CallModel reemplazando ALICE_JWT con el JWT de antes:
func loginIfNeeded() {
guard status != "Connected" else { return }
VGVoiceClient.isUsingCallKit = false
client.createSession("ALICE_JWT") { error, sessionId in
if let error {
self.updateStatus(error.localizedDescription)
} else {
self.updateStatus("Connected")
}
}
}Esta función comprueba si el cliente ya ha iniciado sesión; si no, utilizará el JWT que generó anteriormente para iniciar sesión y establecerá el delegado para el cliente en esta clase. El VGVoiceClientDelegate es la forma en que el Client SDK comunica los cambios con los servidores de Vonage a tu aplicación. A continuación, implementa las funciones de delegado requeridas.
func voiceClient(_ client: VGVoiceClient, didReceiveHangupForCall callId: VGCallId, withQuality callQuality: VGRTCQuality, reason: VGHangupReason) {
self.resetState()
}
func client(_ client: VGBaseClient, didReceiveSessionErrorWith reason: VGSessionErrorReason) {
let reasonString: String!
switch reason {
case .tokenExpired:
reasonString = "Expired Token"
case .pingTimeout, .transportClosed:
reasonString = "Network Error"
default:
reasonString = "Unknown"
}
status = reasonString
}
func voiceClient(_ client: VGVoiceClient, didReceiveInviteForCall callId: VGCallId, from caller: String, with type: VGVoiceChannelType) {}
func voiceClient(_ client: VGVoiceClient, didReceiveInviteCancelForCall callId: VGCallId, with reason: VGVoiceInviteCancelReason) {}Cuando se produce un error de sesión, la propiedad status y si la llamada finaliza, el estado del modelo se reinicia. Las siguientes dos funciones que necesitas agregar permitirán a tu aplicación hacer y terminar llamadas. Añade las siguientes funciones.
func startCall() {
self.isCalling = true
client.serverCall(["to": number]) { error, callId in
if error == nil {
self.callId = callId
}
}
}
func endCall() {
client.hangup(callId!) { error in
if error == nil {
self.resetState()
}
}
}La función callNumber utiliza el Client SDK para realizar una llamada al número de la propiedad number propiedad. Esto utiliza la función answer_url de antes en el tutorial. Vonage realizará entonces una llamada HTTP a su answer_url con el número de la aplicación iOS, que devolverá un objeto de control de llamadas con instrucciones para que Vonage conecte tu aplicación con el número. Si todo esto tiene éxito, el Client SDK devuelve un ID de llamada que se almacena en la clase. La función endCall cuelga la llamada, establece la propiedad callId a nil y devuelve el valor booleano isCalling a false para que la interfaz de usuario pueda actualizarse.
La última función que debe añadir al módulo CallModel llama a initializeClient, requestPermissionsIfNeededy loginIfNeeded funciones.
func setup() {
initializeClient()
requestPermissionsIfNeeded()
loginIfNeeded()
} Crear la interfaz de usuario
La interfaz de usuario constará de un objeto Text para mostrar el estado, un objeto TextField para introducir los números y un par de objetos Button para iniciar y finalizar llamadas. Añade una propiedad para la clase CallModel que creó anteriormente a la estructura ContentView y utilícela para mostrar el estado del Client SDK.
struct ContentView: View {
@StateObject var callModel = CallModel()
var body: some View {
VStack {
Text(callModel.status)
}
.animation(.default)
.onAppear(perform: self.callModel.setup)
}
}Cuando aparezca la vista, llamará a la función setup en la clase del modelo; esto solicitará los permisos del micrófono y registrará al cliente. Al hacerlo, se actualizará la propiedad status de la clase modelo, y el cambio en su valor hará que la función ContentView para que se actualice.
Ahora que el cliente ha iniciado sesión, puede utilizar el resto de las propiedades publicadas en la clase modelo para construir el resto de la interfaz de usuario. Añade el siguiente bloque de código al VStack.
if self.callModel.status == "Connected" {
TextField("Enter a phone number", text: $callModel.number)
.textFieldStyle(RoundedBorderTextFieldStyle())
.multilineTextAlignment(.center)
.keyboardType(.numberPad)
.disabled(self.callModel.isCalling)
.padding(20)
if !self.callModel.isCalling {
Button(action: { self.callModel.startCall() }) {
HStack(spacing: 10) {
Image(systemName: "phone")
Text("Call")
}
}
}
if self.callModel.isCalling {
Button(action: { self.callModel.endCall() }) {
HStack(spacing: 10) {
Image(systemName: "phone")
Text("End Call")
}
.foregroundColor(Color.red)
}
}
}La página TextField se animará en la vista si el cliente está conectado. El valor de TextField está vinculado a la propiedad number de la clase modelo. Para ello se utiliza el signo $ signo. Una vez que se ha introducido un número de longitud válida, se cumplirán las condiciones para mostrar el botón de llamada, y una vez que se ha iniciado una llamada, ya no se cumplirán las condiciones, pero sí las condiciones para el botón de fin de llamada. Así que sólo se mostrará un botón a la vez, y toda la actualización de la interfaz de usuario será manejada por ti.
Ejecute su aplicación
Si ejecuta el proyecto (CMD + R), primero se le pedirá que autorice los permisos de micrófono. Podrá introducir un número y llamarlo. El formato de los Numbers debe ser del tipo E.164 .

¿Y ahora qué?
Puede encontrar el proyecto completo en GitHub. Puedes hacer mucho más con el Client SDK. Más información en developer.vonage.com.