【问题标题】:iOS Firebase Push Notifications : How To Give Firebase User's Device Token And Send NotificationiOS Firebase 推送通知:如何给 Firebase 用户的设备令牌并发送通知
【发布时间】:2016-10-06 16:05:48
【问题描述】:

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

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

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

但是,我从未在设备上收到通知。因此,总而言之,我需要一个解决方案来向 Firebase 发送此 deviceToken,然后使用“Firebase Notifications”发送推送通知消息。

对我的代码或一般情况的任何帮助将不胜感激,我希望这对未来的观众有所帮助。谢谢!我在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)

    }


}

【问题讨论】:

  • "关闭我的设备。" Err,如果设备关闭,如何接收通知?您的意思是重新打开设备后没有收到通知吗?这是预期的行为。
  • 所以,在我的 iPhone 上,我第一次打开了应用程序。我接受启用通知弹出窗口。然后我退出应用程序并将其关闭。我所期待的是,当通知通过时,通知会出现在您的锁定屏幕上,然后点亮锁定屏幕,但没有任何反应。
  • 关机没有锁屏,关机怎么会有?如果你把它关掉就没有电了。所以当你一直说关掉它时,我不明白你在说什么。到底关掉什么?
  • 无论如何,除此之外,让我们假设设备已打开并且您仍然没有收到推送。您的代码没有在任何地方获得推送令牌。因此,您如何向 firebase 提供推送令牌?
  • 这就是我有点困惑的地方。我认为不需要设备令牌,并且 firebase 会将通知发送给拥有该应用程序的每个人。当我说“关闭”时,我并不是指完全关闭电源,而是您可以向左滑动并输入密码。谢谢。

标签: ios push-notification firebase


【解决方案1】:

更新:从 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已禁用:映射您的 APNs 令牌和注册令牌

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 允许您 通过添加禁用方法混合 FIRMessagingAutoRegisterEnabledflag 在应用的 Info.plist 文件中和 将其值设置为 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)
}

【讨论】:

  • 我的 Podfile 中没有 pod 'FirebaseMessaging',也没有显示任何通知。补充说,这一切都开始工作了。谢谢!
  • connectToFcm 是干什么用的?推送通知仅与 . setAPNSToken() 一起使用。
  • @IulianOnofrei 可能是“数据消息”连接
【解决方案2】:

无需 CocoaPods 即可集成

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

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

  2. 从这里获取 GoogleService-Info.plist 文件=> 项目=> 设置 => 常规

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

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

  5. 在此处下载 Firebase SDK => Firebase SDK Download

  6. 在您的项目中创建 SDK 文件夹并将所有 SDK 文件夹放入其中。

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

  8. 在 Xcode 中设置背景模式为 ON => 项目 => 功能 => 背景模式为 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]);
                
            });
        });
        
        
    }
}];
}

【讨论】:

  • 我这样做并检查了它。我以为我收到了一次通知,但无法再次收到。检查我在此处发布的问题,其中包含我的整个代码:stackoverflow.com/questions/37965615/…
  • 这在 iOS 应用程序处于后台或前台模式时工作正常。但是当iOS应用程序终止时它不起作用。当应用程序终止时,我无法收到推送通知。
  • 你有东西不见了兄弟我的应用程序在应用程序商店上运行它对我来说很好
  • 不要在生产中使用它!没有人会在第一次应用启动时接受推送通知权限。
  • @lulian Onofrei 我在我的应用程序中使用它,我的应用程序正在运行并且工作正常。
【解决方案3】:

现在适用于 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 服务器

【讨论】:

  • 谢谢,但我在调用选择器时遇到错误:#selector
  • 您需要使用 xcode 7.3 的#selector 语法。否则你可以试试selector: "self.tokenRefreshNotificaiton:"
  • 我已经实现了上面的代码,并将 p12 设置为 firebase -> Settings-> Cloud Messaging,是的,我可以在 Firebase-> Notification -> New Message.... .but self.ref.child("messages").childByAutoId().setValue(mdata) 没有收到推送通知......
  • 你应该把它作为一个单独的问题问@iDeveloper
  • 是的,但是你有什么想法吗?
猜你喜欢
  • 2017-12-07
  • 2018-01-22
  • 1970-01-01
  • 2017-10-29
  • 2018-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
相关资源
最近更新 更多