ios: getInitialNotification is always returning null

Bug

I can’t get getInitialNotification() to work, its always returning null. Regular notification when the app is already open is working fine, but if the app is closed and I receive a new notification it will ways return null for me.

Environment info

React native info output:

System:
    OS: macOS 10.14.6
    CPU: (4) x64 Intel(R) Core(TM) i7-7660U CPU @ 2.50GHz
    Memory: 1.39 GB / 16.00 GB
    Shell: 5.3 - /bin/zsh
  Binaries:
    Node: 8.10.0 - ~/.nvm/versions/node/v8.10.0/bin/node
    Yarn: 1.17.0 - /usr/local/bin/yarn
    npm: 5.6.0 - ~/.nvm/versions/node/v8.10.0/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 12.4, macOS 10.14, tvOS 12.4, watchOS 5.3
    Android SDK:
      API Levels: 28
      Build Tools: 28.0.3, 29.0.1
      System Images: android-Q | Google Play Intel x86 Atom
  IDEs:
    Android Studio: 3.4 AI-183.6156.11.34.5692245
    Xcode: 10.3/10G8 - /usr/bin/xcodebuild
  npmPackages:
    react: 16.8.6 => 16.8.6
    react-native: 0.60.4 => 0.60.4
  npmGlobalPackages:
    react-native-cli: 2.0.1

Library version: 1.0.2

Steps To Reproduce

  1. Install the library
  2. Add all settings to AppDelegate.m
  3. Add code to your app
  4. Send a notification
componentDidMount() {
    PushNotificationIOS.addEventListener('notification', function(notification) {
      console.log('Log - notification is open', notification);
      if (!notification) {
        return;
      }
      const data = notification.getData();
      Alert.alert(JSON.stringify({ data, source: 'CollapsedApp' }));
    });

    PushNotificationIOS.getInitialNotification().then(notification => {
      console.log('Log - notification from closed', notification);
      if (!notification) {
        return;
      }
      const data = notification.getData();
      Alert.alert(JSON.stringify({ data, source: 'ClosedApp' }));
    });
    PushNotificationIOS.requestPermissions();
  }

A code sample can be found here https://github.com/filipecrosk/react-native-push-notification-ios-test

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 21
  • Comments: 27

Commits related to this issue

Most upvoted comments

disabling Debug JS Remotely solved the issue for me.

I found this to be a problem when the Scheme’s Build Configuration is set to Debug but not when it’s set to Release. I’m using React Native 0.59.9 and not using this library yet.

Details

At least in my case, through some digging in Objective-C, I found that two React Native bridges were created when doing a Debug build, while only one was created for a Release build. For Debug, the initial notification was included in the first bridge’s bridge.launchOptions (ref) while bridge.launchOptions was nil for the second instance. I added some debugging statements in RCTBridge’s setUp method, which is how I discovered it was being called twice.

I then changed the Scheme’s Build Configuration to Release and tried again. Only one React Native bridge was created and PushNotificationIOS.getInitialNotification returned the notification I used to launch the app.

I had this issue and solved it, at least enough for my needs.

On RN 0.59.10, running locally on a device using a dev/debug build (hot reload, debugger running) all calls to getInitialNotification returned null. Following @cmoel comment, I created a release build and distributed the .ipa to my test device. It worked fully there, with push notifications to a closed app as well as a backgrounded app. getInitialNotification would return the notification correctly, using exactly the same code as I ran in the dev/debug build.

Obviously this isn’t ideal. It would be great to be able to received initial notifications on a dev build with debugger and hot reload working. I’m wondering if this isn’t really a bug but is actually an issue with how react-native loads the js bundle. In my dev build, whenever the app is opened from closed state, the js bundle is redownloaded. Perhaps this is in essence opening the app twice, and the initial notification is not available by the time it opens fully.

I still could’t get this fixed. Can some one look into my test project repo and help me to identify the issue.

https://github.com/anishtr4/salesforce_react_pushnotitifcation.git

Does any one have a working GitHub repo . I tried almost all the above fixed none of them didn’t worked . I have tried in release mode also still getinitialnotification always return null. This happens for localnotification and remotenotification

Ran into this issue as well. Basically the initial notifications don’t seem to be part of the normal flow, but need to be processed in the initial launch method. With this hack I am adding a delay, and firing off the initial notification (including a fake completion method), which should fit into the normal notification listener pattern. Hopefully this works until there’s an official fix.


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

/*
Usual setup for notifications as per docs
*/

  if (launchOptions) { 
      NSDictionary *notification = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
      NSString *const RCTRemoteNotificationReceived = @"RemoteNotificationReceived";
    
       if (notification) {
         double delayInSeconds = 5.0;//waiting for debug load to finish...this is a guess
         
         dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
         dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
           NSLog(@"Initial notification %@",notification);
           
           NSDictionary *userInfo = @{@"notification": notification, @"completionHandler": ^(){}};
           [[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
                                                               object:self
                                                             userInfo:userInfo];
         });
        
       }
   }

      return YES;
}

@opula I’m not well versed in it either but I threw a gist together that should be more helpful. The swift and obj-c files go in ‘ios/app name/Native’ folder. here ya go - https://gist.github.com/shanemduggan/b22c60fa1d0bacf364c91e83efe0926c

We ended up writing native code to handle this since it wasn’t working with the library. Hope this helps.

JS Helper async function getInitialNotification() { if (Platform.OS === 'ios') { return await NativeModules.NativeHelpers.getInitialNotification(); } return null; }

Swift @objc func getInitialNotification(_ resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { let launchOptions = (UIApplication.shared.delegate as! AppDelegate).launchOptions let notification = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] resolve(notification) }

Objective-C #import <React/RCTBridgeModule.h> @interface RCT_EXTERN_MODULE(NativeHelpers, NSObject) RCT_EXTERN_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) (dispatch_queue_t)methodQueue {return dispatch_get_main_queue();} (BOOL)requiresMainQueueSetup { return YES;} @end