Search code examples
react-nativeaws-amplifyaws-pinpoint

(React Native - Using AWS Amplify) - Invariant Violation: Native module cannot be null


Description of the issue:

I'm implementing push notification in my React-Native app using this AWS Amplify doc and testing with the iOS part fails with the error "Invariant Violation: Native module cannot be null", however if I test (i.e fetching device token and sending push notification) the Android part it works. Screenshot of the error I see on the iOS is seen below :

enter image description here

What I have tried so far :

  1. Upgrading react-native version from 0.59.10 to 0.61.5
  2. As per this github post, I also tried installing the following:

    @react-native-community/push-notification-ios

    npm install aws-amplify@unstable

This module (aws-amplify@unstable) introduced an error 😓 saying TypeError: undefined is not an object (evaluating '_core.Amplify.register') so I decided to get rid of it.

  1. Using latest package of "@aws-amplify/pushnotification": "^3.0.13" works for Android but in iOS I'm back to the original error 😓 : "Invariant Violation: Native module cannot be null"

currently I've left my package.json as follows :

"dependencies": {
"@aws-amplify/pushnotification": "^1.1.4",
"@aws-amplify/analytics": "^1.3.3",
"@react-native-community/netinfo": "^5.7.0",
"@react-native-community/push-notification-ios": "^1.2.0",
"amazon-cognito-identity-js": "^4.2.1",
"aws-amplify": "^1.2.4",
"aws-amplify-react-native": "^4.2.0",
"axios": "^0.19.2",
"cache": "^2.3.1",
"react": "16.9.0",
"react-native": "^0.62.2"
}

Let me get some sleep, I'll continue debugging tomorrow morning ..


Solution

  • After hours of debugging it appears some versions don't play well with each-other and I've managed to fix the error "Invariant Violation: Native module cannot be null" and get Android & iOS push notification working 😊💪 using the following version aws amplify lib and @react-native-community/push-notification-ios:

    "dependencies": {
    "@aws-amplify/pushnotification": "^3.0.13",
    "@aws-amplify/analytics": "^1.3.3",
    "@react-native-community/netinfo": "^5.7.0",
    "@react-native-community/push-notification-ios": "^1.0.2",
    "amazon-cognito-identity-js": "^4.2.1",
    "aws-amplify": "^3.0.13",
    "aws-amplify-react-native": "^4.2.0",
    "axios": "^0.19.2",
    "cache": "^2.3.1",
    "react": "16.9.0",
    "react-native": "^0.62.2"
    },
    

    or

    "dependencies": {
    "@react-native-community/push-notification-ios": "^1.2.0",
    "@react-native-community/netinfo": "^5.7.0",
    "@aws-amplify/pushnotification": "^3.1.2",
    "@aws-amplify/analytics": "^1.3.3",
    "@aws-amplify/core": "^3.3.2",
    "amazon-cognito-identity-js": "^4.2.1",
    "aws-amplify-react-native": "^4.2.0",
    "aws-amplify": "^3.0.16",
    "axios": "^0.19.2",
    "cache": "^2.3.1",
    "react": "16.9.0",
    "react-native": "^0.62.2"
    },
    

    It appears AWS Amplify (push notification module for iOS) has switched from react-native core to @react-native-community/push-notification-ios. Therefore, here's some changes due to this migration which one might need to cross-check incase you run into this issue :

    Step 1 : Update Podfile

    Remove 'React-RCTPushNotification' from your Podfile (which you can find in ios folder).:

    pod 'React-RCTPushNotification', :path => '../node_modules/react-native/Libraries/PushNotificationIOS'
    

    Step 2: Link the PushNotificationIOS library

    Step 2.1 : Automatic Linking

    Add the following RNCPushNotificationIOS to your podfile (which you can find in ios folder).

    pod 'RNCPushNotificationIOS', :path => '../node_modules/@react-native-community/push-notification-ios/RNCPushNotificationIOS.podspec'
    

    And then install pod dependencies by running following command: cd ios && pod install

    Step 2.2 : Manual Linking (if Auto linking doesn't work for you consider this option)

    Drag this PushNotificationIOS.xcodeproj file (node_modules/@react-native-community/push-notification-ios/ios) to your project on Xcode (usually under the Libraries group on Xcode):

    enter image description here

    Add libRNCPushNotificationIOS.a into your linked Binaries by selecting Project Navigator -> Target -> Build Phrases -> Linked Binary with Libraries (make sure libRNCPushNotificationIOS.a is there)

    enter image description here enter image description here

    Step 3 : Augment AppDelegate

    Step 3.1 : Update AppDelegate.h

    At the top of the file add the following :

    #import <UserNotifications/UNUserNotificationCenter.h>
    

    Then, add the 'UNUserNotificationCenterDelegate' to protocols as shown below :

    @interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>
    

    Step 3.2 : Update AppDelegate.m

    At the top of the file add the following :

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

    Replace all entries in your AppDelegate.m for RCTPushNotificationManager with RNCPushNotificationIOS

    Then, add the following code snippet just before @end as per react-native-community.push-notification-ios

    // Required to register for notifications
    - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
    {
      [RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
    }
    // 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 the localNotification event.
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
    {
      [RNCPushNotificationIOS didReceiveLocalNotification:notification];
    }
    

    Other helpful Tips!

    whenever you update your package.json, do the following :

    rm -rf -rf node_modules
    yarn cache clean --force
    yarn install
    cd ios && pod install
    React-native start -- --reset-cache
    

    Hope this helps someone!