When user taps on a remote notification, the following callback is triggered in the app delegate:
-application:didReceiveRemoteNotification:fetchCompletionHandler:
in this scenario, application is launched and the app state is UIApplicationStateActive which I interpret it as user actioned on a remote notification.
the problem:
This method can also get called when a remote notification arrives and app is in the foreground with inactive state.
example: when notification center view is open(swipe from top edge of screen down) or a UIAlert is open. In both case application state is UIApplicationStateActive and there is no way to tell whether it's a user actioned notification or system push received.
Q: How can I determine if didReceiveRemoteNotification callback is response to user tapping on remote notification vs arrival of remote notification?
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateActive)
{
//When your app is in foreground and it received a push notification
}
else if (state == UIApplicationStateInactive)
{
//When your app was in background and it received a push notification
}
Also, didFinishLaunchingWithOptions will be called if the app was not running and the user tapped a notification. I have not tried it but i can assume you can get the notification details from options.
To differentiate both calls in didReceiveRemoteNotification you can add this code from below.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
if ([UIApplication sharedApplication].applicationState == UIApplicationStateInactive) {
[[NSNotificationCenter defaultCenter] postNotificationName:#“inactivePush" object:nil];
}
else if([UIApplication sharedApplication].applicationState==UIApplicationStateActive){
[[NSNotificationCenter defaultCenter] postNotificationName:#"appOpenPush" object:nil];
}
//When the app is in the background
else {
}//End background
}
}
Related
I build and app that has Background Modes enabled, and the push notification payload that the app gets has "content-available" key.
This setup results in didReceiveRemoteNotification being called EVERY TIME the app gets a push notification, which means that if i get 3 push notifications while the app is in the background - the function will fire 3 times and the code inside it will be executed when the app will applicationDidBecomeActive
My biggest problem is that there is NO way to know if a user tapped the Push System Alert or tapped the app icon to bring the app from background, since regardless of the user's action, the didReceiveRemoteNotification will fire.
Is there a way to know for sure that the user tapped on the Sys alert?
and this: http://samwize.com/2015/08/07/how-to-handle-remote-notification-with-background-mode-enabled/
and other answers
don't seem to be helpful
For app is background push
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
if ( application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground )
{
//opened from a push notification when the app was on background
}
}
For app is terminate state
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (launchOptions != nil) {
// Launched from push notification
NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
}
}
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
}
An app is running on iPhone and user tap the home button once and app will enter background.
after 2 or 3 seconds local notification arrives and user tap on local notification.
app will again enter in foreground and become active and didReceiveLocalNotification will be called.
How to determine that app become active by tapping on local notification not the app icon.
Here is an easy way to detect what's your App's status when UILocalNotification fired and if
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
is called, this makes sure that local notification is received.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
UIApplicationState state = [application applicationState];
if (state == UIApplicationStateInactive) {
// Application was in the background when notification was delivered.
} else {
}
}
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
}
}
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
}
}