简体   繁体   中英

When my app is in background, push notifications are handled only if I touch the top notification banner and not working while I click app icon

I've implemented application:didReceiveRemoteNotification: to store data in my app when a push notification is received.
However when my app is in background and I receive a notification, the data is stored only if I touch the notification banner appearing on top:

Instead, if I touch the app icon to reopen it, the content of the notification is not stored:

application:didReceiveRemoteNotification: is invoked only when I push the notification banner on top.

I've used applicationWillEnterForeground and didFinishLaunchingWithOptions methods and while clicking the app icon and debugging its entering applicationWillEnterForeground and control goes nowhere. Here is the code for didFinishLaunchingWithOptions and applicationWillEnterForeground and didReceiveRemoteNotification .

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    self.isForeground = YES;

    // Let the device know we want to receive push notifications
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    storage= [[NSMutableArray alloc]init];
    if (launchOptions != nil) {
        // launched from notification item click
        NSDictionary *userInfo = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
        if (userInfo != nil) [self HandleNotification:userInfo];
    }
    return YES;
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    isForeground = YES;
    NSArray *subviews = [window subviews];
    for (int i = 0; i < [subviews count]; i++) {
        [[subviews objectAtIndex:i] removeFromSuperview];
    }
    //[self.window addSubview:tabBarController.view];
    [self.window makeKeyAndVisible];
    self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
    self.window.rootViewController = self.viewController; 
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    [self HandleNotification:userInfo]; 
}

- (void)HandleNotification:(NSDictionary *)userInfo {
    ApiWrapper *wrapper = [[ApiWrapper alloc] init];
    NSString *dteStr = [[NSString alloc] init];
    NSDate *nowdate = [NSDate date];
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    //[dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/London"]];
    [dateFormat setDateFormat:@"dd/MM/yyyy HH:mm:ss"];
    dteStr = [dateFormat stringFromDate:nowdate];
    [dateFormat release];

    NSString *notifId = [userInfo objectForKey:@"NotificationId"];
    NSData *test = self.strTest;
    NSString *strToken = [NSString stringWithFormat:@"%@", test];
    strToken = [strToken substringWithRange:NSMakeRange(1, [strToken length] - 2)];     

    [wrapper deviceResponse:notifId:dteStr:strToken];

    NSLog(@".....user info%@", userInfo);
    NSDictionary *pushInfo = [userInfo  objectForKey:@"aps"];
    NSString *alertstring = [pushInfo objectForKey:@"alert"];
    NSLog(@"Alertstring: %@", alertstring);

    [UIApplication sharedApplication].applicationIconBadgeNumber = [[[userInfo objectForKey:@"aps"] objectForKey: @"badgecount"] intValue];

    MLNotifMessage *objNotif = [[MLNotifMessage alloc] init];
    objNotif.notifText = alertstring;    
    NSDate *nowdate1 = [NSDate date];
    NSDateFormatter *dateFormat1 = [[NSDateFormatter alloc] init];
    //[dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/London"]];
    [dateFormat1 setDateFormat:@"dd/MM/yyyy HH:mm:ss"];
    objNotif.datenow = [dateFormat1 stringFromDate:nowdate1];
    [dateFormat1 release];

    NSLog(@"Date in delegate class is %@", objNotif.datenow);
    [storage addObject:objNotif];    

    if (self.isForeground) {
        NSArray *subviews = [window subviews];
        for (int i = 0; i < [subviews count]; i++) {
            [[subviews objectAtIndex:i] removeFromSuperview];
        }
        [self.window makeKeyAndVisible];
        self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
        self.window.rootViewController = self.viewController;
    }
}

You can not get data for push notification if clicked on app icon on home screen. But there is way around, you could send a small payload to your server whenever the app enters in foreground, then ask for the server to send push notification immediately.

Also take a look at this : your question is possibly duplicate of it.

Hope this helps you.

In general your app should not require the contents of push notifications for normal operation. Apple doesn't even guarantee that push notifications will be delivered (it will drop all but the most recent if the device is unavailable).

Your app should always talk to the server to get the authoritative state of the user's data (or whatever it is you presenting). If you do receive a push notification you can of course use that as a cue to update or display new information. But even when the user taps your app icon normally (therefore no notification) you should contact the server to fetch or update everything you need.

Even though this is an older question, it ranks high in this topic and there's a solution for it as of iOS7.

There's a method called application:didReceiveRemoteNotification:fetchCompletionHandler: which will get called even if your application is in the background.

The problem I was having is that it wasn't getting called. I then found this article and realized I had to enable "Remote Notifications" inside of my project's Capabilities in order for this to work.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM