quickstart-ios: FCM Swift - Application does not receive message data in background - iOS 10
Hello,
Since Parse.com is closed, I changed my communication module to Firebase. It would seem that my application does not receive a message (notification or data) in background.
I tried to send different messages:
{
"to": "My_Super_FCM_Token",
"content_available": true,
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
{
"to": "My_Super_FCM_Token",
"priority": "high",
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
{
"to": "My_Super_FCM_Token",
"priority": "high",
"content_available": true,
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
The application can receive messages (notification or data) in foreground. It works perfectly in foreground.
Here is my code from my AppDelegate.swift
:
import UIKit
import Foundation
import Firebase
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
import XCGLogger
let log = XCGLogger.default
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm.message_id"
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//adapt the storyboard if the device is an iPad or a iPhone
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)//self.adaptStoryboard()
self.window?.rootViewController = storyboard.instantiateInitialViewController()
self.window?.makeKeyAndVisible()
// MARK: Init Notification
registerForPushNotifications(application: application)
// Add observer for InstanceID token refresh callback.
NotificationCenter.default.addObserver(self,
selector: #selector(self.tokenRefreshNotification),
name: .firInstanceIDTokenRefresh,
object: nil)
if let token = FIRInstanceID.instanceID().token() {
print("TOKEN....")
print(token)
connectToFcm()
}
return true
}
func applicationWillResignActive(_ application: UIApplication) {
}
func applicationDidEnterBackground(_ application: UIApplication) {
log.info("Application: DidEnterBackground")
}
func applicationWillEnterForeground(_ application: UIApplication) {
}
func applicationDidBecomeActive(_ application: UIApplication) {
log.info("Application: DidBecomeActive")
connectToFcm()
}
func applicationWillTerminate(_ application: UIApplication) {
}
}
extension AppDelegate {
/**
Register for push notification.
Parameter application: Application instance.
*/
func registerForPushNotifications(application: UIApplication) {
print(#function)
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: {_, _ in })
// For iOS 10 data message (sent via FCM)
FIRMessaging.messaging().remoteMessageDelegate = self
log.info("Notification: registration for iOS >= 10 using UNUserNotificationCenter")
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
log.info("Notification: registration for iOS < 10 using Basic Notification Center")
}
application.registerForRemoteNotifications()
FIRApp.configure()
}
func tokenRefreshNotification(_ notification: Notification) {
print(#function)
if let refreshedToken = FIRInstanceID.instanceID().token() {
log.info("Notification: refresh token from FCM -> \(refreshedToken)")
}
// Connect to FCM since connection may have failed when attempted before having a token.
connectToFcm()
}
func connectToFcm() {
// Won't connect since there is no token
guard FIRInstanceID.instanceID().token() != nil else {
log.error("FCM: Token does not exist.")
return
}
// Disconnect previous FCM connection if it exists.
FIRMessaging.messaging().disconnect()
FIRMessaging.messaging().connect { (error) in
if error != nil {
log.error("FCM: Unable to connect with FCM. \(error.debugDescription)")
} else {
log.info("Connected to FCM.")
}
}
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
log.error("Notification: Unable to register for remote notifications: \(error.localizedDescription)")
}
// This function is added here only for debugging purposes, and can be removed if swizzling is enabled.
// If swizzling is disabled then this function must be implemented so that the APNs token can be paired to
// the InstanceID token.
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var token = ""
for i in 0..<deviceToken.count {
token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
}
log.info("Notification: APNs token: \((deviceToken as! NSData))")
log.info("Notification: APNs token retrieved: \(token)")
// With swizzling disabled you must set the APNs token here.
/*FIRInstanceID
.instanceID()
.setAPNSToken(deviceToken,
type: FIRInstanceIDAPNSTokenType.sandbox)*/
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
log.info("Notification: basic delegate")
// 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.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
analyse(notification: userInfo)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
log.info("Notification: basic delegate (background fetch)")
// 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.
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
analyse(notification: userInfo)
completionHandler(UIBackgroundFetchResult.newData)
}
}
@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) {
log.info("Notification: iOS 10 delegate(willPresent notification)")
let userInfo = notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
analyse(notification: userInfo)
completionHandler([])
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
log.info("Notification: iOS 10 delegate(didReceive response)")
let userInfo = response.notification.request.content.userInfo
// Print message ID.
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
// Print full message.
analyse(notification: userInfo)
completionHandler()
}
}
extension AppDelegate: FIRMessagingDelegate {
// Receive data message on iOS 10 devices while app is in the foreground.
func applicationReceivedRemoteMessage(_ remoteMessage: FIRMessagingRemoteMessage) {
log.info("Notification: Firebase FCM delegate remote message.")
analyse(notification: remoteMessage.appData)
}
}
Settings
Environment
- iOS 10
- Xcode 8.3.1
- Apple Swift version 3.1 (swiftlang-802.0.51 clang-802.0.41) Target: x86_64-apple-macosx10.9
Pods
- Using Firebase (3.15.0)
- Using FirebaseAnalytics (3.7.0)
- Using FirebaseCore (3.5.2)
- Using FirebaseInstanceID (1.0.9)
- Using FirebaseMessaging (1.2.2)
Info.plist
- FirebaseAppDelegateProxyEnabled: NO
Regards, Ysee
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 2
- Comments: 25 (4 by maintainers)
I fixed my issue by deleting the
FirebaseAppDelegateProxyEnabled
key fromInfo.plist
and updating the APNs certificates.Now it works perfectly using
"content_available": true
to receive messages while application is in background.Regards,
A few things:
Try updating to the latest SDK (4.0.0). The FCM setup is very different now (no longer need to call connect()/disconnect(), just set
shouldEstablishDirectChannel = true
, FIRApp -> FirebaseApp, FIRMessaging -> Messaging, etc.)Call
FIRApp.configure()
beforeapplication.registerForRemoteNotifications()
. Otherwise Firebase might not get your APNs token in order to configure your FCM token correctly for push notifications.If you send
data : ...
that means you’re sending an Apple silent notification. Silent notifications are noted by Apple as being a “low priority” notification, and there are certain cases where the silent notifications are NOT delivered, until the app is opened the next time:If you are debugging the app, and you click “Stop” in Xcode, that quits the app, but silent notifications will continue to work, so that’s a good way to test, as you can expect silent notifications to work, yet your app is not running.
@YMonnier when you posted this comment https://github.com/firebase/quickstart-ios/issues/246#issuecomment-292710316 were you getting data notifications when app was backgrounded or killed? And were you able to process the data to generate notification text to the user while app is backgrounded/killed?
Hi @ahmeric,
Below my answers about your troubles.
Did you try to send a payload from you server like this?
With this payload, the application can display notification popup. However, if you send a payload with only the data key:
your application will not display the notification popup. Of course you are able to use both of these keys into payload (
data
¬ification
)If you set the
content_available: true
into your payload, app will able to received messages in background.analyse
is just my parsing function to insert some data etc…Regards,