
Compartilhar:
Abdul é um Developer Advocate da Vonage. Ele tem experiência profissional na área de produtos de consumo como engenheiro de iOS. Em seu tempo livre, ele gosta de andar de bicicleta, ouvir música e orientar quem está dando os primeiros passos na área de tecnologia
Como fazer chamadas telefônicas com o SwiftUI
Tempo de leitura: 15 minutos
Neste tutorial, você criará um aplicativo SwiftUI capaz de fazer chamadas para um número de telefone especificado usando o Vonage Client SDK para iOS. O SwiftUI é uma estrutura de interface do usuário lançada pela Apple em 2019, que ajuda a desenvolver aplicativos para todas as plataformas da Apple com menos código do que suas versões anteriores. Como você verá, o SwiftUI possui uma sintaxe declarativa que permite definir o que a interface do usuário deve fazer, o que torna o aplicativo mais fácil de ler.
Pré-requisitos
Um account da API da Vonage. Se você ainda não tiver um, pode se cadastrar hoje mesmo.
Xcode 12 e Swift 5 ou versão posterior.
Cocoapods para instalar o Vonage Client SDK para iOS.
O CLI do Vonage. Caso ainda não o tenha, ele pode ser instalado com
npm install -g @vonage/cli.
Visão geral
Este projeto tem três partes: o aplicativo da Vonage, o servidor de webhooks e o aplicativo para iOS. O aplicativo da Vonage é a forma de utilizar os produtos da Vonage; neste caso, a Voice API. O aplicativo da Vonage que você criará requer duas URLs: uma answer_url e uma event_url. O answer_url precisa retornar um Objeto de Controle de Chamada, que informará à Vonage como lidar com a chamada. A parte do servidor do projeto retornará um Objeto de Controle de Chamada com base no número especificado no aplicativo para iOS.
Criação do servidor
Conforme mencionado anteriormente, é necessário criar um servidor de webhooks que exponha duas URLs, sendo que uma delas retorna um Objeto de Controle de Chamada. Ele conterá uma ação de conexão que encaminhará a chamada para o número de telefone PSTN. Para isso, extraia o número de destino do to parâmetro de consulta e retorná-lo em sua resposta.
Crie um novo diretório de projeto no local de sua escolha e acesse-o:
Dentro da pasta, inicialize um novo projeto Node.js executando este comando:
Você precisará de um número da Vonage. É possível adquirir um número usando a CLI da Vonage. O comando a seguir adquire um número disponível nos EUA. Especifique um código de país alternativo de dois caracteres para adquirir um número em outro país.
Dentro da pasta do seu projeto, crie um arquivo chamado server.js e adicione o código conforme mostrado abaixo — certifique-se de substituir NUMBER pelo seu número da Vonage (em formato E.164 ), bem como SUBDOMAIN por um valor exclusivo. O valor utilizado fará parte das URLs que você definirá como webhooks na próxima etapa.
Criação do aplicativo Vonage
Nesta etapa, você criará um Vonage Applications capaz de atender a casos de uso de comunicação de voz dentro do aplicativo.
Criar um aplicativo
Crie uma aplicação Vonage copiando e colando o comando abaixo no terminal. Certifique-se de alterar os valores de --voice_answer_url e --voice_event_url argumentos, substituindo SUBDOMAIN pelo valor real usado na etapa anterior:
Um arquivo chamado vonage_app.json é criado no diretório do seu projeto e contém o ID do aplicativo Vonage recém-criado e a chave privada. Um arquivo de chave privada chamado SwiftUICall.key também é criado. Agora que seu aplicativo está criado, vincule seu número da Vonage ao aplicativo:
Criar um usuário
A Conversation API da Vonage utiliza o conceito de usuários. Um usuário representa um usuário único do seu aplicativo e, portanto, possui um ID exclusivo. É assim que seu aplicativo iOS se autenticará e será identificado pelos servidores da Vonage. Você pode usar a CLI para criar um usuário:
Isso adicionará uma usuária, com o nome de usuário Alice, ao seu aplicativo e exibirá o ID exclusivo dela.
Criar um JWT
Os SDKs do cliente Vonage utilizam JSON Web Tokens (JWTs) para autenticação. Os JWTs são um método para representar reivindicações de forma segura entre duas partes. Você pode ler mais sobre JWTs em JWT.io ou sobre as reivindicações que a Conversation API suporta. Usaremos a chave privada, o ID do aplicativo e o nome de usuário das seções anteriores para criar o JWT necessário para seu aplicativo iOS. Novamente, isso é feito por meio da CLI. Substitua a APPLICATION_ID variável pelo ID do seu aplicativo e PRIVATE_KEY pelo nome do seu arquivo de chave privada.
Isso exibirá o JWT da usuária Alice, que foi assinado com sua chave privada. Guarde-o, pois você precisará dele mais tarde.
Criação do aplicativo para iOS
Agora que o servidor e o aplicativo da Vonage estão configurados, é hora de desenvolver o aplicativo para iOS.
Criar um projeto no Xcode
Para começar, abra o Xcode e crie um novo projeto selecionando Arquivo > Novo > Projeto. Selecione um modelo de aplicativo e dê um nome a ele. Selecione SwiftUI para a interface, SwiftUI App para o ciclo de vida e Swift como linguagem — por fim, escolha um local para salvar seu projeto.

Instale o Vonage Client SDK
Agora que o projeto foi criado, você pode adicionar o Vonage Client SDK como dependência. Navegue até o local onde você salvou o projeto no seu terminal e execute os seguintes comandos.
Execute o
pod initpara criar um novo Podfile para o seu projeto.Abra o Podfile no Xcode usando
open -a Xcode Podfile.Atualize o Podfile para incluir
VonageClientSDKVoicecomo dependência.
# 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 o SDK usando
pod install.Abra o novo arquivo xcworkspace no Xcode usando
open SwiftUICall.xcworkspace.
Permissões do microfone
Como o aplicativo usará o microfone para fazer chamadas, é necessário solicitar permissão explicitamente para isso. O primeiro passo é editar o Info.plist arquivo. Esse é um arquivo que contém todos os metadados necessários para o aplicativo. Adicione uma nova entrada ao arquivo passando o mouse sobre a última entrada da lista e clicando no pequeno + botão que aparece. Escolha Privacy - Microphone Usage Description na lista suspensa e adicione Microphone access required to make and receive audio calls. como valor. Você realizará a segunda etapa para solicitar permissões de uso do microfone mais adiante neste tutorial.
Criação da classe de modelo
Antes de começar a criar a interface do usuário (UI) do aplicativo, você criará primeiro uma classe de modelo. Essa classe é usada para separar a lógica do aplicativo do código da visualização. Neste caso, a classe de modelo lidará com as chamadas de delegado do Client SDK e determinará quando o botão de chamada deve ser exibido. No início do ContentView.swift arquivo, importe o Client SDK e o AVFoundation.
import SwiftUI
import AVFoundation
import VonageClientSDKVoiceEm seguida, no final do arquivo, crie uma nova classe chamada CallModel:
final class CallModel: NSObject, ObservableObject, VGVoiceClientDelegate {
}Nessa classe, defina as propriedades e as funções auxiliares necessárias:
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 = ""
}
}
}O @Published wrapper de propriedade é o que permite que a interface do usuário saiba quando reagir às alterações da classe do modelo. Tudo isso é tratado automaticamente para você, já que a classe está em conformidade com o ObservedObject protocolo. A client propriedade é para o Vonage Voice Client, que permitirá que você faça chamadas. callId é usado para armazenar o objeto de chamada, e audioSession é usado para solicitar as permissões do microfone. Configure o Client SDK:
func initializeClient() {
let config = VGClientConfig(region: .US)
client.setConfig(config)
client.delegate = self
}Para concluir a solicitação de permissões de microfone para o aplicativo, adicione a seguinte função à CallModel classe:
func requestPermissionsIfNeeded() {
if audioSession.recordPermission != .granted {
audioSession.requestRecordPermission { (isGranted) in
print("Microphone permissions \(isGranted)")
}
}
}Isso verificará primeiro se as permissões já foram concedidas; caso contrário, irá solicitá-las e exibirá o resultado no console. Em seguida, você precisa fazer login como a usuária Alice usando o Client SDK. Para isso, adicione a função a seguir à CallModel classe, substituindo ALICE_JWT pelo 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")
}
}
}Essa função verifica se o cliente já está conectado; caso contrário, ela usará o JWT que você gerou anteriormente para fazer o login e definirá o delegado do cliente como esta classe. É VGVoiceClientDelegate é assim que o Client SDK comunica as alterações dos servidores da Vonage de volta ao seu aplicativo. Em seguida, implemente as funções de delegado necessárias.
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) {}Quando ocorre um erro de sessão, a status propriedade é atualizada e, se a chamada for encerrada, o estado do modelo é reinicializado. As duas funções a seguir, que você precisa adicionar, permitirão que seu aplicativo faça e encerre chamadas. Adicione as seguintes funções.
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()
}
}
}A callNumber função usa o Client SDK para fazer uma chamada para o número da number propriedade. Isso utiliza o answer_url apresentado anteriormente neste tutorial. A Vonage, então, fará uma chamada HTTP para o seu answer_url com o número do aplicativo iOS, que retornará um Objeto de Controle de Chamada com instruções para que a Vonage conecte seu aplicativo ao número. Se tudo der certo, o Client SDK retorna um ID de chamada, que é armazenado na classe. A endCall função encerra a chamada, define a callId propriedade como nil e define o isCalling booleano de volta para false para que a interface do usuário possa ser atualizada.
A última função que você precisa adicionar à CallModel chamadas initializeClient, requestPermissionsIfNeedede loginIfNeeded funções.
func setup() {
initializeClient()
requestPermissionsIfNeeded()
loginIfNeeded()
} Criar a interface do usuário
A interface do usuário consistirá em um Text objeto para exibir o status, um TextField objeto para a entrada do número e um par de Button objetos para iniciar e encerrar chamadas. Adicione uma propriedade para a CallModel classe que você criou anteriormente à ContentView estrutura e use-a para exibir o status do Client SDK.
struct ContentView: View {
@StateObject var callModel = CallModel()
var body: some View {
VStack {
Text(callModel.status)
}
.animation(.default)
.onAppear(perform: self.callModel.setup)
}
}Quando a visualização for exibida, ela chamará a setup função na classe do modelo; isso solicitará as permissões do microfone e fará o login do cliente. Ao fazer isso, a status propriedade na classe do modelo, e a alteração em seu valor acionará a ContentView a ser atualizada!
Agora que o cliente está conectado, você pode usar as demais propriedades publicadas na classe do modelo para construir o restante da interface do usuário. Adicione o seguinte bloco de código ao 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)
}
}
}O TextField será exibido na visualização se o cliente estiver conectado. O valor do TextField está vinculado à number propriedade da classe do modelo. Isso é feito por meio do $ sinal. Assim que um número com comprimento válido for inserido, as condições para exibir o botão de chamada serão atendidas; e, assim que a chamada for iniciada, essas condições não serão mais atendidas, mas as condições para o botão de encerrar a chamada serão. Portanto, apenas um botão é exibido por vez, e todas as atualizações da interface do usuário serão feitas automaticamente para você!
Execute seu aplicativo
Se você executar o projeto (CMD + R), primeiro será solicitado que você conceda permissões para o microfone. Você poderá digitar um número e ligar para ele! O formato dos números deve estar de acordo com a norma E.164 .

E agora?
Você pode encontrar o projeto concluído no GitHub. É possível fazer muito mais com o Client SDK. Saiba mais em developer.vonage.com.
Compartilhar:
Abdul é um Developer Advocate da Vonage. Ele tem experiência profissional na área de produtos de consumo como engenheiro de iOS. Em seu tempo livre, ele gosta de andar de bicicleta, ouvir música e orientar quem está dando os primeiros passos na área de tecnologia