In an iOS app using remote notifications (coming from Parse.com) I have arrived, after spending some time researching on the subject, to the conclusion that I should not use remote notifications in the background or possibly use silent notifications.
But silent notification seem quite complex.
For example:
In this code:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(#"application:didReceiveRemoteNotification:fetchCompletionHandler:");
completionHandler(UIBackgroundFetchResultNewData);
}
The fact of adding the last line (completionHandler) prevents an error message.
But what does this do exactly? Where does this completionHandler come from?
I have never touched silent-notifications and I am kind of lost there.
The last line is completing block that will be called when you application is in background.
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
Above method get called when your application in running in background OR foreground mode.
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
If you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives.
When a remote notification arrives, the system displays the notification to the user and launches the app in the background (if needed) so that it can call this method. Launching your app in the background gives you time to process the notification and download any data associated with it, minimizing the amount of time that elapses between the arrival of the notification and displaying that data to the user.
Let me know if you need anymore clarification.
Related
I am working on core data and silent notifications. I don't have any thread safe implementation in core data. And when i get silent notifications i need to fetch & save couple of items into database.
So my question is does didReceiveRemoteNotification:fetchCompletionHandler always works on main thread? (Even the app is on background).
I did the experimentation, i sent silent notification when app is on the background, didReceiveRemoteNotification triggered in Thread 1(UIThread).
But still i want to make sure and prevent crashes related with thread issues.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler NS_AVAILABLE_IOS(7_0)
{
}
I have implemented Push Notification in my iOS app.I can see two delegate methods for didReceiveRemoteNotification like the below methods: What is the difference between these two methods?
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { }
and
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
completionHandler(UIBackgroundFetchResultNewData);
}
The first one is deprecated in iOS 10.0 use the second one. Information for second one
This method will be invoked even if the application was launched or resumed because of the remote notification. The respective delegate methods will be invoked first. Note that this behavior is in contrast to application:didReceiveRemoteNotification:, which is not called in those cases, and which will not be invoked if this method is implemented.
And for first one
Use UserNotifications Framework's -[UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:] or -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:] for user visible notifications and -[UIApplicationDelegate application:didReceiveRemoteNotification:fetchCompletionHandler:] for silent remote notifications
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { }**
Called when your app has received a remote notification. This method is deprecated in iOS 10.0
For more details click here
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { completionHandler(UIBackgroundFetchResultNewData); }**
Tells the app that a remote notification arrived that indicates there is data to be fetched.
For more details click here
The below method is updated one
This delegate method offers an opportunity for applications with the "remote-notification" background mode to fetch appropriate new data in response to an incoming remote notification. You should call the fetchCompletionHandler as soon as you're finished performing that operation, so the system can accurately estimate its power and data cost.
This method will be invoked even if the application was launched or resumed because of the remote notification. The respective delegate methods will be invoked first. Note that this behavior is in contrast to application:didReceiveRemoteNotification:, which is not called in those cases, and which will not be invoked if this method is implemented.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
completionHandler(UIBackgroundFetchResultNewData);
}
You app needs to handle all the possible push notification delivery states:
Your app was just launched
Your app was just brought from background to foreground
Your app was already running in the foreground
You can tell whether your app was just brought to the foreground or not in didReceiveRemoteNotification using this bit of code: Deprecated in iOS 10.0
(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo;
Tells the app that a remote notification arrived that indicates there is data to be fetched. Use this method to process incoming remote notifications for your app. Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running in the foreground, the system calls this method when your app is running in the foreground or background. In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
In addition
The block to execute when the download operation is complete. When calling this block, pass in the fetch result value that best describes the results of your download operation. You must call this handler and should do so as soon as possible. For a list of possible values, see the UIBackgroundFetchResult type.
This method is called when a push notification is received while the app is in background mode and the user clicks on notification. But I want to call a method when notification comes in background mode without the user to click on the notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(#"%#",userInfo);
}
For this to happen you need to enable Background mode for remote notifications. You can find it Capabilities section of the project. Besides that your incoming Notification Payload should contain content-available:1 key-value pair.
Then this method will be called immediately without user interaction.
Note: This works if the app is in Background or suspended state. If the app is completely killed or force quit by the user, it will not work.
There's a new feature in iOS 8: using a push notification to wake an app, which also lets the app refresh data in the background. How do I use this feature?
The push notification arrives with a value of 1 for the key 'content-available'. However, no data is received if the app is not already running in background. Why not?
There are couple of things here,
1.U need to check Remote Notification on under Background mode of the target in Capabilities section.
2.U need to implement below method,
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
I am using iOS7 and I am trying to determine if I can get the JSON payload in the following situation.
I have background mode "remote-notifications" enabled
The push notification is received while the app is terminated
The app is launched manually from the icon not from the notification center
When I launch the app from the icon itself after the notification has been received I do not get the push in the launch options from
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
and the following method does not get called either when app is manually launched from the icon
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
I finally figured out how you can get this!
As of iOS 7 you can get it!
Basically, you need to configure your application for background remote notifications.
So, in your info.plist file:
For required backgrounds - set it to app downloads content from push notifications.
In the AppDelegate.m file, you need to implement this method:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
See this for how to implement that: didReceiveRemoteNotification: fetchCompletionHandler: open from icon vs push notification
For your push notifications, you must have 'content-available': 1, as part of the push notification. This is what tells the application that there is new content before displaying the alert.
See this page for more information on background remote notifications: http://developer.xamarin.com/guides/cross-platform/application_fundamentals/backgrounding/part_3_ios_backgrounding_techniques/updating_an_application_in_the_background/