AzureCommunicationUI/AzureCommunicationUIDemoApp/Sources/AppDelegate.swift (144 lines of code) (raw):

// // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. // import UIKit import AppCenter import AppCenterCrashes import CallKit import AzureCommunicationUICalling import PushKit import OSLog import AVFoundation @main class AppDelegate: UIResponder, UIApplicationDelegate, PKPushRegistryDelegate, UNUserNotificationCenterDelegate { static var orientationLock: UIInterfaceOrientationMask = .all let envConfigSubject = EnvConfigSubject() func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. AppCenter.start(withAppSecret: envConfigSubject.appCenterSecret, services: [Crashes.self]) self.setupNotifications(application: application) return true } public func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { return true } // MARK: UISceneSession Lifecycle func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return AppDelegate.orientationLock } func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { guard type == .voIP else { return } let tokenString = self.tokenString(from: pushCredentials.token) print("VoIP Token: \(tokenString)") if let entryViewController = findEntryViewController() { entryViewController.registerDeviceToken(deviceCode: pushCredentials.token) } } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { print("pushRegistry payload: \(payload.dictionaryPayload)") os_log("pushRegistry payload: \(payload.dictionaryPayload)") if isAppInForeground() { os_log("calling demo app: app is in foreground") if let entryViewController = findEntryViewController() { os_log("calling demo app: onPushNotificationReceived") entryViewController.onPushNotificationReceived(dictionaryPayload: payload.dictionaryPayload) } } else { os_log("calling demo app: app is not in foreground") let pushInfo = PushNotification(data: payload.dictionaryPayload) let providerConfig = CXProviderConfiguration() providerConfig.supportsVideo = true providerConfig.maximumCallGroups = 1 providerConfig.maximumCallsPerCallGroup = 1 providerConfig.includesCallsInRecents = true providerConfig.supportedHandleTypes = [.phoneNumber, .generic] let callKitOptions = CallKitOptions(providerConfig: providerConfig, isCallHoldSupported: true, provideRemoteInfo: incomingCallRemoteInfo, configureAudioSession: configureAudioSession) CallComposite.reportIncomingCall(pushNotification: pushInfo, callKitOptions: callKitOptions) { result in if case .success = result { DispatchQueue.global().async { if let entryViewController = self.findEntryViewController() { os_log("calling demo app: onPushNotificationReceivedBackgroundMode") entryViewController.onPushNotificationReceivedBackgroundMode( dictionaryPayload: payload.dictionaryPayload) } } } else { os_log("calling demo app: failed on reportIncomingCall") } } } } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { self.voipRegistration() } public func configureAudioSession() -> Error? { let audioSession = AVAudioSession.sharedInstance() var configError: Error? do { try audioSession.setCategory(.playAndRecord) } catch { configError = error } return configError } public func incomingCallRemoteInfo(info: Caller) -> CallKitRemoteInfo { let cxHandle = CXHandle(type: .generic, value: "Incoming call") var remoteInfoDisplayName = envConfigSubject.callkitRemoteInfo if remoteInfoDisplayName.isEmpty { remoteInfoDisplayName = info.displayName } let callKitRemoteInfo = CallKitRemoteInfo(displayName: remoteInfoDisplayName, handle: cxHandle) return callKitRemoteInfo } private func isAppInForeground() -> Bool { let appState = UIApplication.shared.applicationState switch appState { case .active: return true default: return false } } // Register for VoIP notifications private func voipRegistration() { let mainQueue = DispatchQueue.main // Create a push registry object let voipRegistry = PKPushRegistry(queue: mainQueue) // Set the registry's delegate to self voipRegistry.delegate = self // Set the push type to VoIP voipRegistry.desiredPushTypes = [PKPushType.voIP] } private func tokenString(from data: Data) -> String { return data.map { String(format: "%02.2hhx", $0) }.joined() } private func findEntryViewController() -> EntryViewController? { guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = scene.windows.first, let rootViewController = window.rootViewController as? UINavigationController, let entryViewController = rootViewController.viewControllers.first as? EntryViewController else { return nil } return entryViewController } private func setupNotifications(application: UIApplication) { UNUserNotificationCenter.current().delegate = self UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, _) in if granted { DispatchQueue.main.async { application.registerForRemoteNotifications() } } } } }