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

时间:2016-06-06 22:23:33

标签: ios push-notification firebase

最近在谷歌I / O活动上谷歌翻新了Firebase&添加了许多新功能,并触及其余的功能。我一直在尝试通过Firebase将iOS推送通知实现到我的应用程序中,通过最基本的级别,所以我创建了一个非常简单的应用程序,除了接收远程推送通知之外什么都不做。

在Firebase内部,我上传了我的证书,在Xcode中,我的配置文件已添加到目标和项目中,而在Firebase中我已上传了正确的证书。以下是我的AppDelegate.swift文件中包含的代码,但因为我的ViewController.swift是"为空,"我没有把它包括在内。

虽然没有崩溃或运行时错误,但当我加载应用程序时,我接受通知。然后,我退出应用程序并关闭我的设备。在Firebase中,我将通知发送到正确的应用。几分钟后,在Firebase中,它说通知是“#34;已完成"。

但是,我从未收到过设备上的通知。总而言之,我需要一个解决方案来deviceToken发送Firebase,然后使用' 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)

    }


}

3 个答案:

答案 0 :(得分:31)

已更新:自Firebase 4.0.4起,您可以关注https://github.com/onmyway133/blog/issues/64

如何处理APNS设备令牌

我一直在阅读Send a Notification to a User Segment on iOS,但没有提及APNS设备令牌,这对于推送通知至关重要。

所以Firebase必须在引擎盖下做一些调整。事实上它是。阅读后端文档Downstream Messages为我们提供了想法

  

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)
}

我特别努力避免尽可能多的调酒。阅读Migrate a GCM Client App for iOS to Firebase Cloud Messaging告诉我们如何禁用它

启用/禁用方法调配

  

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)
}

答案 1 :(得分:13)

没有CocoaPods整合

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

  
      
  1. 在Firebase上注册项目=> Register Project here

  2.   
  3. 从此处获取GoogleService-Info.plist文件=>项目=> settings =>一般

  4.   
  5. 项目中的GoogleService-Info.plist文件。

  6.   
  7. 在Firebase中设置通知.p12证书(生产和开发)    =>项目=> settings =>云消息传递

  8.   
  9. 在此处下载Firebase SDK => Firebase SDK Download

  10.   
  11. 在项目中创建SDK文件夹并删除其中的所有SDK文件夹。

  12.   
  13. 现在在Xcode中添加此框架=> libicucore.tbd

  14.   
  15. 在Xcode =>中设置背景模式为ON Projects =>能力=>背景模式ON => RemoteNotification
  16.   
  17. 添加您的Info.Plist文件 FirebaseAppDelegateProxyEnabled 设置BOOL
  18.   

enter image description here

在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]);

            });
        });


    }
}];
}

答案 2 :(得分:5)

现在iOS的FCM文档很差。

按照他们在github上的sample应用

此处添加了重要部分:

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服务器