didReceiveRemoteNotification not working in the background
Solution 1
Implementing didReceiveRemoteNotification
and didReceiveRemoteNotification:fetchCompletionHandler
is the correct way, but you also need to do the following:
Make sure to register for remote notifications, see documentation here:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
return YES;
}
Also make sure to edit Info.plist
and check the "Enable Background Modes" and "Remote notifications" check boxes:
Additionally, you need to add "content-available":1
to your push notification payload, otherwise the app won't be woken if it's in the background (see documentation here updated):
For a push notification to trigger a download operation, the notification’s payload must include the content-available key with its value set to 1. When that key is present, the system wakes the app in the background (or launches it into the background) and calls the app delegate’s application:didReceiveRemoteNotification:fetchCompletionHandler: method. Your implementation of that method should download the relevant content and integrate it into your app
So payload should at least look like this:
{
aps = {
"content-available" : 1,
sound : ""
};
}
Solution 2
- Register for push notification in app delegate.
- Add background mode in app capabilities.
- Add "content-available"="1" while sending the push notification(if you are using firebase replace "content-available"="1" by "content_available"="true" while sending the push notification from server side).
Solution 3
I had the same problem. Notification banner appeared, but -application:didReceiveRemoteNotification:fetchCompletionHandler: method was not called. The solution for me that worked was to add implementation of - application:didReceiveRemoteNotification: method and forward call to -application:didReceiveRemoteNotification:fetchCompletionHandler::
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
self.application(application, didReceiveRemoteNotification: userInfo) { (UIBackgroundFetchResult) in
}
}
Solution 4
I am creating an iOS project that will use Firebase Cloud Messaging (FCM) to deliver custom data elements, sent via Firebase/APNS notifications, from a company server to the iOS device.
The first thing I had to understand is that unlike Android, there is no similar type of 'Service' that will be able to capture and save information I'm sending, regardless if the app is in the foreground (active), background (still in memory) or not active (not in memory). Therefore, I have to use Notification messages NOT Data messages like I had designed for Android.
After much reading to understand both Apple APNS and the Firebase interface between the iOS app and APNS server, looking at countless posts on stackoverflow and other web resources, I finally figured out how to get this to work for my requirements.
When a Firebase Cloud Messaging (FCM) Notification message is sent from the server (or Firebase Console as the FCM defaults to Notification NOT Data messages), it is delivered via APNS and presented as a notification on the iOS device. When the user taps on the notification banner, iOS does the following: if the app is not running/loaded iOS launches the app, if the app is loaded/running but in the background iOS brings the app to the foreground OR if the app is in the foreground (all three cases), the message content is then delivered via func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {}.
One thing for sure, you Must Enable Background Modes and check Remote Notification, you DO NOT have to include {"content-available" : 1} in the payload.
1) Go through the APNS and Firebase setup, pretty straight forward, generate and register certificates and such.
2) In appDelegate, didFinishLaunchingWithOptions, add:
Messaging.messaging().delegate = self as? MessagingDelegate
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
}
else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
3) Then add these call back functions to appDelegate:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Print message ID.
if let messageID = userInfo["gcm.message_id"] {
print("\n*** application - didReceiveRemoteNotification - fetchCompletionHandler - Message ID: \(messageID)")
}
// Print full message.
print("\n*** application - didReceiveRemoteNotification - full message - fetchCompletionHandler, userInfo: \(userInfo)")
myNotificationService?.processMessage(title: userInfo["Title"] as! String
, text: userInfo["Text"] as! String, completion: { (success) in
if success {
completionHandler(.newData)
}
else {
completionHandler(.noData)
}
})
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.alert, .badge, .sound])
}
Very Helpful:
https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html
Solution 5
My device was in a bad state. I had to restart the device to get it working although I had done all the pre-requisites mentioned here.
Related videos on Youtube
YogevSitton
Updated on July 09, 2022Comments
-
YogevSitton almost 2 years
I'm working on a big app with a huge chunk of legacy code. Currently - there's an implementation for:
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
The problem is that it is only called when the app is in the foreground OR when the user taps the the notification while the app is in the background. I tried to implement:
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
But the app behaves the same. In any case - this method is not called when the app is in the background. What could be the problem?
-
KudoCC almost 9 yearsIt's normal that the method won't be called when app is in the background. System will notify you the notification through prompting a alert view or a banner.
-
Islam almost 9 yearsWhat's the iOS version of your device? Is it at least 7? Because
fetchCompletionHandler:
requires minimum iOS 7.
-
-
YogevSitton almost 9 yearsI'm already calling registerForRemoteNotificationTypes and Remote Notifications is enabled
-
Baris Akar almost 9 years@godmoney See my update answer, you need to add
"content-available":"1"
to your notification payload... -
Ashish Kakkad almost 9 years@BarisAkar Great. I did not know about
content-available
payload. +1 -
priyanka gautam over 8 yearsI am enabled Background mode for remote notifications and Payload should contain content-available:1 key-value pair But not call my background method
-
Baris Akar over 8 years@priyankagautam Sorry, but I don't know, what could cause your problem. Everything you need to do is actually described in this answer...
-
pqteru over 7 yearswhat if I didn't want to call
didReceiveRemoteNotification
when I launch the app by icon? -
Usman Nisar over 7 yearsHi ZaEem, have you found any solution
-
Wilson over 7 yearswhen the app is the background, sending a remote push notification only this method is called
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
-
ZaEeM ZaFaR over 7 years@UsmanNisar I have added the workaround for my problem and its working fine for me. is it not working for you ?
-
Kirk Hammett over 7 yearsFor those who are looking for this in new Xcode interface, take a look at your target -> Capabilities tab -> Background modes -> On
-
Yuchen over 6 years@BarisAkar the link in the answer is broken. Could you help fix it?
-
Baran Emre about 6 yearsThat did it. 1+
-
Gopik almost 6 yearsWithout "sound": "" -> Thanks @onmyway133 It saved me..... iOS 10 its working fine... But not working on iOS 11, Any suggestions?
-
Michał Ziobro over 4 yearsNot Info.plist but Capabilities there you can add Background Modes
-
bigbubble over 3 yearsThe same issue is occurring for iOS 14.
didReceiveRemoteNotification
method never gets called when app is in background(not force close). Any suggestion for this? I followed the exact procedure and added "content-available" : 1 in the aps.didReceiveRemoteNotification
only gets called in foreground. -
ScottyB over 3 yearsI thought I had this problem because the notification wasn't arriving immediately. Then I decided to wait, and wait, and wait. Over a full minute after receiving the "banner" notification while my app was in the background, my app delegate's didReceiveRemoteNotification method was called. No idea why it's taking so long, and I had to make a minor change to improve the UX.
-
ScottyB over 3 yearsCame back to add that the long delay in receiving the notification in the background was only with APNS Sandbox environment. The notification to Prod is very quick.