iOS Firebase推送通知:如何提供Firebase用户的设备令牌并发送通知

最近在Google I / O活动中,Google重新整理了Firebase并添加了许多新function,并对其余部分进行了修改。 我一直试图通过Firebase将iOS推送通知实现到我的应用程序的最基本的级别,所以我创build了一个非常简单的应用程序,除了接收远程推送通知之外什么都不做。 在Firebase内部,我已经上传了我的证书,在Xcode中,我的configuration文件已经添加到目标和项目中,并且在Firebase中我已经上传了正确的证书。 下面是我的AppDelegate.swift文件中包含的代码,但因为我的ViewController.swift是“空的”,我没有包括它。 虽然没有崩溃或运行时错误,当我加载应用程序,我接受通知。 然后,我退出应用程序并closures我的设备。 在Firebase中,我将通知发送到正确的应用程序。 几分钟后,Firebase表示通知“已完成”。 但是,我从来没有收到设备上的通知。 因此,总而言之,我需要一个解决scheme来发送Firebase此设备deviceToken ,然后使用“Firebase通知”发送推送通知消息。 任何帮助我的代码或一般将不胜感激,我希望这有助于未来的观众。 谢谢! 我在AppDelegate.swift代码:

 import UIKit import Firebase import FirebaseMessaging @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { FIRApp.configure() let notificationTypes : UIUserNotificationType = [UIUserNotificationType.Alert, UIUserNotificationType.Badge, UIUserNotificationType.Sound] let notificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: nil) application.registerForRemoteNotifications() application.registerUserNotificationSettings(notificationSettings) return true } func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) { print("Device Token: \(deviceToken)") } func applicationWillResignActive(application: UIApplication) { } func applicationDidEnterBackground(application: UIApplication) { } func applicationWillEnterForeground(application: UIApplication) { } func applicationDidBecomeActive(application: UIApplication) { } func applicationWillTerminate(application: UIApplication) { } func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) { print("MessageID : \(userInfo["gcm.messgae_id"]!)") // or gcm_etc... print(userInfo) } } 

更新:从Firebase 4.0.4开始,您可以按照https://github.com/onmyway133/blog/issues/64

如何处理APNS设备标记

我一直在阅读发送通知给iOS上的用户段,但是没有提到APNS设备令牌,这对于推送通知是至关重要的。

所以Firebase必须在引擎盖下进行一些调整。 实际上是这样。 阅读后端文档下游消息给了我们这个想法

禁用Swizzling :映射您的APN令牌和注册令牌

 If you have disabled method swizzling, you'll need to explicitly map your APNs token to the FCM registration token. Override the 

方法didRegisterForRemoteNotificationsWithDeviceToken来检索APNs令牌,然后调用setAPNSToken

 func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) { FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenTypeSandbox) } 

我特别尽量避免调整。 阅读将用于iOS的GCM客户端应用程序迁移到Firebase云消息传递为我们提供了禁用它的方法

启用/禁用方法swizzling

FCM提供的方法可以简化您的客户端代码。 但是,对于不喜欢使用它的开发人员,FCM允许您通过在应用程序的Info.plist文件中添加FIRMessagingAutoRegisterEnabledflag并将其值设置为NO(布尔值)来禁用方法调整

 FCM swizzling affects how you handle the default registration token, and how you handle downstream message callbacks. Where 

本指南提供了使用和不使用方法调整的迁移示例。

向我展示代码

在你的Podfile有这个

 pod 'Firebase' pod 'FirebaseMessaging' 

这是完成的代码

 import Firebase import FirebaseMessaging override func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { FIRApp.configure() NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(tokenRefreshNotification(_:)), name: kFIRInstanceIDTokenRefreshNotification, object: nil) } // NOTE: Need to use this when swizzling is disabled public func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) { FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Sandbox) } func tokenRefreshNotification(notification: NSNotification) { // NOTE: It can be nil here let refreshedToken = FIRInstanceID.instanceID().token() print("InstanceID token: \(refreshedToken)") connectToFcm() } func connectToFcm() { FIRMessaging.messaging().connectWithCompletion { (error) in if (error != nil) { print("Unable to connect with FCM. \(error)") } else { print("Connected to FCM.") } } } public func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) { print(userInfo) } 

没有CocoaPods集成

首先阅读Firebase文档。 => Firebase文档

  1. 在此注册Firebase项目=>在此注册项目

  2. 从这里获取GoogleService-Info.plist文件=> project => settings => General

  3. GoogleService-Info.plist文件放在您的项目中。

  4. 在Firebase中设置通知.p12证书(生产和开发)=> project => settings => Cloud Messaging

  5. 下载Firebase SDK => Firebase SDK下载

  6. 在您的项目中创buildSDK文件夹,并将其中的所有SDK文件夹。

  7. 现在添加这个框架在你的Xcode => libicucore.tbd

  8. 在Xcode中设置背景模式=> Projects => Capabilities => Background Mode ON => RemoteNotification
  9. 添加您的Info.Plist文件FirebaseAppDelegateProxyEnabled设置BOOL NO

在这里输入图像说明

在Objective-c中你的Appdelegate.m文件

 #import "AppDelegate.h" #import "Firebase.h" #import "AFNHelper.h" @interface AppDelegate (){ NSString *InstanceID; } @property (nonatomic, strong) NSString *strUUID; @property (nonatomic, strong) NSString *strDeviceToken; @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UIUserNotificationType allNotificationTypes = (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge); UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; [[UIApplication sharedApplication] registerForRemoteNotifications]; [FIRApp configure]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tokenRefreshNotification:) name:kFIRInstanceIDTokenRefreshNotification object:nil]; return YES; } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]); [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; NSLog(@"userInfo=>%@", userInfo); } - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [[FIRInstanceID instanceID] setAPNSToken:deviceToken type:FIRInstanceIDAPNSTokenTypeProd]; NSLog(@"deviceToken1 = %@",deviceToken); } - (void)tokenRefreshNotification:(NSNotification *)notification { NSLog(@"instanceId_notification=>%@",[notification object]); InstanceID = [NSString stringWithFormat:@"%@",[notification object]]; [self connectToFcm]; } - (void)connectToFcm { [[FIRMessaging messaging] connectWithCompletion:^(NSError * _Nullable error) { if (error != nil) { NSLog(@"Unable to connect to FCM. %@", error); } else { NSLog(@"InstanceID_connectToFcm = %@", InstanceID); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ dispatch_async(dispatch_get_main_queue(), ^{ [self sendDeviceInfo]; NSLog(@"instanceId_tokenRefreshNotification22=>%@",[[FIRInstanceID instanceID] token]); }); }); } }]; } 

现在iOS的FCM文档相当差劲。

按照他们在github上的示例应用程序

这里添加的重要部分:

 import Firebase import FirebaseInstanceID import FirebaseMessaging func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Register for remote notifications if #available(iOS 8.0, *) { let settings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil) application.registerUserNotificationSettings(settings) application.registerForRemoteNotifications() } else { // Fallback let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound] application.registerForRemoteNotificationTypes(types) } FIRApp.configure() // Add observer for InstanceID token refresh callback. NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.tokenRefreshNotificaiton), name: kFIRInstanceIDTokenRefreshNotification, object: nil) return true } func tokenRefreshNotificaiton(notification: NSNotification) { let refreshedToken = FIRInstanceID.instanceID().token()! print("InstanceID token: \(refreshedToken)") // Connect to FCM since connection may have failed when attempted before having a token. connectToFcm() } // [END refresh_token] // [START connect_to_fcm] func connectToFcm() { FIRMessaging.messaging().connectWithCompletion { (error) in if (error != nil) { print("Unable to connect with FCM. \(error)") } else { print("Connected to FCM.") } } } 

现在您的令牌已经发送到FCM服务器