FCM后台通知无法在iOS中使用 [英] FCM background notifications not working in iOS

查看:212
本文介绍了FCM后台通知无法在iOS中使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



当我的应用处于前台时,我收到了成功的通知(回调 didReceiveRemoteNotification appdelegate 被激发),但是当应用程序在后台时我没有收到通知(我在iOS的通知托盘中没有看到任何东西)。

因此,我认为问题在于FCM发送的消息的格式。
服务器发送给FCM的json格式如下:

$ p $ $ $ $ $ $ $ $ $ $ $ :{
title:mytitle,
body:mybody,
url:myurl
},

title:mytitle,
body:mybody
},
to:/ topics / topic
正如你所看到的,我的json中有两个块:一个通知块(用于接收通知在后台)和一个数据块(在前台接收通知)。

我不明白为什么没有收到后台的通知。
我的怀疑是关于块的顺序(如果我把data块放在notification块之前,是一个问题吗?)。

谢谢你,
标记

编辑:
更多关于这个问题的信息。 b $ b

这是我的appdelegate.swift:

  @UIApplicationMain $ b $ class AppDelegate:UIResponder,UIApplicationDelegate 
{
var window:UIWindow?

$ b $ //应用程序启动
func application(application:UIApplication,didFinishLaunchingWithOptions launchOptions:[NSObject:AnyObject]?) - > Bool
{
let pushNotificationSettings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes:[.Alert,.Badge,.Sound],categories:nil)
application.registerUserNotificationSettings(pushNotificationSettings)
application。 registerForRemoteNotifications()

FIRApp.configure()

NSNotificationCenter.defaultCenter()。addObserver(self,selector:tokenRefreshNotification:,name:kFIRInstanceIDTokenRefreshNotification,object:nil)

返回true
}




//处理刷新通知令牌
func tokenRefreshNotification(通知:NSNotification ){
let refreshedToken = FIRInstanceID.instanceID()。token()
print(InstanceID token:\(refreshedToken))

//连接FCM,可能在获得令牌之前尝试失败。
if(refreshedToken!= nil)
{
connectToFcm()

FIRMessaging.messaging()。subscribeToTopic(/ topics / topic)
}



//连接到FCM
func connectToFcm(){
FIRMessaging.messaging()。connectWithCompletion {(error )
if(error!= nil){
print(无法连接FCM。\(错误))
} else {
print(Connected to FCM。)
}
}
}


//当应用程序处于前台时处理通知
func application(application: UIApplication,didReceiveRemoteNotification userInfo:[NSObject:AnyObject],fetchCompletionHandler completionHandler:(UIBackgroundFetchResult) - > Void){
//如果您的应用在后台收到通知消息,
//这个回调不会直到用户点击启动应用程序的通知。
// TODO:处理通知数据

//打印消息ID。
print(Message ID:\(userInfo [gcm.message_id]))

//打印完整的信息。
print(%@,userInfo)
}


//应用程序将在后台输入
func applicationWillResignActive(application:UIApplication)
{
//当应用程序即将从活动状态转移到非活动状态时发送。对于某些类型的临时中断(例如来电或SMS消息)或用户退出应用程序并开始转换到后台状态时,可能会发生这种情况。
//使用此方法可暂停正在进行的任务,禁用定时器,并降低OpenGL ES帧速率。游戏应该使用这种方法来暂停游戏。



$ b //在后台输入应用程序
func applicationDidEnterBackground(application:UIApplication)
{
FIRMessaging.messaging ().disconnect()
print(与FCM断开连接)
}



//应用程序将在前台输入
func applicationWillEnterForeground(application:UIApplication)
{
//作为从后台到非活动状态转换的一部分;在这里你可以撤消进入背景的许多变化。



$ b //在前台输入的应用程序
func applicationDidBecomeActive(application:UIApplication)
{
connectToFcm

application.applicationIconBadgeNumber = 0;



$ b //应用程序将终止
func applicationWillTerminate(application:UIApplication)
{
// //调用应用程序即将终止。保存数据,如果适用。另请参阅applicationDidEnterBackground :.
}


}

唯一方法我可以在前台接收消息,通过禁用方法调试,在我的info.plist中设置FirebaseAppDelegateProxyEnabled为NO。



在这种情况下,FCM文档说我必须在我的appdelegate.swift中有两个方法:

$ $ p $ - 在didReceiveRemoteNotification中的FIRMessaging.messaging()。appDidReceiveMessage(userInfo)回调
- 在didRegisterForRemoteNotificationsWithDeviceToken回调中,FIRInstanceID.instanceID()。setAPNSToken(deviceToken,type:FIRInstanceIDAPNSTokenType.Sandbox)

如果我实现这些功能,即使应用程序在前台,消息也会停止。



我知道这很奇怪。
任何建议将非常感激。

编辑2: 当应用程序在后台时, t收到,但是当我打开我的应用程序,同样的通知是立即收到(方法didReceiveRemoteNotification被解雇)。

解决方案

假设你已经正确设置了一切,然后将消息的优先级正常设置为应该立即显示。这是由于iOS绑定通知并处理它们的方式。您可以阅读这里的 FCM通知的优先级。请注意,在生产中不应该使用 high ,除非有好的情况,因为它有电池损失。

以下是苹果文档


通知的优先级。指定以下值之一:

10 - 立即发送推送消息。具有此优先级
的通知必须在目标设备上触发警报,声音或徽章。对于只包含
内容可用密钥的推送通知,使用此优先级是一个
错误。



5-发送推送消息在考虑设备功耗
的时候。具有这个优先权的通知可能被
分组并且以突发传送。他们被扼杀,并在一些
案件不交付。如果您省略此标头,则APNs服务器会将
的优先级设置为10.



I have a problem with FCM notification on iOS.

I receive notifications with success when my app is in foreground (the callback didReceiveRemoteNotification in appdelegate is fired), but I don't receive notifications when the app is in background (I do not see anything in the notification tray of iOS).

So, I think the problem is in the format of the message sent by FCM. The json sent by my server to FCM, is in the following format:

{  
   "data":{  
      "title":"mytitle",
      "body":"mybody",
      "url":"myurl"
   },
   "notification":{  
      "title":"mytitle",
      "body":"mybody"
   },
   "to":"/topics/topic"
}

As you can see, there are two blocks in my json: one notification block (to receive notifications in background), and one data block (to receive notifications in foreground).

I cannot understand why notifications in background are not received. My doubts are about the order of the blocks (is a problem if I put the "data" block before the "notification" block?).

Thank you, Mark

EDIT: More info about the problem.

This is my appdelegate.swift:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
{
    var window: UIWindow?


    // Application started
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
    {
        let pushNotificationSettings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        application.registerUserNotificationSettings(pushNotificationSettings)
        application.registerForRemoteNotifications()

        FIRApp.configure()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "tokenRefreshNotification:", name: kFIRInstanceIDTokenRefreshNotification, object: nil)

        return true
    }




    // Handle refresh notification token
    func tokenRefreshNotification(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.
        if (refreshedToken != nil)
        {
            connectToFcm()

            FIRMessaging.messaging().subscribeToTopic("/topics/topic")
        }

    }


    // 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.")
            }
        }
    }


    // Handle notification when the application is in foreground
    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (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.
            print("Message ID: \(userInfo["gcm.message_id"])")

            // Print full message.
            print("%@", userInfo)
    }


    // Application will enter in background
    func applicationWillResignActive(application: UIApplication)
    {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }



    // Application entered in background
    func applicationDidEnterBackground(application: UIApplication)
    {
        FIRMessaging.messaging().disconnect()
        print("Disconnected from FCM.")
    }



    // Application will enter in foreground
    func applicationWillEnterForeground(application: UIApplication)
    {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }



    // Application entered in foreground
    func applicationDidBecomeActive(application: UIApplication)
    {
        connectToFcm()

        application.applicationIconBadgeNumber = 0;
    }



    // Application will terminate
    func applicationWillTerminate(application: UIApplication)
    {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }


}

The only way I can receive messages in foreground, is by disabling method swizzling, setting FirebaseAppDelegateProxyEnabled to NO in my info.plist.

In this case, FCM documentation says that I have to implement in my appdelegate.swift two methods:

 - FIRMessaging.messaging().appDidReceiveMessage(userInfo)  in didReceiveRemoteNotification callback
 - FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Sandbox) in didRegisterForRemoteNotificationsWithDeviceToken callback

But if i implement those functions, messages stops to arrive even when the app is in foreground.

I know this is very strange. Any suggestion would be so much appreciated.

EDIT 2:

When the app is in background the notification isn't received, but when i open my app, the same notification is received immediatly (method didReceiveRemoteNotification is fired).

解决方案

Assuming you've set up everything correctly, then setting the priority of the message from normal to high should make it appear immediately. This is due to the way iOS bundles notifications and handles them. You can read about the Priority of FCM notifications here. Please note that you shouldn't really use high in production unless there is a good case for it, as it has a battery penalty.

Here is the reference from Apple's docs

The priority of the notification. Specify one of the following values:

10–Send the push message immediately. Notifications with this priority must trigger an alert, sound, or badge on the target device. It is an error to use this priority for a push notification that contains only the content-available key.

5—Send the push message at a time that takes into account power considerations for the device. Notifications with this priority might be grouped and delivered in bursts. They are throttled, and in some cases are not delivered. If you omit this header, the APNs server sets the priority to 10.

这篇关于FCM后台通知无法在iOS中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆