1

I'm having an issue handling the notification payload on some device. I'm sending push notifications to my users through Parse Cloud functions.

I'm using the below method to capture the notification and storing its payload so that the user can view all the received notifications in a dedicated view. On my personal device I always get the notification and it is saved correctly, on my friend's device though the notification arrive but if the App is in background the payload is not saved, while if the App is in foreground the payload is saved.

Can this be an issue of the device itself? Or maybe something related to the phone provider (I have h3g and he have Vodafone)?

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
// Parse push handler will show a UIAlertView
[PFPush handlePush:userInfo];

if (application.applicationState == UIApplicationStateInactive) {

    // tha app is inactive, transitioning to or from the background        
    completionHandler(UIBackgroundFetchResultNoData);

} else if (application.applicationState == UIApplicationStateBackground) {

    // tha app is running in background
    // add the notification to the notificationsArrayRecord
    NSDate *now = [[NSDate alloc]init];
    NSDictionary *aps = userInfo[@"aps"];
    NSString *alertMessage = aps[@"alert"];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSMutableArray *notificationsArrayRecord = [[defaults arrayForKey:@"notificationsArrayRecord"] mutableCopy];
    [notificationsArrayRecord addObject:@[now,alertMessage]];
    [defaults setValue: notificationsArrayRecord forKey:@"notificationsArrayRecord"];

    // update the notifications counter
    NSInteger pushCount = [[NSUserDefaults standardUserDefaults] integerForKey: @"pushCount"];
    pushCount ++;
    [defaults setInteger: pushCount forKey:@"pushCount"];
    [defaults synchronize];

    completionHandler(UIBackgroundFetchResultNewData);
} else {        
    // the app is running in foreground

    // add the notification to the notificationsArrayRecord
    NSDate *now = [[NSDate alloc]init];
    NSDictionary *aps = userInfo[@"aps"];
    NSString *alertMessage = aps[@"alert"];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSMutableArray *notificationsArrayRecord = [[defaults arrayForKey:@"notificationsArrayRecord"] mutableCopy];
    [notificationsArrayRecord addObject:@[now,alertMessage]];
    [defaults setValue: notificationsArrayRecord forKey:@"notificationsArrayRecord"];

    // update the notifications counter
    NSInteger pushCount = [[NSUserDefaults standardUserDefaults] integerForKey: @"pushCount"];
    pushCount ++;
    [defaults setInteger: pushCount forKey:@"pushCount"];
    [defaults synchronize];

    completionHandler(UIBackgroundFetchResultNewData);

    // refresh the menu buttons and the notification counter
    [[NSNotificationCenter defaultCenter] postNotificationName:@"appDidReceiveNotificationWhileActive" object:nil];
   }
  }
soumya
  • 3,801
  • 9
  • 35
  • 69
Diego
  • 366
  • 3
  • 18
  • How do you know that the notifications arrive? Are they shown in the Notification Center or are you sure that `didReceiveRemoteNotification` is called? If the app was force-quit by the user, the app won't be woken up and `didReceiveRemoteNotification` won't be called. Maybe he is force-quitting the app? – Baris Akar Jul 20 '15 at 12:04
  • I did a lot of tests with the 2 phones on my hand. The notification never fails to appear, it fails in being saved once i open the app. Sometimes even on my phone, so i don't think anymore it can be a phone issue..It is something with my code but i don't know what's wrong with it. – Diego Jul 20 '15 at 12:08

1 Answers1

1

I guess the problem is how you handle the application state UIApplicationStateInactive. In this case, you are not storing the information. You should also store it in this case, because the app can apparently be in this state, when you receive notifications. This also explains, why it fails sometimes. Also see this question, that states the app is in state UIApplicationStateInactive sometimes, when the device receives a notification.

You should refactor your code to store the data in all cases:

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
    // Parse push handler will show a UIAlertView
    [PFPush handlePush:userInfo];

    // add the notification to the notificationsArrayRecord     
    NSDate *now = [[NSDate alloc]init];
    NSDictionary *aps = userInfo[@"aps"];
    NSString *alertMessage = aps[@"alert"];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSMutableArray *notificationsArrayRecord = [[defaults arrayForKey:@"notificationsArrayRecord"] mutableCopy];
    [notificationsArrayRecord addObject:@[now,alertMessage]];
    [defaults setValue: notificationsArrayRecord forKey:@"notificationsArrayRecord"];

    // update the notifications counter
    NSInteger pushCount = [[NSUserDefaults standardUserDefaults] integerForKey: @"pushCount"];
    pushCount ++;
    [defaults setInteger: pushCount forKey:@"pushCount"];
    [defaults synchronize];

    if (application.applicationState == UIApplicationStateInactive) {
        // the app is inactive, transitioning to or from the background        
        completionHandler(UIBackgroundFetchResultNoData);
    } else if (application.applicationState == UIApplicationStateBackground) {
        // the app is running in background
        completionHandler(UIBackgroundFetchResultNewData);
    } else {        
        // the app is running in foreground
        completionHandler(UIBackgroundFetchResultNewData);

        // refresh the menu buttons and the notification counter
        [[NSNotificationCenter defaultCenter] postNotificationName:@"appDidReceiveNotificationWhileActive" object:nil];
    }
}

Update: I am not sure about calling completionHandler(UIBackgroundFetchResultNoData) in applicationState (no idea what this is good for), but maybe you need to call completionHandler(UIBackgroundFetchResultNewData) instead, also in this case, to get the data stored.

Also make sure you configured everything properly to receive notifications in background, [see this] answer(https://stackoverflow.com/a/31450953/594074).

Community
  • 1
  • 1
Baris Akar
  • 4,895
  • 1
  • 26
  • 54
  • Your answer looks very promising to me, I'm gonna try that out immediately and accept it once it gets approved and i can try it properly. In the meantime thank you. – Diego Jul 20 '15 at 12:24
  • Ok, i tried with your correction, the issue still exist. Some time the payload gets saved then 5 minutes later it's not saved. Tried again on two phones. The issue appear only when the app is in background state, because when it's in foreground it always succeed to save the payload. Also, if I tap on the iOS notification badge everything is saved correctly (well in this case with your code the payload gets saved twice but this would be a minor issue)... – Diego Jul 21 '15 at 14:35
  • ...Honestly i'm giving up on this thing..for what i'm concerned this is not a reliable system. I don't know if it depends on the synchronize method I'm using or the fact that I'm using NSUserDefaults to save the payload, the fact is that sometimes the app goes in a state where the didReceiveRemoteNotification method isn't called for some reasons..Yor answer was still useful to me. Thanks. – Diego Jul 21 '15 at 14:36
  • Read the update in my answer: I am not sure about calling `completionHandler(UIBackgroundFetchResultNoData)` in `applicationState` (no idea what this is good for), but maybe you need to call `completionHandler(UIBackgroundFetchResultNewData)` instead, also in this case, to get the data stored. Also make sure you configured everything properly to receive notifications in background, [see this] answer(http://stackoverflow.com/a/31450953/594074). – Baris Akar Jul 21 '15 at 14:44
  • Nope, i tried also with `UIBackgroundFetchResultNewData `. I even removed all the conditions and kept only the save and the completitionHadler, to be sure the code would always be called. Same result. In fact i just did a test and the payload didn't get saved. Payload saved for some time, then i left the phone in sleep mode for about 20 minutes, sent again a push and payload not saved. The configuration is fine, i checked again it and it's done right. – Diego Jul 21 '15 at 17:12
  • @Diego Are you sure, your app was running (in background) in that case? If your app is not running (in background) at all, your app won't be woken up to handle it, even though the notification will appear in the notification center. See [this answer](http://stackoverflow.com/a/31514104/594074)... – Baris Akar Jul 22 '15 at 08:10
  • Yes, I am sure I didn't force quit the app. Of course I can't be sure on which state the app was running at that exact moment. Maybe the issue is that sometimes iOS terminate the app for some reasons I'm unaware of, but I assure you I didn't force quit it and I was using it just some minutes before. – Diego Jul 22 '15 at 08:19