ios Push notification click handler when the app i

2019-09-18 06:02发布

问题:

I have the following code running to handle a push notification -

I receive the notification -> tap on it -> and then performing a jsCallBack -> passing the custom data as parameters to a JS function.

but this works only when the app is running in background or foreground.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    //Handle notification when the user click it while app is running in background or foreground.
    [[Pushbots sharedInstance] receivedPush:userInfo];
    //Get Custom field data
    NSString* Value1 = [userInfo objectForKey:@"customval1"];
    NSString* Value2 = [userInfo objectForKey:@"customval1"];
    NSLog(@"%@", Value1);
    NSLog(@"%@", Value2);

    NSString * jsCallBack = [NSString stringWithFormat:@"testfromdelegate('%@','%@')", Value1, Value2];
    NSLog(@"%@", jsCallBack);
    [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsCallBack];
}

I read posts in SO and few other blogs that didFinishLaunchingWithOptions is something that would help me handle the notification when the app is not running at all. This link has info but am not sure about the implementation for my scenario.

Please could someone help me on how to use didFinishLaunchingWithOptions in my case? What all I need is to get the custom data fields, pass them to my JSCallBack even when the app is not running.

Should I have both didReceiveRemoteNotification and didFinishLaunchingWithOptions in my delegate.m? Also, when I am also using didFinishLaunchingWithOptions in my delegate.m, what changes should I make in delegate.h?

UPDATE 1: I understood that, when the app is terminated, one cannot get access to the payload. And, when app is in foreground or background, it is the didReceiveRemoteNotification that works when there is a push notification. But, I am not able to invoke my JS callback function when I received the notification and I tapped on it while the app is in background. I need some help on how to handle this.

回答1:

You need to do following code in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

NSDictionary *userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
if (userInfo) {
    [self application:application didReceiveRemoteNotification:userInfo];
}


回答2:

First I think you can not access all the notifications which came when the app was not running. You only get access to the the notification which you clicked to activate the app. I think this thread here explains it very well

didReceiveRemoteNotification when in background

For your scenario I think you would need to somehow keep the counter on server side and when the app is active then exchange it and retrieve the ones missed by the app.

Now for the code to handle your case when app is launched you can do this in didFinishLaunchingWithOptions and I think you would need to leave your existing function didReceiveRemoteNotification because they will be called when a notification is received when app is running in background (is not terminated)

- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    UILocalNotification *localNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
    if (localNotif) 
    {
        NSDictionary *userInfo;
        NSString* Value1 = [userInfo objectForKey:@"customval1"];
        NSString* Value2 = [userInfo objectForKey:@"customval1"];
        NSLog(@"%@", Value1);
        NSLog(@"%@", Value2);
        NSString * jsCallBack = [NSString stringWithFormat:@"testfromdelegate('%@','%@')", Value1, Value2];
        NSLog(@"%@", jsCallBack);
        [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsCallBack];
        NSString *itemName = [localNotif.userInfo objectForKey:ToDoItemKey];
        [viewController displayItem:itemName];  // custom method
        NSString * jsCallBack = [NSString stringWithFormat:@"testfromdelegate('%@','%@')", Value1, Value2];
        NSLog(@"%@", jsCallBack);
        [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsCallBack];    
    }
   return YES;
}


回答3:

This works for me, as required in my question + the UPDATE-

If the app is in foreground or in background -

//app is in background/foreground
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    [[Pushbots sharedInstance] receivedPush:userInfo]; //Using Pushbots notification platform - a 3rd party push platform

    NSString* Value1 = [userInfo objectForKey:@"val1"];
            NSString* Value2 = [userInfo objectForKey:@"val2"];
            NSString * jsCallBack = [NSString stringWithFormat:@"testfromdelegate('%@','%@')", Value1, Value2];            

    // If the app is in the foreground just execute the javascript        
    if ( application.applicationState == UIApplicationStateActive ) {
        [self.viewController.webView stringByEvaluatingJavaScriptFromString: jsCallBack];
    } else {
    // If the app is in background, then force to execute the js code on the main thread
        [self.viewController.webView performSelectorOnMainThread:@selector(stringByEvaluatingJavaScriptFromString:) withObject:jsCallBack waitUntilDone:NO]
    }
}

If the app is in closed state, add this in didFinishLaunchingWithOptions

//Don't remove the existing code, just paste this before the return YES
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cordovaDidLoad) name:CDVPageDidLoadNotification object:self.viewController.webView];

    if (launchOptions) { //check if launchOptions is not nil
        NSDictionary *userInfo = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        self.myUserInfo = userInfo;
    }

and add this, which will be called after Cordova is loaded -

- (void)cordovaDidLoad {
    //Check that myUserInfo isn't null, that will mean that the app was completely closed and it was opened from the push notification

    if (self.myUserInfo) {
        NSString* Value1 = [self.myUserInfo objectForKey:@"val1"];
        NSString* Value2 = [self.myUserInfo objectForKey:@"val2"];
        NSString * jsCallBack = [NSString stringWithFormat:@"testfromdelegate('%@','%@')", Value1, Value2];
        NSLog(@"%@", jsCallBack);
        [self.viewController.webView stringByEvaluatingJavaScriptFromString: jsCallBack];
    }
}