diff options
Diffstat (limited to 'Example/Messaging/Sample/iOS/AppDelegate.swift')
-rw-r--r-- | Example/Messaging/Sample/iOS/AppDelegate.swift | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/Example/Messaging/Sample/iOS/AppDelegate.swift b/Example/Messaging/Sample/iOS/AppDelegate.swift new file mode 100644 index 0000000..89a5120 --- /dev/null +++ b/Example/Messaging/Sample/iOS/AppDelegate.swift @@ -0,0 +1,153 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import UIKit +import FirebaseCore +import FirebaseMessaging +import UserNotifications + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + static let isWithinUnitTest: Bool = { + if let testClass = NSClassFromString("XCTestCase") { + return true + } else { + return false + } + }() + + static var hasPresentedInvalidServiceInfoPlistAlert = false + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + guard !AppDelegate.isWithinUnitTest else { + // During unit tests, we don't want to initialize Firebase, since by default we want to able + // to run unit tests without requiring a non-dummy GoogleService-Info.plist file + return true + } + + guard SampleAppUtilities.appContainsRealServiceInfoPlist() else { + // We can't run because the GoogleService-Info.plist file is likely the dummy file which needs + // to be replaced with a real one, or somehow the file has been removed from the app bundle. + // See: https://github.com/firebase/firebase-ios-sdk/ + // We'll present a friendly alert when the app becomes active. + return true + } + + FirebaseApp.configure() + Messaging.messaging().delegate = self + Messaging.messaging().shouldEstablishDirectChannel = true + // Just for logging to the console when we establish/tear down our socket connection. + listenForDirectChannelStateChanges(); + + NotificationsController.configure() + + if #available(iOS 8.0, *) { + // Always register for remote notifications. This will not show a prompt to the user, as by + // default it will provision silent notifications. We can use UNUserNotificationCenter to + // request authorization for user-facing notifications. + application.registerForRemoteNotifications() + } else { + // iOS 7 didn't differentiate between user-facing and other notifications, so we should just + // register for remote notifications + NotificationsController.shared.registerForUserFacingNotificationsFor(application) + } + return true + } + + func application(_ application: UIApplication, + didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { + print("APNS Token: \(deviceToken.hexByteString)") + NotificationCenter.default.post(name: APNSTokenReceivedNotification, object: nil) + if #available(iOS 8.0, *) { + } else { + // On iOS 7, receiving a device token also means our user notifications were granted, so fire + // the notification to update our user notifications UI + NotificationCenter.default.post(name: UserNotificationsChangedNotification, object: nil) + } + } + + func application(_ application: UIApplication, + didRegister notificationSettings: UIUserNotificationSettings) { + NotificationCenter.default.post(name: UserNotificationsChangedNotification, object: nil) + } + + func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { + print("application:didReceiveRemoteNotification:fetchCompletionHandler: called, with notification:") + print("\(userInfo.jsonString ?? "{}")") + completionHandler(.newData) + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // If the app didn't start property due to an invalid GoogleService-Info.plist file, show an + // alert to the developer. + if !SampleAppUtilities.appContainsRealServiceInfoPlist() && + !AppDelegate.hasPresentedInvalidServiceInfoPlistAlert { + if let vc = window?.rootViewController { + SampleAppUtilities.presentAlertForInvalidServiceInfoPlistFrom(vc) + AppDelegate.hasPresentedInvalidServiceInfoPlistAlert = true + } + } + } +} + +extension AppDelegate: MessagingDelegate { + // FCM tokens are always provided here. It is called generally during app start, but may be called + // more than once, if the token is invalidated or updated. This is the right spot to upload this + // token to your application server, or to subscribe to any topics. + func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) { + if let token = Messaging.messaging().fcmToken { + print("FCM Token: \(token)") + } else { + print("FCM Token: nil") + } + } + + // Direct channel data messages are delivered here, on iOS 10.0+. + // The `shouldEstablishDirectChannel` property should be be set to |true| before data messages can + // arrive. + func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) { + // Convert to pretty-print JSON + guard let prettyPrinted = remoteMessage.appData.jsonString else { + print("Received direct channel message, but could not parse as JSON: \(remoteMessage.appData)") + return + } + print("Received direct channel message:\n\(prettyPrinted)") + } +} + +extension AppDelegate { + func listenForDirectChannelStateChanges() { + NotificationCenter.default.addObserver(self, selector: #selector(onMessagingDirectChannelStateChanged(_:)), name: .MessagingConnectionStateChanged, object: nil) + } + + func onMessagingDirectChannelStateChanged(_ notification: Notification) { + print("FCM Direct Channel Established: \(Messaging.messaging().isDirectChannelEstablished)") + } +} + +extension Dictionary { + /// Utility method for printing Dictionaries as pretty-printed JSON. + var jsonString: String? { + if let jsonData = try? JSONSerialization.data(withJSONObject: self, options: [.prettyPrinted]), + let jsonString = String(data: jsonData, encoding: .utf8) { + return jsonString + } + return nil + } +} |