我遇到了iOS上关于FCM通知的问题。
当我的应用程序处于前台时(appdelegate
中的回调didReceiveRemoteNotification
被触发),我可以成功地接收通知,但是当应用程序处于后台时,我无法接收通知(在iOS的通知栏中什么也没有显示)。
因此,我认为问题可能出现在FCM发送的消息格式上。 我的服务器发送给FCM的JSON格式如下:
{
"data":{
"title":"mytitle",
"body":"mybody",
"url":"myurl"
},
"notification":{
"title":"mytitle",
"body":"mybody"
},
"to":"/topics/topic"
}
如您所见,我的JSON文件中有两个块:一个通知块(用于接收后台通知)和一个数据块(用于接收前台通知)。
我无法理解为什么无法接收后台通知。我怀疑问题出在块的顺序上(如果将“数据”块放在“通知”块之前会出现问题吗?)。
编辑: 关于问题的更多信息。
这是我的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 active 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:.
}
}
我能在前台接收消息的唯一方法是禁用方法交换,在我的 info.plist 中将 FirebaseAppDelegateProxyEnabled 设置为 NO。
在这种情况下,FCM文档说我必须在我的 appdelegate.swift 中实现两个方法:
- FIRMessaging.messaging().appDidReceiveMessage(userInfo) in didReceiveRemoteNotification callback
- FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Sandbox) in didRegisterForRemoteNotificationsWithDeviceToken callback
但如果我实现那些功能,即使应用程序处于前台,消息也停止到达。
我知道这很奇怪。
编辑2:
当应用程序在后台时,无法收到通知,但当我打开我的应用程序时,立即收到相同的通知(方法didReceiveRemoteNotification被触发)。
content_available
时删除priority
。我不是很熟悉APNS的工作原理,但是如果priority
和content_available
同时存在于单个负载中,则有可能会忽略该消息。如果有用请告诉我,好运! - AL.