@@ -30,12 +30,17 @@ var incomingCallData: [Meeting] = [] // have to keep this in centralised place
30
30
@UIApplicationMain
31
31
class AppDelegate : UIResponder , UIApplicationDelegate {
32
32
var window : UIWindow ?
33
-
33
+ var callKitManager : CallKitManager ?
34
+ class var shared : AppDelegate {
35
+ return UIApplication . shared. delegate as! AppDelegate
36
+ }
34
37
func application( _ application: UIApplication , didFinishLaunchingWithOptions launchOptions: [ UIApplication . LaunchOptionsKey : Any ] ? ) -> Bool {
35
38
window = UIWindow ( )
36
39
navigateToLoginViewController ( )
37
40
window? . makeKeyAndVisible ( )
38
-
41
+ if ( callKitManager == nil ) {
42
+ callKitManager = CallKitManager ( )
43
+ }
39
44
UNUserNotificationCenter . current ( ) . requestAuthorization ( options: [ . sound, . alert, . badge] ) { granted, error in
40
45
if granted {
41
46
print ( " Approval granted to send notifications " )
@@ -46,7 +51,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
46
51
application. registerForRemoteNotifications ( )
47
52
self . voipRegistration ( )
48
53
UNUserNotificationCenter . current ( ) . delegate = self
49
-
50
54
return true
51
55
}
52
56
@@ -60,24 +64,57 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
60
64
}
61
65
62
66
func navigateToLoginViewController( ) {
63
- window? . rootViewController = LoginViewController ( )
67
+ if !( UIApplication . shared. topViewController ( ) is CallViewController ) {
68
+ window? . rootViewController = LoginViewController ( )
69
+ }
64
70
}
65
71
66
72
// Register for VoIP notifications
67
73
func voipRegistration( ) {
68
74
// Create a push registry object
69
- let mainQueue = DispatchQueue . main
70
- let voipRegistry = PKPushRegistry ( queue: mainQueue)
71
- voipRegistry. delegate = self
72
- voipRegistry. desiredPushTypes = [ PKPushType . voIP]
75
+ let voipRegistry = PKPushRegistry ( queue: . main)
76
+ voipRegistry. delegate = self
77
+ voipRegistry. desiredPushTypes = [ PKPushType . voIP]
73
78
}
74
79
}
75
-
80
+
76
81
extension AppDelegate : UNUserNotificationCenterDelegate {
77
82
func userNotificationCenter( _ center: UNUserNotificationCenter , willPresent notification: UNNotification , withCompletionHandler completionHandler: @escaping ( UNNotificationPresentationOptions ) -> Void ) {
78
83
completionHandler ( . alert)
79
84
}
80
85
86
+ func application( _ application: UIApplication , didReceiveRemoteNotification userInfo: [ AnyHashable : Any ] , fetchCompletionHandler completionHandler: @escaping ( UIBackgroundFetchResult ) -> Void ) {
87
+ guard let authType = UserDefaults . standard. string ( forKey: " loginType " ) else { return }
88
+ if authType == " jwt " {
89
+ initWebexUsingJWT ( )
90
+ } else if authType == " token " {
91
+ initWebexUsingToken ( )
92
+ } else {
93
+ initWebexUsingOauth ( )
94
+ }
95
+ DispatchQueue . main. async {
96
+ webex. initialize { success in
97
+ if success {
98
+ do {
99
+ let data = try JSONSerialization . data ( withJSONObject: userInfo, options: . prettyPrinted)
100
+ let string = String ( data: data, encoding: . utf8) ?? " "
101
+ print ( " Received push: string " )
102
+ print ( string)
103
+ webex. phone. processPushNotification ( message: string) { error in
104
+ if let error = error {
105
+ print ( " processPushNotification error " + error. localizedDescription)
106
+ }
107
+ }
108
+ }
109
+ catch ( let error) {
110
+ print ( error. localizedDescription)
111
+ }
112
+
113
+ }
114
+ }
115
+ }
116
+ }
117
+
81
118
func userNotificationCenter( _ center: UNUserNotificationCenter , didReceive response: UNNotificationResponse , withCompletionHandler completionHandler: @escaping ( ) -> Void ) {
82
119
guard let handler = window? . rootViewController as? PushNotificationHandler else {
83
120
print ( " RootViewController must confirm to a PushNotificationHandler " )
@@ -135,4 +172,85 @@ extension AppDelegate: PKPushRegistryDelegate {
135
172
func pushRegistry( _ registry: PKPushRegistry , didInvalidatePushTokenFor type: PKPushType ) {
136
173
print ( " pushRegistry:didInvalidatePushTokenForType: \( type) " )
137
174
}
175
+
176
+ func pushRegistry( _ registry: PKPushRegistry , didReceiveIncomingPushWith payload: PKPushPayload , for type: PKPushType , completion: @escaping ( ) -> Void ) {
177
+ debugPrint ( " Received push: voIP " )
178
+ debugPrint ( payload. dictionaryPayload)
179
+
180
+ if type == . voIP {
181
+ // Report the call to CallKit, and let it display the call UI.
182
+ guard let bsft = payload. dictionaryPayload [ " bsft " ] as? [ String : Any ] , let sender = bsft [ " sender " ] as? String else {
183
+ print ( " payload not valid " )
184
+ return
185
+ }
186
+
187
+ callKitManager? . reportIncomingCallFor ( uuid: UUID ( ) , sender: sender) {
188
+ completion ( )
189
+ self . establishConnection ( payload: payload)
190
+ }
191
+ }
192
+ }
193
+
194
+ func establishConnection( payload: PKPushPayload ) {
195
+ guard let authType = UserDefaults . standard. string ( forKey: " loginType " ) else { return }
196
+ if authType == " jwt " {
197
+ initWebexUsingJWT ( )
198
+ } else if authType == " token " {
199
+ initWebexUsingToken ( )
200
+ } else {
201
+ initWebexUsingOauth ( )
202
+ }
203
+ DispatchQueue . main. async {
204
+ webex. initialize { [ weak self] success in
205
+ if success {
206
+ webex. phone. onIncoming = { [ weak self] call in
207
+ self ? . callKitManager? . updateCall ( call: call)
208
+ }
209
+ do {
210
+ let data = try JSONSerialization . data ( withJSONObject: payload. dictionaryPayload, options: . prettyPrinted)
211
+ let string = String ( data: data, encoding: . utf8) ?? " "
212
+ print ( " Received push: string " )
213
+ print ( string)
214
+ webex. phone. processPushNotification ( message: string) { error in
215
+ if let error = error {
216
+ print ( " processPushNotification error " + error. localizedDescription)
217
+ }
218
+ }
219
+ }
220
+ catch ( let error) {
221
+ print ( error. localizedDescription)
222
+ }
223
+
224
+ } else {
225
+ print ( " Failed to initialise WebexSDK on receiving incoming call push notification " )
226
+ }
227
+ }
228
+ }
229
+ }
230
+
231
+ func initWebexUsingOauth( ) {
232
+ guard let path = Bundle . main. path ( forResource: " Secrets " , ofType: " plist " ) else { return }
233
+ guard let keys = NSDictionary ( contentsOfFile: path) else { return }
234
+ let clientId = keys [ " clientId " ] as? String ?? " "
235
+ let clientSecret = keys [ " clientSecret " ] as? String ?? " "
236
+ let redirectUri = keys [ " redirectUri " ] as? String ?? " "
237
+ let scopes = " spark:all " // spark:all is always mandatory
238
+
239
+ // See if we already have an email stored in UserDefaults else get it from user and do new Login
240
+ if let email = EmailAddress . fromString ( UserDefaults . standard. value ( forKey: " userEmail " ) as? String ) {
241
+ // The scope parameter can be a space separated list of scopes that you want your access token to possess
242
+ let authenticator = OAuthAuthenticator ( clientId: clientId, clientSecret: clientSecret, scope: scopes, redirectUri: redirectUri, emailId: email. toString ( ) )
243
+ webex = Webex ( authenticator: authenticator)
244
+ return
245
+ }
246
+ }
247
+
248
+ func initWebexUsingJWT( ) {
249
+ webex = Webex ( authenticator: JWTAuthenticator ( ) )
250
+ }
251
+
252
+ func initWebexUsingToken( ) {
253
+ webex = Webex ( authenticator: TokenAuthenticator ( ) )
254
+ }
138
255
}
256
+
0 commit comments