Sie können mobile Apps auf verschiedene Arten für die Verwendung mit der Contact Center AI Platform (CCAI Platform) einrichten, unter anderem mit Flutter. Auf dieser Seite erfahren Sie, wie Sie das iOS SDK mit Flutter in eine iOS-App einbinden.
Hinweise
Bevor Sie die Anleitung auf dieser Seite befolgen, müssen Sie zuerst die Anleitung unter Mit Flutter einbinden befolgen.
SDK mit CocoaPods einbinden
So binden Sie das SDK mit CocoaPods ein:
Öffnen Sie
Podfileund fügen Sie dem Ziel Abhängigkeiten hinzu, wie im folgenden Codebeispiel:UJETPodspec = { :podspec => 'https://sdk.ujet.co/ios/UJET.podspec' } pod 'UJET', UJETPodspec pod 'UJET/Cobrowse', UJETPodspecWechseln Sie im Terminal in das Verzeichnis
example/iosund führen Sie den Befehlpod installaus, um Abhängigkeiten zu installieren.
iOS-Push-Benachrichtigungen einrichten
So richten Sie iOS-Push-Benachrichtigungen ein:
Öffnen Sie
example/ios/Runner.xcodeprojin Xcode.Fügen Sie Ihrer
AppDelegate.swift-Datei den folgenden Code hinzu:import PushKit import UJETKit @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Register Flutter Plugins GeneratedPluginRegistrant.register(with: self) UJETModule.register(with: self.registrar(forPlugin: "UjetModule")!) UJETModule.onInitDone = { // setup push notification let voipRegistry = PKPushRegistry(queue: DispatchQueue.main) voipRegistry.desiredPushTypes = Set([PKPushType.voIP]) voipRegistry.delegate = self UNUserNotificationCenter.current().delegate = self } return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } // Extension for Push Notification extension AppDelegate { func tokenFromData(data: Data) -> String { return data.map { String(format: "%02x", $0) }.joined() } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { print("apns token: ", tokenFromData(data: deviceToken)) UJET.updatePushToken(deviceToken, type: .APN) } override func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { UJET.updatePushToken(nil, type: .APN) } override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { handleNotification(userInfo: userInfo, completion: nil) } } // MARK: PushKit extension AppDelegate: PKPushRegistryDelegate { func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { print("voip token: ", tokenFromData(data: credentials.token)) if type == .voIP { UJET.updatePushToken(credentials.token, type: .voIP) } } func pushRegistry(_ registry: PKPushRegistry, didInvalidatePushTokenFor type: PKPushType) { if type == .voIP { UJET.updatePushToken(nil, type: .voIP) } } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { if type == .voIP { handleNotification(userInfo: payload.dictionaryPayload, completion: completion) } } } extension AppDelegate { // handle push received in foreground state override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo handleNotification(userInfo: userInfo, completion: nil) } // handle push received and tapped in background state override func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo handleNotification(userInfo: userInfo, completion: nil) } } private func handleNotification(userInfo: [AnyHashable: Any], completion: (() -> Void)?) { if userInfo["ujet"] != nil { UJET.receivedNotification(userInfo, completion: completion) } else { // Handle your notification here completion?() } }Wählen Sie Ihr
.xcodeprojund dann Ihr App-Zielvorhaben aus. Fügen SiePushKit.frameworkim AbschnittFrameworks, Libraries, and Embedded Contenthinzu.
Deeplinks einrichten
Fügen Sie den folgenden Code hinzu, um Deeplinks einzurichten:
// Extension for deep linking
extension AppDelegate {
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
print("Open app with url: \(url.absoluteString)")
return self.handleRouting(url)
}
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// Universal links
if NSUserActivityTypeBrowsingWeb == userActivity.activityType {
return self.handleRouting(userActivity.webpageURL!)
} else if userActivity.activityType == "INStartAudioCallIntent" {
// Open app from Call history
UJET.start(with: UJETStartOptions())
return true
}
return false
}
func handleRouting(_ url: URL) -> Bool {
let availableSchema = [
"ujetrn", // TODO: Change to your custom URL scheme. Config from Portal > Developer Settings > Mobile App > Enable Send SMS to Download App > iOS App > URL
"https" // universal link
]
let availableHostAndPath = [
"call", // custom URL scheme
"ujet.cx/app" // universal link,
]
if !(availableSchema.contains(url.scheme ?? "")) {
return false
}
let hostAndPath = String.init(format: "%@%@", url.host ?? "", url.path)
if !(availableHostAndPath.contains(hostAndPath)) {
return false
}
// ujet://call?call_id={call_id}&nonce={nonce}
// https://ujet.co/app?call_id={call_id}&nonce={nonce}
let urlComponents: URLComponents? = URLComponents(url: url, resolvingAgainstBaseURL: false)
let queryItems = urlComponents?.queryItems
let callId = value(forKey: "call_id", fromQueryItems: queryItems)
// validate call ID
if !isValidCallId(callId) {
return false
}
guard let nonce = value(forKey: "nonce", fromQueryItems: queryItems) else {
return false
}
let options = UJETStartOptions.init(callId: callId!, nonce: nonce)
UJET.start(with: options)
return true
}
func value(forKey key: String?, fromQueryItems queryItems: [URLQueryItem]?) -> String? {
let predicate = NSPredicate(format: "name=%@", key ?? "")
let filtered = (queryItems as NSArray?)?.filtered(using: predicate) as? [URLQueryItem]
let queryItem: URLQueryItem? = filtered?.first
return queryItem?.value
}
func isValidCallId(_ callId: String?) -> Bool {
if (callId ?? "").isEmpty {
return false
}
let nonNumbers = CharacterSet.decimalDigits.inverted
let r = callId?.rangeOfCharacter(from: nonNumbers)
return r == nil
}
}