iOS Firebase 推送通知:如何提供 Firebase 用户的设备令牌并发送通知
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37667753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS Firebase Push Notifications : How To Give Firebase User's Device Token And Send Notification
提问by EQOxx123
Somewhat recently at the Google I/O event Google renovated Firebase & added a lot of new features, and touched up on the remaining ones. I have been trying to implement the iOS Push Notifications via Firebase into my app through the most basic level, So I created a very simple app that really does nothing besides receive remote push notifications.
最近在 Google I/O 活动中,Google 翻新了 Firebase 并添加了许多新功能,并对其余功能进行了改进。我一直在尝试通过最基本的级别通过 Firebase 将 iOS 推送通知实现到我的应用程序中,所以我创建了一个非常简单的应用程序,除了接收远程推送通知之外,它真的什么都不做。
Inside of Firebase, I have uploaded my certificate and within Xcode my provisioning profiles have been added to both the target and project, and in Firebase I have uploaded the correct certificate. Below is the code contained inside of my AppDelegate.swift
file but because my ViewController.swift
is "empty," I did not include it.
在 Firebase 中,我上传了我的证书,在 Xcode 中我的配置文件已添加到目标和项目中,并且在 Firebase 中我上传了正确的证书。下面是我的AppDelegate.swift
文件中包含的代码,但因为我的文件ViewController.swift
是“空的”,所以我没有包含它。
Although there are no crashes or runtime errors, when I load the app, I accept the notifications. Then, I exit the app and turn off my device. In Firebase, I send the notification to the correct app. After a couple of minutes, in Firebase it says the notification was "Completed".
虽然没有崩溃或运行时错误,但当我加载应用程序时,我接受了通知。然后,我退出应用程序并关闭我的设备。在 Firebase 中,我将通知发送到正确的应用程序。几分钟后,在 Firebase 中,它说通知“已完成”。
However, I never received the notification on the device. So, in conclusion, I need a solution to send Firebase this deviceToken
and then use 'Firebase Notifications' to send the push notification Message.
但是,我从未在设备上收到通知。因此,总而言之,我需要一个解决方案来发送 Firebase deviceToken
,然后使用“Firebase 通知”发送推送通知消息。
Any help for my code or in general would be greatly appreciated and I hope this helps future viewers. Thank you! My code in AppDelegate.swift
:
对我的代码或一般情况的任何帮助将不胜感激,我希望这有助于未来的观众。谢谢!我的代码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)
}
}
回答by onmyway133
Updated: As of Firebase 4.0.4, you can follow https://github.com/onmyway133/blog/issues/64
更新:从 Firebase 4.0.4 开始,您可以关注https://github.com/onmyway133/blog/issues/64
HOW APNS DEVICE TOKEN IS HANDLED
如何处理 APNS 设备令牌
I've been reading Send a Notification to a User Segment on iOSbut there is no mention of APNS device token, which is crucial to push notifications.
我一直在阅读在 iOS 上向用户段发送通知,但没有提到 APNS 设备令牌,这对于推送通知至关重要。
So Firebase must be doing some swizzling under the hood. In fact it is. Reading backend documentation Downstream Messagesgives us the idea
所以 Firebase 必须在幕后进行一些调整。事实上它是。阅读后端文档下游消息给了我们这个想法
Swizzlingdisabled: mapping your APNs token and registration token
If you have disabled method swizzling, you'll need to explicitly map your APNs token to the FCM registration token. Override the
methods
didRegisterForRemoteNotificationsWithDeviceToken
to retrieve the APNs token, and then callsetAPNSToken
.
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)
}
I particularly try to avoid swizzling as much as possible. Reading Migrate a GCM Client App for iOS to Firebase Cloud Messaginggives us how to do disable it
我特别尽量避免 swizzling。阅读Migrate a GCM Client App for iOS to Firebase Cloud Messaging为我们提供了如何禁用它
Enabling/disabling method swizzling
启用/禁用方法调配
Method swizzling available with FCM simplifies your client code. However, for developers who prefer not to use it, FCM allows you to disable method swizzling by adding the FIRMessagingAutoRegisterEnabledflagin the app's Info.plist file and setting its value to NO (boolean value).
FCM swizzling affects how you handle the default registration token, and how you handle downstream message callbacks. Where
applicable, this guide provides migration examples both with and without method swizzling enabled.
FCM 提供的方法混合可简化您的客户端代码。但是,对于不喜欢使用它的开发人员,FCM 允许您通过在应用程序的 Info.plist 文件中添加FIRMessagingAutoRegisterEnabledflag并将其值设置为 NO(布尔值)来禁用方法 调配。
FCM swizzling affects how you handle the default registration token, and how you handle downstream message callbacks. Where
适用,本指南提供了启用和不启用方法调配的迁移示例。
SHOW ME THE CODE
给我看代码
Have this in your Podfile
有这个在你的 Podfile
pod 'Firebase'
pod 'FirebaseMessaging'
Here is the completed code
这是完成的代码
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)
}
回答by Sanandiya Vipul
Integrate without CocoaPods
无需 CocoaPods 即可集成
First Read Firebase Doc.=> Firebase Doc
首先阅读 Firebase 文档。=> Firebase 文档
Register project on Firebase here => Register Project here
Get GoogleService-Info.plist file from here=> project=> settings => General
GoogleService-Info.plist file drop in your project.
set Notification .p12 Certificates (Production and Development) in Firebase => project=> settings => Cloud Messaging
Download Firebase SDK here => Firebase SDK Download
Create SDK folder in your project and Drop all SDK Folder in it.
Now Add this Framework in your Xcode => libicucore.tbd
- Set Background Modes ON in Xcode => Projects => Capabilities => Background Mode ON => RemoteNotification
- Add in your Info.Plist file FirebaseAppDelegateProxyEnabledSet BOOL NO.
在此处在 Firebase 上注册项目 => 在此处注册项目
从这里获取 GoogleService-Info.plist 文件 => 项目 => 设置 => 常规
GoogleService-Info.plist 文件放入您的项目中。
在 Firebase => 项目 => 设置 => 云消息传递中设置 Notification .p12 证书(生产和开发)
在此处下载 Firebase SDK => Firebase SDK 下载
在您的项目中创建 SDK 文件夹并将所有 SDK 文件夹放入其中。
现在在你的 Xcode 中添加这个框架 => libicucore.tbd
- 在 Xcode 中设置背景模式 => 项目 => 功能 => 背景模式开启 => 远程通知
- 在您的 Info.Plist 文件中添加FirebaseAppDelegateProxyEnabled设置 BOOL NO。
In Objective-c your Appdelegate.m file
在 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]);
});
});
}
}];
}
回答by Shubhank
Docs are pretty poor for the FCM for iOS now.
现在,iOS 版 FCM 的文档非常糟糕。
Follow the sampleapp they have on github
按照他们在 github 上的示例应用程序
Important part added here :
重要部分在这里添加:
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.")
}
}
}
Now your token has been sent to the FCM server
现在您的令牌已发送到 FCM 服务器