ios icon indicating copy to clipboard operation
ios copied to clipboard

Scheduled notifications are not handled when app is killed

Open Estebank94 opened this issue 4 years ago • 13 comments

Description

When I open a scheduled notification when the app is killed, the app opens and nothing happens. When I open a scheduled notification when the app is in foreground or background, the notification is handled.

This is the notification data I get when I open the app by tapping on a notification:

notification ios {"action": undefined, "badge": 0, "data": null, "finish": [Function finish], "fireDate": 1610466763000, "foreground": false, "id": undefined, "message": undefined, "reply_text": undefined, "soundName": "default", "title": undefined, "userInteraction": false}

I think there must be something wrong with the App Delegate but I followed the instructions and checked with the example provided.

AppDelegate.h

#import <UserNotifications/UNUserNotificationCenter.h>
...
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>
...

AppDelegate.m

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#import <React/RCTLinkingManager.h>

#import "RNBootSplash.h"

...

#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>

...

@implementation AppDelegate

// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
 [RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
 [RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler
{
  [RNCPushNotificationIOS didReceiveNotificationResponse:response];
}

...

  // Define UNUserNotificationCenter
  UNUserNotificationCenter *center =
      [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;
  
  return YES;
}

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}


- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
  return [RCTLinkingManager application:application
                   continueUserActivity:userActivity
                     restorationHandler:restorationHandler];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end

React Native version:

  SDKs:
    iOS SDK:
      Platforms: iOS 13.7, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.13.1 => 16.13.1 
    react-native: 0.63.4 => 0.63.4 
    @react-native-community/push-notification-ios": "^1.8.0"

Steps To Reproduce

  1. Schedule a local notification
  2. Kill App
  3. Open scheduled notification

Expected Results

The notification should be handled

Estebank94 avatar Jan 12 '21 02:01 Estebank94

+1

bang9 avatar Jan 26 '21 09:01 bang9

Any workaround?

kanelloc avatar Jan 26 '21 11:01 kanelloc

I didn't find one yet...

Estebank94 avatar Feb 04 '21 23:02 Estebank94

Same problem :(

cuttlas avatar Feb 09 '21 16:02 cuttlas

@Estebank94 Are you opening the notification through an action on the notification or just by tapping the notification?

Also, what do you mean the notification should be handled? By what?

ninjz avatar Feb 26 '21 06:02 ninjz

@ninjz do you know how I can handle an action when the app is killed, or is it not possible? Since the event listener is removed

joaocosta9 avatar Mar 03 '21 10:03 joaocosta9

@joaocosta9 Two things:

  1. Make sure you're not using react-native-splash-screen as that ends up swallowing some events which prevents you from receiving the callbacks on the delegate. (This was a huge breakthrough for me which took days to figure out)
  2. Since getInitialNotification() always returns null. Store the notification action response in didReceiveNotification callback inside of AsyncStorage and retrieve that on app launch. Also, delay the call of the callback inside of didReceiveNotification to make sure there is enough time to handle everything you need to process the notification action.

For me, the biggest issue now is getting this to work with the Watch. Can't seem to consistently get the notification action response from it when the app has been backgrounded for some time (> ~30mins). Still investigating this issue and my guess so far is that it's due to some other dependency.

ninjz avatar Mar 03 '21 10:03 ninjz

Hey @ninjz , thanks for your response. You are talking about the didReceiveNotificationResponse in the AppDelegate.m file correct?

joaocosta9 avatar Mar 03 '21 16:03 joaocosta9

@joaocosta9 Yes, if you set the AppDelegate as the delegate for the UNUserNotificationCenter.currentNotificationCenter

ninjz avatar Mar 05 '21 07:03 ninjz

I would really appreciate if somebody could share the code on how to store the didReceiveNotification response in the AsyncStorage

cuttlas avatar Mar 05 '21 08:03 cuttlas

@cuttlas me too, I tried to find a way to do that, but I could not find one. Im sorry @ninjz, is there any way you can help us with this ? 😅

joaocosta9 avatar Mar 05 '21 14:03 joaocosta9

@joaocosta9 Two things:

  1. Make sure you're not using react-native-splash-screen as that ends up swallowing some events which prevents you from receiving the callbacks on the delegate. (This was a huge breakthrough for me which took days to figure out)
  2. Since getInitialNotification() always returns null. Store the notification action response in didReceiveNotification callback inside of AsyncStorage and retrieve that on app launch. Also, delay the call of the callback inside of didReceiveNotification to make sure there is enough time to handle everything you need to process the notification action.

For me, the biggest issue now is getting this to work with the Watch. Can't seem to consistently get the notification action response from it when the app has been backgrounded for some time (> ~30mins). Still investigating this issue and my guess so far is that it's due to some other dependency.

@ninjz do you have any progress with this?

andrew-stupchuk avatar Mar 26 '21 10:03 andrew-stupchuk

+1

webgev avatar Jan 20 '22 09:01 webgev