https://d226lax1qjow5r.cloudfront.net/blog/blogposts/how-to-make-outbound-calls-using-ios-callkit/ios-callkit_outbound-call.png

Wie man mit iOS CallKit ausgehende Anrufe tätigt

Zuletzt aktualisiert am October 18, 2023

Lesedauer: 5 Minuten

In diesem Tutorial werden Sie eine SwiftUI-Anwendung erstellen, die mit dem Vonage Client SDK und CallKit Anrufe tätigen kann. CallKit ermöglicht es Ihnen, Ihre iOS-Anwendung in das System zu integrieren. Wenn Sie ausgehende Anrufe tätigen, wird der Anrufverlauf Ihrer Anwendung in der iOS-Telefon-App verfügbar sein.

Voraussetzungen

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

  • Ein Apple Developer-Konto und ein iOS-Gerät

  • Xcode 12 und Swift 5 oder höher.

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

Übersicht

Zunächst werden Sie einen Server bereitstellen, um eine Vonage-Anwendung, Benutzer, JWT-Generierung und Webhooks zu erstellen. Anschließend passen Sie eine iOS-Anwendung an, die mithilfe des Vonage Client SDK Anrufe über CallKit tätigt.

Einsetzen des Servers

Dieses Projekt wird den Vonage Cloud Runtime-Marktplatz um einen Client SDK Voice Server auf der Vonage-Infrastruktur einzusetzen. Öffnen Sie den Client SDK Voice-Beispielserver Produktseite. Öffnen Sie die Registerkarte "Deploy Code", und wenn Sie sich noch nicht angemeldet haben, tun Sie dies jetzt.

Geben Sie einen Namen für die Bereitstellung ein und wählen Sie eine Region. Klicken Sie dann auf die Schaltfläche "Code bereitstellen".

Client SDK Voice Sample Server "Deploy Code" pageClient SDK Voice Sample Server "Deploy Code" page

Um die Sprach-API zu nutzen, müssen Sie eine Vonage-Nummer kaufen und der Anwendung zuweisen. Klicken Sie auf "Nummer zuweisen", um Ihre bestehenden Nummern einzusehen oder eine neue Nummer zu kaufen. Klicken Sie anschließend auf "Weiter".

Assign number popupAssign number popup

Sobald die Bereitstellung abgeschlossen ist, klicken Sie auf die Schaltfläche "Starten". Dadurch wird die Serveranwendung in Ihrem Browser geöffnet, wo Sie mehr über die Funktionsweise des Servers erfahren können. Um mit dem Lernprogramm fortzufahren, müssen Sie einen Benutzer anlegen. Mit Benutzern identifizieren Sie eine Anwendung, die das Vonage Client SDK mit den Vonage APIs ausführt.

Client SDK Voice Sample Server landing pageClient SDK Voice Sample Server landing page

Erstellen Sie einen Benutzer namens "Alice" und generieren Sie ein JWT. Die Client-SDKs verwenden JWT zur Authentifizierung bei Vonage. Wenn Sie einen Anruf an die Vonage-Nummer tätigen, die Sie der Anwendung zuvor zugewiesen haben, wird Vonage eine Anfrage an diesen Server stellen, der ein Objekt zur Anrufsteuerung zurückgibt, das den eingehenden Anruf mit dem Benutzer "Alice" verbindet.

Generating a JWT for a user on the Client SDK Voice Sample ServerGenerating a JWT for a user on the Client SDK Voice Sample Server

Download des Starterprojekts

Dieses Tutorial wird auf einem bestehenden Projekt aufgebaut. Wenn Sie mit dem Vonage Client SDK noch nicht vertraut sind, empfehlen wir Ihnen, die Anleitung Wie man mit SwiftUI Telefonanrufe tätigt Blog-Beitrag. Wenn Sie bereit sind, können Sie das Starterprojekt von GitHub klonen, indem Sie diesen Befehl in Ihrem Terminal verwenden:

git clone git@github.com:Vonage-Community/blog-clientsdk-ios_swift-swiftui_app_to_phone.git

Wechseln Sie dann in das Verzeichnis des Projekts und installieren Sie die VonageClientSDKVoice Abhängigkeit:

cd blog-clientsdk-ios_swift-swiftui_app_to_phone
pod install

Nach Fertigstellung können Sie das Projekt mit diesem Befehl öffnen:

xed .

Aktualisieren des Starterprojekts

Da Sie mit CallKit Anrufe tätigen werden, können Sie die loginIfNeeded Funktion in der ContentView.swift Datei aktualisieren, um das isUsingCallKit Flagge zu entfernen. Das SDK setzt diesen Wert standardmäßig auf true. Hier können Sie auch den JWT für den Benutzer "Alice" einfügen, den Sie zuvor erstellt haben:

func loginIfNeeded() {
    guard status != "Connected" else { return }
    client.createSession("ey...") { error, sessionId in
        if let error {
            self.updateStatus(error.localizedDescription)
        } else {
            self.updateStatus("Connected")
        }
    }
}

Hinzufügen des VoIP-Hintergrundmodus

CallKit erfordert, dass Sie den VoIP-Hintergrundmodus hinzufügen. Vergewissern Sie sich, dass Sie in Ihrem Apple-Entwicklerkonto in Xcode über die Einstellungen angemeldet sind. Wenn ja, wählen Sie Ihr Ziel aus und wählen Sie dann Signierung & Fähigkeiten:

Add capability button in XcodeAdd capability button in Xcode

Wählen Sie dann die Schaltfläche "Fähigkeit hinzufügen" und die Fähigkeit "Hintergrundmodi". Wählen Sie unter der Fähigkeit Background Modes Sprache über IP:

Adding the VoIP background mode in XcodeAdding the VoIP background mode in Xcode

Verknüpfung des CallKit-Frameworks

Verknüpfen Sie das CallKit-Framework mit Ihrem Projekt, indem Sie es unter Frameworks, Bibliotheken und eingebettete Inhalte unter Allgemein:

Adding the CallKit framework in XcodeAdding the CallKit framework in Xcode

Erstellen des Provider-Managers

Nun werden Sie eine Klasse erstellen, ProviderManager. CallKit übernimmt die Kommunikation zwischen Ihrer Anwendung und dem System über die CXProvider. Erstellen Sie eine neue Swift-Datei (CMD + N) mit dem Namen ProviderManager:

import CallKit
import Foundation
import VonageClientSDKVoice

protocol ProviderManagerDelegate: AnyObject {
    func callReported(_ providerManager: ProviderManager, callUUID: UUID)
    func providerReset()
}

final class ProviderManager: NSObject {
    private static var providerConfiguration: CXProviderConfiguration = {
        let providerConfiguration = CXProviderConfiguration()
        providerConfiguration.maximumCallsPerCallGroup = 1
        providerConfiguration.supportedHandleTypes = [.generic, .phoneNumber]
        return providerConfiguration
    }()
    
    private let provider = CXProvider(configuration: ProviderManager.providerConfiguration)
    weak var delegate: ProviderManagerDelegate?
    
    override init() {
        super.init()
        provider.setDelegate(self, queue: nil)
    }
    
    public func reportOutgoingCall(callUUID: UUID) {
        provider.reportOutgoingCall(with: callUUID, connectedAt: .now)
    }
    
    public func reportFailedCall(callUUID: UUID) {
        provider.reportCall(with: callUUID, endedAt: .now, reason: .failed)
    }
    
    public func reportEndedCall(callUUID: UUID) {
        provider.reportCall(with: callUUID, endedAt: .now, reason: .remoteEnded)
    }
}

Der obige Code umfasst die Erstellung einer CXProvider und einige Hilfsfunktionen, um den Status von Aufrufen an das System zu melden. Die ProviderManagerDelegate ist hier ebenfalls definiert.

Die Umsetzung derCXProviderDelegate

Die Website CXProviderDelegate informiert Sie über Anrufe aus dem System. Fügen Sie eine Erweiterung zu dem ProviderManager die den Delegaten in derselben Datei implementiert:

extension ProviderManager: CXProviderDelegate {
    func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
        provider.reportOutgoingCall(with: action.callUUID, startedConnectingAt: .now)
        delegate?.callReported(self, callUUID: action.callUUID)
        action.fulfill()
    }
    
    func providerDidReset(_ provider: CXProvider) {
        delegate?.providerReset()
    }
    
    func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
        VGVoiceClient.enableAudio(audioSession)
    }
    
    func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
        VGVoiceClient.disableAudio(audioSession)
    }
}

Wenn ein Benutzer eine Nummer eingibt und einen Anruf startet, fordert die App CallKit an, den Anruf zu starten. Wenn diese Anfrage erfolgreich ist, wird die CXStartCallAction Delegatenfunktion aufgerufen, die den ausgehenden Anruf meldet. Es ist sehr wichtig zu beachten, dass VGVoiceClient.enableAudio/VGVoiceClient.disableAudio hier mit der vom CallKit bereitgestellten Audiositzung aufgerufen wird CXProviderDelegate.

Die Aktualisierung derCallModel

Nun, da die ProviderManager eingerichtet ist, können Sie nun die CallModel Klasse aktualisieren, um sie zu verwenden. Öffnen Sie die ContentView.swift Datei und ersetzen Sie die Variablen am Anfang der CallModel Klasse:

final class CallModel: NSObject, ObservableObject, VGVoiceClientDelegate {

    @Published var status: String = ""
    @Published var isCalling: Bool = false
    private let client = VGVoiceClient()
    var number: String = ""


    private var callId: (vonage: String?, callkit: UUID?)
    private let callController = CXCallController()
    private let providerManager = ProviderManager()
    private let audioSession = AVAudioSession.sharedInstance()

    ...
}

callId wurde nun zu einem Tupel geändert, um das Mapping von einer Vonage Call ID zu einer CallKit Call UUID zu verwalten, providerManager wurde hinzugefügt, ebenso wie callController. callController ist eine Instanz von CXCallControllerdie verwendet wird, um das System aufzufordern, einen Anruf zu starten.

Die Aktualisierung derstartCall Funktion

Die Funktion startCall Funktion muss nun aktualisiert werden, um einen Aufruf über die callController aufzurufen, wenn der Benutzer auf die Funktion "Aufruf starten" klickt. Ersetzen Sie die bestehende Funktion durch die neue:

func startCall() {
    isCalling = true
    let handle = CXHandle(type: .phoneNumber, value: number)
    self.callId.callkit = UUID()
    
    let startCallAction = CXStartCallAction(call: self.callId.callkit!, handle: handle)
    let transaction = CXTransaction(action: startCallAction)
    callController.request(transaction) { _ in }
}

Diese neue Funktion erstellt eine UUID, da CallKit eine Möglichkeit zur Identifizierung des Anrufs benötigt, aber Sie erhalten die Vonage-Anruf-ID erst, wenn das SDK einen Anruf tätigt. Dann wird eine CXStartCallAction in einer CXTransaction verwendet, um einen Anruf anzufordern. Dies ruft die CXStartCallAction Funktion auf dem CXProviderDelegate die Sie zuvor definiert haben.

Die Aktualisierung derendCall Funktion

In ähnlicher Weise muss die endCall Funktion muss für die Verwendung mit CallKit aktualisiert werden. Ersetzen Sie die bestehende Funktion durch die neue:

func endCall() {
    client.hangup(callId.vonage!) { error in
        if error == nil {
            if let callkitUUID = self.callId.callkit {
                let transaction = CXTransaction(action: CXEndCallAction(call: callkitUUID))
                self.callController.request(transaction) { _ in }
            }
        }
    }
}

Diese neue Funktion erzeugt eine CXEndCallAction Aktion, die in einer CXTransaction verwendet wird, um die Beendigung des Anrufs anzufordern. Durch die Aufforderung, den Anruf zu beenden, kann das System die Anrufdauer genau berechnen. Sie müssen auch den Fall behandeln, dass der Anruf aus der Ferne beendet wird. Aktualisieren Sie die didReceiveHangupForCall Funktion auf dem VGVoiceClientDelegate Delegaten:

func voiceClient(_ client: VGVoiceClient, didReceiveHangupForCall callId: VGCallId, withQuality callQuality: VGRTCQuality, reason: VGHangupReason) {
    if let callkitUUID = self.callId.callkit {
        providerManager.reportEndedCall(callUUID: callkitUUID)
    }
    resetState()
}

Auch hier wurde sichergestellt, dass das Ende des Anrufs über die providerManageran das System gemeldet wird, damit die Gesprächsdauer genau berechnet werden kann.

Die Umsetzung derProviderManagerDelegate

Schließlich implementieren Sie die ProviderManagerDelegate damit die providerManager in der Lage ist, Änderungen zurück an den CallModel:

extension CallModel: ProviderManagerDelegate {
    func callReported(_ providerManager: ProviderManager, callUUID: UUID) {
        client.serverCall(["to": number]) { error, callId in
            if error == nil {
                providerManager.reportOutgoingCall(callUUID: callUUID)
                self.callId.vonage = callId
            } else {
                providerManager.reportFailedCall(callUUID: callUUID)
            }
        }
    }
    
    func providerReset() {
        resetState()
    }
}

Wenn die providerManager den Anruf erfolgreich an das System gemeldet hat, erstellt diese Delegatenfunktion einen Anruf unter Verwendung des Vonage Client SDK. Auch hier wird sowohl im Erfolgs- als auch im Fehlerfall die providerManager verwendet, um den Anrufstatus an das System zu melden. Jetzt können Sie einen Anruf in der App tätigen, indem Sie das Xcode-Projekt auf einem physischen Gerät ausführen. Wenn Sie sich die letzten Anrufe in der Telefon-App auf iOS ansehen, sollten Sie Ihren Anruf und den Namen der App sehen. Wenn Sie auf das Info-Symbol klicken, können Sie auch die Dauer des Anrufs sehen.

Call log from phone appCall log from phone app

Was kommt als Nächstes?

Sie finden das fertige Projekt auf GitHub. Mit dem Client SDK und CallKit können Sie noch viel mehr tun; Sie können CallKit für ausgehende Anrufe verwenden. Erfahren Sie mehr über das Client SDK auf der Vonage Client SDK Übersicht und CallKit auf developer.apple.com.

Teilen Sie:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiSenior Advocate für Entwickler

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.