Detect push notifications tap - ios

I know you can use this code for handling your notifications :
- (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
}
}
But this isn't reliable it does loops with number of current notifications so it shows my view controller hundres of time
So my question is :
is there any other "good" way we can use it to handle only the tapped notification ?

Related

How to handle remote notification with background mode enabled

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];
}
}

iOS silent notification cases

For silent push notification I have implemented this method :
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
{
if([userInfo[#"aps"][#"content-available"] intValue]== 1) //it's the silent notification
{
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
// CASE - 1
if (state == UIApplicationStateBackground )
{
//Badge increment
}
// CASE -2 for foreground
else {
//Badge increment
}
handler(UIBackgroundFetchResultNewData);
return;
}
Two scenario
1) I want to decrease the badge count when user clicks the notification .(app comes to foreground)
2) and take no action in badge when notification arrives while (app is in foreground ).
But for both the scenarios , same code is executed . And badge decrement occurs . (Commented as CASE - 2).
How to act according to these scenarios .

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
}
}

how to detect user clicked iOS remote notification?

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
}
}

didReceiveRemoteNotification not called in Background Mode

I am working on push notifications and the data I receive is in JSON format. How can I parse the JSON data, which is shown in the Notification Center below:
if your app in background/foreground mode call this method
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
if you used the above method you will face the following error in console
application:didReceiveRemoteNotification:fetchCompletionHandler:], but you still need to add "remote-notification" to the list of your supported UIBackgroundModes in your Info.plist.
To Resolve this issue
follow the image of steps
if your app in foreground mode call this method
- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo
choice no-2
- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
UIApplicationState state = [application applicationState];
// user tapped notification while app was in background
if (state == UIApplicationStateInactive || state == UIApplicationStateBackground) {
// go to screen relevant to Notification content
} else {
// App is in UIApplicationStateActive (running in foreground)
// perhaps show an UIAlertView
}
}
Swift
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
var state: UIApplicationState = application.applicationState()
// user tapped notification while app was in background
if state == .Inactive || state == .Background {
// go to screen relevant to Notification content
}
else {
// App is in UIApplicationStateActive (running in foreground)
// perhaps show an UIAlertView
}
}
If didReceiveRemoteNotification method is not called in background mode,please follow the below steps
First ON the Push Notification and Tick the check box of Remote Notifications of Background Mode in Capabilities of Target
Then
-(void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void
(^)(UIBackgroundFetchResult))completionHandler
{
if( [UIApplication sharedApplication].applicationState == UIApplicationStateInactive )
{
NSLog( #"INACTIVE" );
}
else if( [UIApplication sharedApplication].applicationState == UIApplicationStateBackground )
{
NSLog( #"BACKGROUND" );
}
else
{
NSLog( #"FOREGROUND" );
}
return YES;
}

Resources