https://a.storyblok.com/f/270183/93755/d624bc5e0b/blog_swiftui_phone-call_1200x600.png

Wie man mit SwiftUI telefoniert

Zuletzt aktualisiert am July 5, 2023

Lesedauer: 15 Minuten

In diesem Tutorial werden Sie eine SwiftUI-Anwendung erstellen, die mit dem Vonage Client SDK für iOS Anrufe an eine bestimmte Telefonnummer tätigen kann. SwiftUI ist ein UI-Framework, das 2019 von Apple veröffentlicht wurde und die Erstellung von Apps für alle Apple-Plattformen mit weniger Code als seine Vorgänger ermöglicht. Wie Sie sehen werden, hat SwiftUI eine deklarative Syntax, mit der Sie angeben können, was die Benutzeroberfläche tun soll, wodurch die Anwendung leichter zu lesen ist.

Voraussetzungen

  • Ein Vonage API-Konto. Wenn Sie noch kein Konto haben, können Sie sich heute anmelden.

  • Xcode 12 und Swift 5 oder höher.

  • Cocoapods um das Vonage Client SDK für iOS zu installieren.

  • Die Vonage CLI. Wenn Sie es noch nicht haben, können Sie es installieren mit npm install -g @vonage/cli.

Übersicht

Dieses Projekt besteht aus 3 Teilen: der Vonage-Anwendung, dem Webhook-Server und der iOS-Anwendung. Mit der Vonage-Anwendung können Sie die Vonage-Produkte nutzen, in diesem Fall die Voice API. Die Vonage-Anwendung, die Sie erstellen werden, benötigt 2 URLs, eine answer_url und eine event_url. Die answer_url muss ein Call Control Object zurückgeben, das Vonage mitteilt, wie der Anruf zu behandeln ist. Der Serverteil des Projekts gibt ein Call Control Object zurück, das auf der Nummer basiert, die in der iOS-Anwendung angegeben ist.

Erstellen des Servers

Wie bereits erwähnt, müssen Sie einen Webhook-Server erstellen, der zwei URLs bereitstellt, von denen eine ein Objekt der Aufrufsteuerung. Es wird eine Verbindungsaktion enthalten, die den Anruf an die PSTN-Telefonnummer. Dazu extrahieren Sie die Zielnummer aus dem to Abfrageparameter extrahieren und in Ihrer Antwort zurückgeben.

Erstellen Sie ein neues Projektverzeichnis an einem Ort Ihrer Wahl und wechseln Sie dorthin:

mkdir vonage-tutorial cd vonage-tutorial

Innerhalb des Ordners initialisieren Sie ein neues Node.js-Projekt, indem Sie diesen Befehl ausführen:

npm init -y npm install express localtunnel --save

Sie benötigen eine Vonage-Nummer. Sie können eine Nummer über die Vonage-CLI erwerben. Mit dem folgenden Befehl kaufen Sie eine verfügbare Nummer in den USA. Geben Sie eine alternative zweistellige Landesvorwahl um eine Nummer in einem anderen Land zu erwerben.

vonage numbers:search US vonage numbers:buy 15555555555 US

Erstellen Sie in Ihrem Projektordner eine Datei mit dem Namen server.js und fügen Sie den unten gezeigten Code ein - bitte ersetzen Sie NUMBER durch Ihre Vonage-Nummer (in E.164 Format), sowie SUBDOMAIN durch einen eindeutigen Wert. Der verwendete Wert wird Teil der URLs, die Sie im nächsten Schritt als Webhooks einrichten werden.

Erstellen der Vonage-Anwendung

In diesem Schritt erstellen Sie eine Vonage Applikation die für die In-App Voice Kommunikation geeignet ist.

Eine Anwendung erstellen

Erstellen Sie eine Vonage-Anwendung, indem Sie den unten stehenden Befehl kopieren und in das Terminal einfügen. Vergewissern Sie sich, dass Sie die Werte von --voice_answer_url und --voice_event_url Argumente durch Ersetzen von SUBDOMAIN durch den tatsächlichen Wert aus dem vorherigen Schritt ersetzen:

vonage apps:create "SwiftUICall" --voice_answer_url=https://SUBDOMAIN.loca.lt/voice/answer --voice_event_url=https://SUBDOMAIN.loca.lt/voice/event

Eine Datei namens vonage_app.json wird in Ihrem Projektverzeichnis erstellt und enthält die neu erstellte Vonage-Anwendungs-ID und den privaten Schlüssel. Eine private Schlüsseldatei mit dem Namen SwiftUICall.key wird ebenfalls erstellt. Verknüpfen Sie nun, nachdem Ihre Anwendung erstellt wurde, Ihre Vonage-Nummer mit Ihrer Anwendung:

vonage apps:link APPLICATION_ID --number=YOUR_VONAGE_NUMBER

Einen Benutzer erstellen

Die Vonage Conversation API hat das Konzept der Benutzer. Ein Benutzer stellt einen eindeutigen Benutzer Ihrer Anwendung dar und hat daher eine eindeutige ID. Auf diese Weise wird sich Ihre iOS-Anwendung bei den Vonage-Servern authentifizieren und von diesen identifiziert werden. Sie können die CLI verwenden, um einen Benutzer zu erstellen:

vonage apps:users:create "Alice"

Dadurch wird ein Benutzer mit dem Benutzernamen Alice zu Ihrer Anwendung hinzugefügt und seine eindeutige ID ausgegeben.

Ein JWT erstellen

Die Vonage Client SDKs verwenden JSON Web Tokens (JWTs) zur Authentifizierung. JWTs sind eine Methode zur sicheren Darstellung von Ansprüchen zwischen zwei Parteien. Mehr über JWTs erfahren Sie auf JWT.io oder die Ansprüche, die die Conversation API unterstützt. Wir werden den privaten Schlüssel, die Anwendungs-ID und den Benutzernamen aus den vorherigen Abschnitten verwenden, um das für Ihre iOS-Anwendung benötigte JWT zu erstellen. Auch dies wird über die CLI durchgeführt. Ersetzen Sie die APPLICATION_ID Variable durch die ID Ihrer Anwendung und PRIVATE_KEY durch den Namen der Datei Ihres privaten Schlüssels.

vonage jwt --app_id=APPLICATION_ID --subject=Alice --key_file=./PRIVATE_KEY --acl='{"paths":{"/*/users/**":{},"/*/conversations/**":{},"/*/sessions/**":{},"/*/devices/**":{},"/*/image/**":{},"/*/media/**":{},"/*/push/**":{},"/*/knocking/**":{},"/*/legs/**":{}}}'

Dadurch wird das JWT für den Benutzer Alice ausgegeben, das mit Ihrem privaten Schlüssel signiert wurde. Bewahren Sie diesen auf, da Sie ihn später benötigen werden.

Erstellen der iOS-Anwendung

Nachdem nun der Server und die Vonage-Anwendung eingerichtet sind, ist es an der Zeit, die iOS-Anwendung zu erstellen.

Ein Xcode-Projekt erstellen

Öffnen Sie Xcode und erstellen Sie ein neues Projekt, indem Sie auf Datei > Neu > Projekt gehen. Wählen Sie eine App-Vorlage und geben Sie ihr einen Namen. Wählen Sie SwiftUI für die Benutzeroberfläche, SwiftUI App für den Lebenszyklus und Swift für die Sprache - und schließlich einen Speicherort für Ihr Projekt.

Xcode project creation

Installieren Sie das Vonage Client SDK

Nachdem das Projekt nun erstellt wurde, können Sie das Vonage Client SDK als Abhängigkeit hinzufügen. Navigieren Sie in Ihrem Terminal zu dem Ort, an dem Sie das Projekt gespeichert haben, und führen Sie die folgenden Befehle aus.

  1. Führen Sie den pod init aus, um eine neue Poddatei für Ihr Projekt zu erstellen.

  2. Öffnen Sie die Poddatei in Xcode mit open -a Xcode Podfile.

  3. Aktualisieren Sie das Podfile, damit es VonageClientSDKVoice als eine Abhängigkeit.

# 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'

end
  1. Installieren Sie das SDK mit pod install.

  2. Öffnen Sie den neuen xcworkspace Datei in Xcode mit open SwiftUICall.xcworkspace.

Berechtigungen für das Mikrofon

Da die Anwendung das Mikrofon zum Tätigen von Anrufen verwendet, müssen Sie explizit um Erlaubnis bitten, dies zu tun. Der erste Schritt ist die Bearbeitung der Info.plist Datei. Dies ist eine Datei, die alle für die Anwendung erforderlichen Metadaten enthält. Fügen Sie der Datei einen neuen Eintrag hinzu, indem Sie den Mauszeiger über den letzten Eintrag in der Liste bewegen und auf die kleine + Schaltfläche, die erscheint. Wählen Sie Privacy - Microphone Usage Description aus der Dropdown-Liste und fügen Sie Microphone access required to make and receive audio calls. für seinen Wert ein. Den zweiten Schritt zur Beantragung von Mikrofonberechtigungen führen Sie später im Lernprogramm aus.

Erstellen der Modellklasse

Bevor Sie mit dem Aufbau der Benutzeroberfläche (UI) der App beginnen, werden Sie zunächst eine Modellklasse erstellen. Diese Klasse wird verwendet, um die Logik der App vom Ansichtscode zu trennen. In diesem Fall wird die Modellklasse die Delegatenaufrufe vom Client SDK verarbeiten und festlegen, wann die Anrufschaltfläche angezeigt werden soll. Am Anfang der ContentView.swift Datei importieren Sie das Client SDK und AVFoundation.

import SwiftUI
import AVFoundation
import VonageClientSDKVoice

Erstellen Sie dann am Ende der Datei eine neue Klasse namens CallModel:

final class CallModel: NSObject, ObservableObject, VGVoiceClientDelegate {

}

Definieren Sie innerhalb dieser Klasse die benötigten Eigenschaften und Hilfsfunktionen:

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 = ""
        }
    }
}

Die @Published Eigenschaft Wrapper ist die Grundlage dafür, dass die Benutzeroberfläche weiß, wann sie auf Änderungen in der Modellklasse reagieren muss. Dies wird alles für Sie erledigt, da die Klasse dem ObservedObject Protokoll entspricht. Die client Eigenschaft ist für den Vonage Voice Client, mit dem Sie Anrufe tätigen können. callId wird verwendet, um das Anrufobjekt zu speichern, und audioSession wird verwendet, um die Mikrofonberechtigung anzufordern. Konfigurieren Sie das Client SDK:

func initializeClient() {
    let config = VGClientConfig(region: .US)
    client.setConfig(config)
    client.delegate = self
}

Um die Abfrage der Mikrofonberechtigungen für die App zu vervollständigen, fügen Sie die folgende Funktion in die CallModel Klasse hinzu:

func requestPermissionsIfNeeded() {
    if audioSession.recordPermission != .granted {
        audioSession.requestRecordPermission { (isGranted) in
            print("Microphone permissions \(isGranted)")
        }
    }
}

Dabei wird zunächst geprüft, ob die Berechtigungen bereits erteilt wurden; wenn nicht, werden sie angefordert und das Ergebnis auf der Konsole ausgegeben. Als nächstes müssen Sie sich mit dem Client SDK als Benutzer Alice anmelden. Fügen Sie dazu die folgende Funktion in die CallModel Klasse hinzu und ersetzen Sie ALICE_JWT durch das JWT von vorhin:

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")
        }
    }
}

Diese Funktion prüft, ob der Client bereits angemeldet ist; falls nicht, verwendet sie das JWT, das Sie zuvor für die Anmeldung generiert haben, und setzt den Delegaten für den Client auf diese Klasse. Die VGVoiceClientDelegate ist die Art und Weise, wie das Client SDK Änderungen mit den Vonage-Servern zurück an Ihre Anwendung kommuniziert. Als nächstes implementieren Sie die erforderlichen Delegatenfunktionen.

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) {}

Bei einem Sitzungsfehler wird die status Eigenschaft aktualisiert, und wenn der Aufruf endet, wird der Zustand des Modells zurückgesetzt. Die folgenden zwei Funktionen, die Sie hinzufügen müssen, ermöglichen es Ihrer Anwendung, Aufrufe zu tätigen und zu beenden. Fügen Sie die folgenden Funktionen hinzu.

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()
        }
    }
}

Die Funktion callNumber Funktion verwendet das Client SDK, um die Nummer aus der number Eigenschaft. Dabei wird die answer_url von weiter oben im Lernprogramm. Vonage wird dann einen HTTP-Anruf an Ihre answer_url mit der Nummer aus der iOS-Anwendung, die ein Call Control Object mit Anweisungen für Vonage zurückgibt, um Ihre Anwendung mit der Nummer zu verbinden. Wenn dies alles erfolgreich war, gibt das Client SDK eine Anruf-ID zurück, die in der Klasse gespeichert wird. Die Funktion endCall Funktion legt den Anruf auf, setzt die callId Eigenschaft auf null und setzt den veröffentlichten isCalling Boolean auf false zurück, damit die Benutzeroberfläche aktualisiert werden kann.

Die letzte Funktion, die Sie der Datei CallModel ruft auf. initializeClient, requestPermissionsIfNeeded, und loginIfNeeded Funktionen.

func setup() {
    initializeClient()
    requestPermissionsIfNeeded()
    loginIfNeeded()
}

Erstellen Sie die Benutzeroberfläche

Die Benutzeroberfläche besteht aus einem Text Objekt zur Anzeige des Status, einem TextField Objekt für die Eingabe der Nummer und einem Paar von Button Objekten zum Starten und Beenden von Anrufen. Fügen Sie eine Eigenschaft für die CallModel Klasse, die Sie zuvor erstellt haben, zu der ContentView struct hinzu und verwenden Sie sie, um den Status des Client SDK anzuzeigen.

struct ContentView: View {
    @StateObject var callModel = CallModel()
    
    var body: some View {
        VStack {
            Text(callModel.status)
        }
        .animation(.default)
        .onAppear(perform: self.callModel.setup)
    }
}

Wenn die Ansicht erscheint, ruft sie die Funktion setup Funktion der Modellklasse auf, die die Mikrofonberechtigungen anfordert und den Client anmeldet. Dadurch wird die Eigenschaft status Eigenschaft der Modellklasse aktualisiert, und die Änderung ihres Wertes wird die Funktion ContentView zu aktualisieren!

Da der Client nun angemeldet ist, können Sie die restlichen veröffentlichten Eigenschaften der Modellklasse verwenden, um den Rest der Benutzeroberfläche zu erstellen. Fügen Sie den folgenden Codeblock zum VStack hinzu.

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)
        }
    }
}

Die TextField wird zur Ansicht animiert, wenn der Client verbunden ist. Der Wert des TextField ist gebunden an die number Eigenschaft der Modellklasse gebunden. Dies geschieht durch die Verwendung des $ Zeichen. Sobald eine gültige Länge der Nummer eingegeben wurde, werden die Bedingungen für die Anzeige der Anrufschaltfläche erfüllt, und sobald ein Anruf begonnen hat, werden die Bedingungen nicht mehr erfüllt, aber die Bedingungen für die Schaltfläche "Anruf beenden" werden erfüllt. Es wird also immer nur eine Schaltfläche angezeigt, und die gesamte Aktualisierung der Benutzeroberfläche wird für Sie übernommen!

Führen Sie Ihre Anwendung aus

Wenn Sie das Projekt starten (CMD + R), werden Sie zunächst aufgefordert, Mikrofonrechte zuzulassen. Sie können dann eine Nummer eingeben und anrufen! Das Format der Numbers sollte in der E.164 Format sein.

Making a call

Was kommt als nächstes?

Sie finden das fertige Projekt auf GitHub. Mit dem Client SDK können Sie noch viel mehr tun. Erfahren Sie mehr auf developer.vonage.com.

Teilen Sie:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiVonage Ehemaliges Teammitglied

Abdul ist ein Developer Advocate für Vonage. Er hat einen Hintergrund als iOS-Ingenieur im Bereich Verbraucherprodukte. In seiner Freizeit fährt er gerne Rad, hört Musik und berät diejenigen, die gerade ihre Reise in die Technologiebranche beginnen.