简体   繁体   中英

How can I intercept an iOS Push Notification before it's displayed on the lock screen notification center?

I'm working on integrating an app with GCM in order to get simple global topic Push Notifications. The server side which communicates with GCM is written in Java/Spring, and for the most part is working as expected. However, I'm having issues with something that may not be possible on the iOS side of things.

Ideally, rather than my push notification just being a flat string with a message, I'd like to send over a JSON structure (in string format) with a few bits of metadata, as after the notification is displayed, I intend to keep it around for review elsewhere in the app.

Now, when the app is active, I have no issue, as my app delegate runs

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo 
    fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
    ....
}

which with a notification registration in my main viewController, happily passes along the remote notification to my viewController code where I can parse the JSON and do with it how I please.

However, I can't seem to find an analogous method/procedure I can define that gives me the same control to a notification that comes in when the app is not actively in the foreground. This results in a lock screen push notification that's displaying my JSON structure in string format, obviously not what I want.

Now, technically I could simply push the message, and use the message string itself as a unique key to hit my database manually for the metadata, but I'd like to avoid this for two reasons. One, it seems like a waste of time/resources, but two, I'd like some control on the client side of the notifications. I'm having issues where on different devices (iPad 2 vs iPhone 5s), my code will display duplicate push notifications, that is, the iPad gets the push and shows it once, the iPhone appears to receive it twice. I'm worried I'm misunderstanding the usage of

    UIUserNotificationType allNotificationTypes =
    (UIUserNotificationTypeAlert);
    UIUserNotificationSettings *settings =
    [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    [[UIApplication sharedApplication] registerForRemoteNotifications];


    [[GCMService sharedInstance] startWithConfig:[GCMConfig defaultConfig]];

these lines and how they effect what gets displayed on the lock screen, but regardless I'd still rather have manual control if it all possible to ensure duplicates are never displayed.

You can send whatever you want trough notifications, there some value that you iOS device will take as mandatory, if you send the following message you can show some message and send additional data with the notification, imagine this base notification:

{
  aps: {
    alert: "Hi there"
  }
}

This notification will show the alert message on the lock screen and the notification bar on you device, but can also send this:

{
  aps: {
    alert: "Hi there",
    content-available: 1, // Add this if you want background processing
    sound: "" // If you don't want to show the notification on the notification area nor the lock screen.
  }
  data: {
    effectiveTime: ...,
    expirationTime: ...,
    message: ...,
    ...
  }
}

This will show exactly the same notification on you device than the first one, but in this case you can do anything you want with the data using didReceiveRemoteNotification: method

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
  NSLog(@"My data sent trough GCM: %@", userInfo[@"data"]);
}

The only keys you can use to your data are the listed in 3-1 and 3-2 on the official push notifications docs

If you want to manage background processing, according to the docs you should use (as you said) the application:didReceiveRemoteNotification:fetchCompletionHandler: but everything else remain the same:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler {

  switch (application.applicationState) { 
    case UIApplicationStateInactive:
      // Do whatever you want if the app is inactive
      handler(UIBackgroundFetchResultNewData);
      break;

    case UIApplicationStateBackground:
      // Do whatever you want if the app is in background
      handler(UIBackgroundFetchResultNewData);
      break;

    case default:
      // Do whatever you want if the app is active
      handler(UIBackgroundFetchResultNewData);
      break;
  }
}

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