smj2393
smj2393

Reputation: 1957

iOS UNUserNotificationCenter didReceiveNotificationResponse only run code if app is open in background

Is it possible to conditionally run code if the app is inactive or in the background.

These are the 2 scenarios:

Here is my code:

// Push notification received in background
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
  NSDictionary *userInfo = response.notification.request.content.userInfo;

  [[SEGAnalytics sharedAnalytics] receivedRemoteNotification:userInfo];

  if ([HSBeacon isBeaconPushNotification:userInfo]) {
    UIApplication *applicaiton = [UIApplication sharedApplication];

    // @todo Do not run if app was killed
    if (application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground) {
      NSString *helpScoutBeaconID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"HelpScoutBeaconID"];
      HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:helpScoutBeaconID];
      [HSBeacon handlePushNotification:userInfo beaconSettings:settings];
    }
    // End of conditional code
  }

  completionHandler();
}

I've tried using:

    UIApplication *applicaiton = [UIApplication sharedApplication];

    if ( application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground) {
      ...
    }

But this fires when the app is killed, inactive or in the backgorund.

Thanks

Upvotes: 1

Views: 1248

Answers (2)

smj2393
smj2393

Reputation: 1957

Thanks @ScottPetit for you answer! I had to change a few things, but got it working with:

AppDelegate.h

// Use a local variable to determine if we deeplink to help scout chat
@property (nonatomic, assign) BOOL launchedFromPushNotification;

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  NSDictionary *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
  if (notification) {
    self.launchedFromPushNotification = YES;
  } else {
    self.launchedFromPushNotification = NO;
  }

  ...
}


// Push notification received in foreground
 - (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
  self.launchedFromPushNotification = NO;
}

// Push notification received in background
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
  NSDictionary *userInfo = response.notification.request.content.userInfo;

  if ([HSBeacon isBeaconPushNotification:userInfo] && !self.launchedFromPushNotification) {
    NSString *helpScoutBeaconID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"HelpScoutBeaconID"];
    HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:helpScoutBeaconID];
    [HSBeacon handlePushNotification:userInfo beaconSettings:settings];

    self.launchedFromPushNotification = NO;
  }

  completionHandler();
}

Thanks for all your help!

Upvotes: 2

ScottPetit
ScottPetit

Reputation: 814

It feels like there must be a better way to do this, but one way that I think would work is keeping a local variable that you set in:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler;

That delegate is only called if the application is currently in the foreground, so if you had a property like

@property (nonatomic, assign) BOOL receivedWillPresentNotification;

then you could potentially implement this like

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
  // Whatever other logic you have here
  self.receivedWillPresentNotification = YES;
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
  NSDictionary *userInfo = response.notification.request.content.userInfo;

  [[SEGAnalytics sharedAnalytics] receivedRemoteNotification:userInfo];

  if ([HSBeacon isBeaconPushNotification:userInfo] && self.receivedWillPresentNotification) {
      NSString *helpScoutBeaconID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"HelpScoutBeaconID"];
      HSBeaconSettings *settings = [[HSBeaconSettings alloc] initWithBeaconId:helpScoutBeaconID];
      [HSBeacon handlePushNotification:userInfo beaconSettings:settings];
  }

  self.receivedWillPresentNotification = NO;
  completionHandler();
}

Again there's probably a better solution, related to checking for notifications in applicationDidFinishLaunching and checking the state of the application there that you could then store, but I think you could potentially use the other UNUserNotificationCenterDelegate methods as a proxy.

Upvotes: 1

Related Questions