Firebase background and inactive notifications not showing iOS - ios

Using FCM for push notifications in iOS 10:
This is the snipper that's getting called after pushing a notification via our own API:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// 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
[[FIRMessaging messaging] appDidReceiveMessage:userInfo];
if (userInfo[kGCMMessageIDKey]) {
NSLog(#"Message ID: %#", userInfo[kGCMMessageIDKey]);
}
completionHandler(UIBackgroundFetchResultNewData);
if(application.applicationState == UIApplicationStateBackground){
[[TWMessageBarManager sharedInstance] showMessageWithTitle:#"Bacgkround"
description:#"Wassup"
type:TWMessageBarMessageTypeSuccess callback:^{
}];
}
else if(application.applicationState == UIApplicationStateActive){
[[TWMessageBarManager sharedInstance] showMessageWithTitle:#"Active"
description:#"Wassup"
type:TWMessageBarMessageTypeSuccess callback:^{
}];
}
else if(application.applicationState == UIApplicationStateInactive){
[[TWMessageBarManager sharedInstance] showMessageWithTitle:#"InActive"
description:#"Wassup"
type:TWMessageBarMessageTypeSuccess callback:^{
}];
}
}
When the app is active, above method gets called and UIApplicationStateActive case gets executed and I am showing a pop-up using a 3rd party library. When I press the Home button and push a notification, above method gets called and UIApplicationStateBackground gets executed but I am not sure how do I show a notification in the form of a banner?
Is this the method where I have to handle the notifications? If yes, how do I handle Background and Inactive states?

you just have to put notification body in payload you receive from server, if you don't add it, iOS consider it as silent push notification and will not show notification banner.e.g
{
"data":{
"title":"mytitle",
"body":"mybody",
},
"notification":{
"title":"mytitle",
"body":"mybody",
},
}
when user clicks on notification banner in what ever state application is, you will get its call back method triggered as provided by firebase.e.g.
// [START receive_message]
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;
etc.
NOTE: no need to use any third party library to show notification banners as all this is controlled by iOS.

I do not know much about TWMessageBarManager but i can tell you can not user any lib or anything you've made custom to show notification while your app is not in foreground. If your app is in background and you receive a push notification the notification banner will be shown itself by the iOS

Related

iOS Push Notifications Flow

I'm working on push notification flow but not getting exactly how to handle it. I need a simple explanation, when push notification comes, which delegate is called
When user tap on push notification label
When user tap on App icon when push notification comes
I'm unable to maintain to my app application state, for me the flow should be like:
When user tap on push notification label: It should open a particular viewcontroller
When user tap on App icon when push notification comes: It should open same viewcontroller from where app goes in background
How I can achieve this in Xcode 8.1/iOS 10.1.1?
Also I'm using background mode remote notification and background fetch.
In AppDelegate.m used it to check where user tap icon
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
//Handle notification when the user click it while app is running in background or foreground.
if(application.applicationState == UIApplicationStateInactive) {
NSLog(#"Inactive - the user has tapped in the notification when app was closed or in background");
//do some tasks
}
else if (application.applicationState == UIApplicationStateBackground) {
NSLog(#"application Background - notification has arrived when app was in background");
}
else {
NSLog(#"application Active - notication has arrived while app was opened");
//do tasks
}
}
When a push notification sends from server a delegate call on app side but you have to register from app end by adding registerForPushNotifications.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
//Handle notification when the user click it while app is running in background or foreground.
//Where userinfo is a dict. It has the data sent from server
}

Determine if notification banner or notification in center was tapped to launch the app when app is background state

I have checked many threads and Apple Documentation for determining whether app is launched on tap of the notification.
I want to handle push notification only if user taps on notification.
I am not able to figure out reason of application:didReceiveRemoteNotification:fetchCompletionHandler: being called.
How can check if this method was called on tap of notification or direct from push when app is background.
Thanks.
Here is few steps for push Notification
1). When you app is killed, neither active nor in background. In that case didFinishLaunchingWithOptions will called when you receive any notification.
2). When your app is active or in background, in that case didReceiveRemoteNotification:fetchCompletionHandler** will called. You have to identify application state here as below.
if ( application.applicationState == UIApplicationStateActive ) {
// app was already in the foreground
}
else {
// app was just brought from background to foreground
}
- (void)application:(UIApplication *)app didReceiveRemoteNotification:(NSDictionary *)userInfo {
//No Need to store the push notification if it is in active or in closed state we can directly navigate to the screens
NSLog(#"notification didReceive method called");
if([app applicationState] == UIApplicationStateInactive) {
//If the application state was inactive, this means the user pressed an action button
//Handle the code after push notification received
}
else if ([app applicationState] == UIApplicationStateActive) {
//Application is in Active state handle the push notification here
}
}

APNs with background refresh. Refresh called twice, when the APN is delivered and when the notification is tapped on? [duplicate]

This question already has answers here:
Remote notification method called twice
(2 answers)
Closed 7 years ago.
I am trying to implement APNs in my app with the content-available key so that a background refresh will be triggered. Here is my code:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
if([userInfo[#"aps"][#"content-available"] intValue]== 1){
//This stops a refresh happening is a push is delivered with the app in the foreground
if(application.applicationState!=UIApplicationStateActive){
NSLog(#“Background push refresh called");
[self backgroundRefreshWithPushUpdate:NO andHandler:^(BOOL successful, BOOL newMessages) {
if(successful){
if(newMessages) handler(UIBackgroundFetchResultNewData);
else handler(UIBackgroundFetchResultNoData);
}
else{
handler(UIBackgroundFetchResultFailed);
}
}];
}
else handler(UIBackgroundFetchResultNoData);
}
}
I have this additional condition: if(application.applicationState!=UIApplicationStateActive) for refreshing in the background as I don't want it to be triggered if the app is in the foreground. However, if I receive a push and then tap on the notification to open the app ALL of the code in - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler is called again. This means my background fetch is called when the notification first comes in and then it's called again when the notification is tapped on. I don't want this to happen. Any ideas how I can get around this?
Here are the things to be noticed in application:didReceiveRemoteNotification:fetchCompletionHandler: method when you receive a push notification:1. When the app is not launched (i.e, when the app is neither in background nor in foreground), the method is called once and applicationState will be UIApplicationStateInactive.2. When the app is in foreground, the method is called once and applicationState will be UIApplicationStateActive.3. When the app is in background, the method is called twice, once when you receive the push notification, and other time when you tap on that notification. When you receive the push notification, applicationState will be UIApplicationStateBackground and when you tap on that notification, applicationState will be UIApplicationStateInactive.We can ignore it when the applicationState will be UIApplicationStateBackground and hence we can handle the push notification only once for all the three scenarios.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
if (application.applicationState == UIApplicationStateBackground) {
completionHandler(UIBackgroundFetchResultNoData);
return;
}
// Do whatever you need here and call completionHandler with appropriate UIBackgroundFetchResult
}

Which method will be triggered for pushnotification when app is in background?

I have implemented push notification in my App. When App is in foreground didReceiveRemoteNotification method is get called. But when app is in background this method is not called. Following pattern is used in server side:
{
aps: {
content-available: 1,
sound: "default"
}
}
But still the didReceiveRemoteNotification is not get called. What else is to be done to get triggered the method after push notification arrives.
There's a new API available to handle background events when the device receives a push notification:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
Now, as per the documentation:
Unlike the application:didReceiveRemoteNotification: method, which is
called only when your app is running, the system calls this method
regardless of the state of your app. If your app is suspended or not
running, the system wakes up or launches your app and puts it into the
background running state before calling the method.
When this method is called, your app has up to 30 seconds of
wall-clock time to perform the download operation and call the
specified completion handler block. In practice, your app should call
the handler block as soon as possible after downloading the needed
data. If you do not call the handler in time, your app is suspended.
More importantly, the system uses the elapsed time to calculate power
usage and data costs for your app’s background downloads.
To trigger this method, you notification payload must contain a key content-available:
{
"aps" : {
"content-available" : 1
},
"content-id" : 42
}
Example Code:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(#"Remote Notification userInfo is %#", userInfo);
NSNumber *contentID = userInfo[#"content-id"];
// Do something with the content ID
completionHandler(UIBackgroundFetchResultNewData);
}
didReceiveRemoteNotification method will be called when push notification arrives in app active state.
If app is inactive when push notification arrived, an option to invoke didReceiveRemoteNotification method is to click on the received notification from notification list and become active.
If app is inactive when push notification arrived and become active by without clicking on notification received, normally there is no way to invoke didReceiveRemoteNotification method.
If you app needs, you can handle it by custom server. Whenever app becomes active, API call can be implemented to list pending notifications.
This would be called:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
Check the launchOptions:
NSDictionary *pushInformation = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(pushInformation)
{
// App opened with push notification
}
didReceiveRemoteNotification Will be called if your app is in UIApplicationStateActive
didReceiveRemoteNotification will be called if your app is inUIApplicationStateBackground or UIApplicationStateInactive and the user opened a push notification from the notification center.
didFinishLaunchingWithOptions will be called upon launch if app was not in the background.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
if (application.applicationState == UIApplicationStateActive )
{
//Your Code here
}
else if (application.applicationState == UIApplicationStateBackground || application.applicationState == UIApplicationStateInactive)
{
//Your code here
}
}

Remote notification method called twice

I have implemented application:didReceiveRemoteNotification:fetchCompletionHandler: in my application delegate to respond to push notifications.
When a notification is received while the app is in the background, this method is called immediately and I fetch new data and execute the completion block when done. All as per the documentation. However, if I tap the notification alert this method gets called again, resulting in another network call and a UI update. I would have expected this method to be called once for each push notification, not once on receipt and again on action.
How have others implemented this method?
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[self loadSomeResource:^(NSData *data,NSError *error){
if (error) {
completionHandler(UIBackgroundFetchResultFailed);
}
else if (data){
completionHandler(UIBackgroundFetchResultNewData);
}
else {
completionHandler(UIBackgroundFetchResultNoData);
}
}];
}
Here are the things to be noticed in application:didReceiveRemoteNotification:fetchCompletionHandler: method when you receive a push notification:1. When the app is not launched (i.e, when the app is neither in background nor in foreground), the method is called once and applicationState will be UIApplicationStateInactive.2. When the app is in foreground, the method is called once and applicationState will be UIApplicationStateActive.3. When the app is in background, the method is called twice, once when you receive the push notification, and other time when you tap on that notification. When you receive the push notification, applicationState will be UIApplicationStateBackground and when you tap on that notification, applicationState will be UIApplicationStateInactive.We can ignore it when the applicationState will be UIApplicationStateBackground and hence we can handle the push notification only once for all the three scenarios.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
if (application.applicationState == UIApplicationStateBackground) {
completionHandler(UIBackgroundFetchResultNoData);
return;
}
// Do whatever you need here and call completionHandler with appropriate UIBackgroundFetchResult
}
Check your application.applicationState to know if you are in the background or inactive and act accordingly.

Resources