Ios Firebase FCM最初不工作,但如果应用程序打开,会在3-4次后工作
我是Firebase FCM集成的新手,我面临一些问题。第一次安装应用程序时,我不会收到推送通知,但如果我打开和关闭应用程序几次,然后从Firebase发送推送通知,我会收到通知,而不会更改客户端或服务器代码。有人能帮我吗 我已在下面附上我的appdelegate代码Ios Firebase FCM最初不工作,但如果应用程序打开,会在3-4次后工作,ios,swift,firebase,push-notification,firebase-cloud-messaging,Ios,Swift,Firebase,Push Notification,Firebase Cloud Messaging,我是Firebase FCM集成的新手,我面临一些问题。第一次安装应用程序时,我不会收到推送通知,但如果我打开和关闭应用程序几次,然后从Firebase发送推送通知,我会收到通知,而不会更改客户端或服务器代码。有人能帮我吗 我已在下面附上我的appdelegate代码 import UIKit import Firebase import UserNotifications import FirebaseMessaging import FirebaseInstanceID @UIApplic
import UIKit
import Firebase
import UserNotifications
import FirebaseMessaging
import FirebaseInstanceID
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate,UNUserNotificationCenterDelegate,MessagingDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: { (granted, error) in
if error == nil{
UIApplication.shared.registerForRemoteNotifications()
}
})
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
}
application.registerForRemoteNotifications()
return true
}
func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
}
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
UIApplication.shared.registerForRemoteNotifications()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// I have tried both method but none worked and i also tried MessagingAPNSTokenType.sandbox and prod
// Method 1: Messaging.messaging().apnsToken = deviceToken
// Method 2:
Messaging.messaging().setAPNSToken(deviceToken, type: MessagingAPNSTokenType.unknown)
}
}
提前感谢我遇到了与您相同的问题,并且存在一个已知问题,即如果
UIApplication.shared.registerforremotentifications()
调用得不够早,则FCM令牌
并不总是与APNs设备令牌
关联
根据GitHub线程的说法,这个问题已经在FirebaseInstanceID SDK
中修复,应该很快就会出来
同时,您可以:
将您的FirebaseInstanceID pod锁定到pod文件中的2.0.0
,或
确保在应用程序启动时调用UIApplication.shared.registerforremotentifications()
,最好在FirebaseApp.configure()之前
更新:
我只是做了一些额外的测试,我注意到这是一个有点随机的时候,这将工作。对于某些设备,它立即起作用,而对于某些设备则不起作用。对于某些设备,单令牌推送
工作,而不是用户段
。我设法让它工作起来,通过添加以下内容,您至少可以获得单令牌推送
或用户段
:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 10.0, *) {
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in
})
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
// For iOS 10 data message (sent via FCM)
Messaging.messaging().delegate = self
application.registerForRemoteNotifications()
print("::: registerForRemoteNotifications iOS 10")
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
print("::: registerUserNotificationSettings iOS 9")
}
FirebaseApp.configure()
Messaging.messaging().delegate = self
Messaging.messaging().shouldEstablishDirectChannel = true
if let refreshedToken = InstanceID.instanceID().token() {
print("::: InstanceID token: \(refreshedToken)")
}
NotificationCenter.default.addObserver(self, selector: #selector(tokenRefreshNotification), name: NSNotification.Name.InstanceIDTokenRefresh, object: nil)
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().setAPNSToken(deviceToken, type: .prod)
if let refreshedToken = InstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
}
}
问题是,如果您不访问didRegisterForRemoteNotificationsWithDeviceToken
函数,它将无法工作。Firebase FCM,需要一些时间才能生成其第一个令牌。获得此令牌后,您将开始接收推送通知。看看这些。可以肯定的是:
希望这有帮助。通过此更新您的appdelegate
import FirebaseCore
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.fcmInitialSetup(application)
return true
}
func fcmInitialSetup(_ application: UIApplication){
// [START register_for_notifications]
if #available(iOS 10.0, *) {
let uns: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(uns)
application.registerForRemoteNotifications()
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
// [END register_for_notifications]
FIRApp.configure()
// Add observer for InstanceID token refresh callback.
NotificationCenter.default.addObserver(self, selector: #selector(self.tokenRefreshNotification), name: NSNotification.Name.firInstanceIDTokenRefresh, object: nil)
if let token = FIRInstanceID.instanceID().token() {
sendTokenToServer(token)
}
}
func sendTokenToServer(_ currentToken: String) {
print("sendTokenToServer() Token: \(currentToken)")
// Send token to server ONLY IF NECESSARY
print("InstanceID token: \(currentToken)")
self.token = currentToken
UserDefaults.standard.set(self.token, forKey: "token")
UserDefaults.standard.synchronize()
if self.token != nil{
let userInfo = ["token": self.token]
NotificationCenter.default.post(
name: Notification.Name(rawValue: self.rkey), object: nil, userInfo: userInfo)
}
}
// NOTE: Need to use this when swizzling is disabled
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenChars = (deviceToken as NSData).bytes.bindMemory(to: CChar.self, capacity: deviceToken.count)
var tokenString = ""
for i in 0..<deviceToken.count {
tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]])
}
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.unknown)
print("Device Token:", tokenString)
print("FIRInstanceID.instanceID().token() Token:", FIRInstanceID.instanceID().token())
if let tokenData = FIRInstanceID.instanceID().token(){
UserDefaults.standard.set(tokenData, forKey: "token")
UserDefaults.standard.synchronize()
let userInfo = ["token": tokenData]
}
}
func tokenRefreshNotification(_ notification: Notification) {
// NOTE: It can be nil here
// print("Token:\(FIRInstanceID.instanceID().token()!)")
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("InstanceID token: \(refreshedToken)")
UserDefaults.standard.set(refreshedToken, forKey: "token")
UserDefaults.standard.synchronize()
print("update now \(self.token)")
if self.token != nil{
let userInfo = ["token": self.token]
NotificationCenter.default.post(
name: Notification.Name(rawValue: self.rkey), object: nil, userInfo: userInfo)
}
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
// [END refresh_token]
func connectToFcm() {
FIRMessaging.messaging().connect { (error) in
if (error != nil) {
print("Unable to connect with FCM. \(error)")
} else {
print("Connected to FCM.")
}
}
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
print(userInfo)
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
print("Within open URL")
return true
}
// [START receive_apns_token_error]
func application( _ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
error: Error ) {
print("Registration for remote notification failed with error: \(error.localizedDescription)")
// [END receive_apns_token_error]
let userInfo = ["error": error.localizedDescription]
NotificationCenter.default.post(
name: Notification.Name(rawValue: rkey), object: nil, userInfo: userInfo)
}
func registrationHandler(_ token: String!, error: NSError!) {
if (token != nil) {
self.token = token!
print("Registration Token: \(self.token)")
UserDefaults.standard.set(self.token, forKey: "token")
UserDefaults.standard.synchronize()
let userInfo = ["token": self.token]
NotificationCenter.default.post(
name: Notification.Name(rawValue: self.rkey), object: nil, userInfo: userInfo)
} else {
print("Registration to GCM failed with error: \(error.localizedDescription)")
let userInfo = ["error": error.localizedDescription]
NotificationCenter.default.post(
name: Notification.Name(rawValue: self.rkey), object: nil, userInfo: userInfo)
}
}
func registerForPushNotifications(_ application: UIApplication) {
let notificationSettings = UIUserNotificationSettings(
types: [.badge, .sound, .alert], categories: nil)
application.registerUserNotificationSettings(notificationSettings)
}
func application(_ application: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types != UIUserNotificationType() {
application.registerForRemoteNotifications()
}
}
// [START receive_message]
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// Print message ID. add Toast
print(userInfo);
print(application.keyWindow?.visibleViewController() ?? "")
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print full message.
print("%@", userInfo)
}
// [END receive_message]
func applicationDidBecomeActive(_ application: UIApplication) {
connectToFcm()
}
// [START disconnect_from_fcm]
func applicationDidEnterBackground(_ application: UIApplication) {
// FIRMessaging.messaging().disconnect()
// print("Disconnected from FCM.")
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
}
}
// [END disconnect_from_fcm]
// [START ios_10_message_handling]
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {
// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
// Print message ID. add Toast
// Print full message.
print("%@", userInfo)
// Print full message.
print("%@", userInfo)
}
}
extension AppDelegate : FIRMessagingDelegate {
// Receive data message on iOS 10 devices.
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
print("%@", remoteMessage.appData)
}
}
导入FirebaseCore
导入FirebaseInstanceID
导入FirebaseMessaging
导入用户通知
@UIApplicationMain
类AppDelegate:UIResponder、UIApplicationLegate{
func应用程序(application:UIApplication,didFinishLaunchingWithOptions launchOptions:[UIApplicationLaunchOptions:[UIApplicationLaunchOptions:任何]?)->Bool{
self.fcminitialstup(应用程序)
返回真值
}
func fcmInitialSetup(u应用程序:ui应用程序){
//[启动注册\u以获取\u通知]
如果可用(iOS 10.0,*){
let uns:UIUserNotificationSettings=UIUserNotificationSettings(类型:[.alert、.badge、.sound],类别:nil)
application.registerUserNotificationSettings(uns)
应用程序.注册表项更改()
}否则{
let设置:UIUserNotificationSettings=
UIUserNotificationSettings(类型:[.alert、.badge、.sound],类别:nil)
application.registerUserNotificationSettings(设置)
}
应用程序.注册表项更改()
//[结束注册以获取通知]
FIRApp.configure()
//添加InstanceID令牌刷新回调的观察者。
NotificationCenter.default.addObserver(self,选择器:#选择器(self.tokenRefreshNotification),名称:NSNotification.name.firInstanceIDTokenRefresh,对象:nil)
如果let token=FIRInstanceID.instanceID().token(){
sendTokenToServer(令牌)
}
}
func sendTokenToServer(currentToken:String){
打印(“sendTokenToServer()令牌:\(currentToken)”)
//仅在必要时向服务器发送令牌
打印(“InstanceID标记:\(currentToken)”)
self.token=currentToken
UserDefaults.standard.set(self.token,forKey:“token”)
UserDefaults.standard.synchronize()
如果self.token!=nil{
让userInfo=[“token”:self.token]
NotificationCenter.default.post(
name:Notification.name(rawValue:self.rkey),object:nil,userInfo:userInfo)
}
}
//注意:禁用swizzling时需要使用此选项
func应用程序(application:UIApplication,DidRegisterForRemotionTificationswithDeviceToken deviceToken:Data){
让tokenChars=(deviceToken作为NSData).bytes.bindMemory(to:CChar.self,capacity:deviceToken.count)
var tokenString=“”
因为我在0..Bool{
打印(“在打开的URL内”)
返回真值
}
//[开始接收\u apns\u令牌\u错误]
func应用程序(application:UIApplication,didFailToRegisterForRemoteNotificationsWithError
错误:错误){
打印(“远程通知注册失败,错误:\(error.localizedDescription)”)
//[结束接收\u apns\u令牌\u错误]
let userInfo=[“error”:error.localizedDescription]
NotificationCenter.default.post(
name:Notification.name(rawValue:rkey),object:nil,userInfo:userInfo)
}
func registrationHandler(uToken:String!,错误:NSError!){
如果(令牌!=nil){
self.token=令牌!
打印(“注册令牌:\(self.Token)”)
UserDefaults.standard.set(self.token,forKey:“token”)
UserDefaults.standard.synchronize()
让userInfo=[“token”:self.token]
NotificationCenter.default.post(
name:Notification.name(rawValue:self.rkey),object:nil,userInfo:userInfo)
}否则{
打印(“向GCM注册失败,错误:\(error.localizedDescription)”)
let userInfo=[“error”:error.localizedDescription]
NotificationCenter.default.post(
name:Notification.name(rawValue:self.rkey),object:nil,userInfo:userInfo)
}
}
func registerForPushNotifications(uApplication:UIApplication){
让notificationSettings=UIUserNotificationSettings(
类型:[.badge、.sound、.alert],类别:无
guard let contents = FIRInstanceID.instanceID().token()
else {
return
}
print("InstanceID token: \(contents)")
if let token = FIRInstanceID.instanceID().token(){
print(token)