Kuldeep Dubey
Kuldeep Dubey

Reputation: 1107

Notification not receiving in iOS for react native project

I have a react native project. I am able to receive the FCM token successfully but when trying to send a notification, the app doesn't receive the notification.
The steps I followed are as below:

  1. Created a project in Firebase Console.
  2. Added the Firebase .plist in the projectName through Xcode.
  3. ran npm install --save react-native-firebase
  4. Added in podfile: pod ‘Firebase/Core’
  5. ran pod install
  6. Update AppDelegate.m with #import <Firebase.h> and [FIRApp configure];
  7. Added the APNS in the Firebase Dashboard for iOS App Cloud Messaging.
  8. Updated the capabilities with Push Notification and Background Modes > Remote notification
  9. In info.plist FIRAnalyticsDebugEnabled, FirebaseAppDelegateProxyEnabled, FirebaseScreenReportingEnabled is set to No

using const fcmToken = await firebase.messaging().getToken(); I am able to get token.

Below is the code for the notification listener.

async createNotificationListeners() {

    /*

     * Triggered when a particular notification has been received in foreground

     * */



    this.notificationListener = firebase.notifications().onNotification((notification) => {


        const {
            title,
            body
        } = notification;

        this.custom_data = notification.data;

        const localNotification = new firebase.notifications.Notification({

                show_in_foreground: true,

            })

            .setSound('default')

            .setNotificationId(notification.notificationId)

            .setTitle(notification.title)

            .setBody(notification.body)




        firebase.notifications()

            .displayNotification(localNotification)

            .catch(err => Alert.alert(err));

    });




    /*

     * If your app is in foreground and background, you can listen for when a notification is clicked / tapped / opened as follows:

     * */

    this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {

        if ("title" in notificationOpen.notification.data) {

            const {
                title,
                body,
                secret_key,
                user_id,
                realm_id,
                user_os,
                user_location
            } = notificationOpen.notification.data;

            this.props.navigation.navigate('Verify', {
                title: title,
                body: body,

                secret_key: secret_key,
                user_id: user_id,
                realm_id: realm_id,
                user_os: user_os,
                user_location: user_location
            });

        } else {

            const {
                title,
                body,
                secret_key,
                user_id,
                realm_id,
                user_os,
                user_location
            } = this.custom_data;

            this.props.navigation.navigate('Verify', {
                title: title,
                body: body,

                secret_key: secret_key,
                user_id: user_id,
                realm_id: realm_id,
                user_os: user_os,
                user_location: user_location
            });

        }

    });



    /*

     * If your app is closed, you can check if it was opened by a notification being clicked / tapped / opened as follows:

     * */

    const notificationOpen = await firebase.notifications().getInitialNotification();

    if (notificationOpen) {

        const {
            title,
            body,
            secret_key,
            user_id,
            realm_id,
            user_os,
            user_location
        } = notificationOpen.notification.data;

        this.props.navigation.navigate('FCM', {
            title: title,
            body: body,

            secret_key: secret_key,
            user_id: user_id,
            realm_id: realm_id,
            user_os: user_os,
            user_location: user_location
        });

    }

    /*

     * Triggered for data only payload in foreground

     * */

    this.messageListener = firebase.messaging().onMessage((message) => {

        console.log("JSON.stringify:", JSON.stringify(message));

    });

}

Please do let me know if more details required.

EDIT

I have updated the code. Now I am able to get firebase.messaging().onMessage() code working and receive a trigger in the foreground. Still unable to get the notification when the app is in the background. Below is the change which I have made.

const fcmToken = await firebase.messaging().getToken();

firebase.messaging().ios.registerForRemoteNotifications().then((flag)=>{
        console.log("registered", flag);
      }).catch((err)=>{
        console.log("message", err);
      });

AppDelegate.m

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase.h>
#import "RNFirebaseNotifications.h"
#import "RNFirebaseMessaging.h"


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure];
  [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
  [RNFirebaseNotifications configure];


  //[FIRApp configure];

  [Fabric with:@[[Crashlytics class]]];

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"CymmAuth"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

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


- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
  [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
  [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings];
}

-(void) userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {

  [[RNFirebaseMessaging instance] didReceiveRemoteNotification:response.notification.request.content.userInfo];
  completionHandler();
}

@end

Do let me know if I am missing anything. firebase.notifications().onNotification() doesn't get triggered

Upvotes: 3

Views: 11450

Answers (1)

Kuldeep Dubey
Kuldeep Dubey

Reputation: 1107

After referring multiple articles from google, I managed to solve the problem. I have realized that many are facing the issue. So I am mentioning all the steps and code which I have implemented.

App Id and APNs key need to be generated from Apple's Developer Account. After generating App Id and APNs key, add the generated APNs key in your Firebase Project. In the App Id where you have added Push Notification as capability configure it with developer and production service SSL Certificates.

Also, make sure the GoogleService-Info.plist file is added in your iOS project through Xcode under the project name.

In Signing & Capabilities of Xcode add Push Notifications and Background Modes > Remote notification, Background fetch, Background processing (confirm if the capabilities are reflecting in both Debug and Release).

In info.plist FIRAnalyticsDebugEnabled, FirebaseAppDelegateProxyEnabled, FirebaseScreenReportingEnabled set to No

In Xcode Scheme > Edit Scheme... check if Run modes Build Configuration is set to Debug. This will help to generate the console in Xcode when you debug the app in your device.

  1. In React App npm install --save react-native-firebase
  2. Update pods in Podfile of ios project
    pod 'Firebase/Core' pod 'Firebase/Messaging' pod 'Firebase/Crashlytics' pod 'Firebase/Analytics' pod 'RNFirebase', :path => '../node_modules/react-native-firebase/ios'
  3. cd ios > pod install

Code to get FCM token and APNs token.

const fcmToken = await firebase.messaging().getToken();
      console.log("FCM_Token", fcmToken);

      firebase.messaging().ios.registerForRemoteNotifications().then((flag) => {
          firebase.messaging().ios.getAPNSToken().then(apns => {
            console.log("Apn Token", apns);
          }).catch((e) => {

          })
        }).catch((err) => {
          console.log("message", err);
        });

AppDelegate.m

#import "AppDelegate.h"
#import <React/RCTBridge.h>    
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>    
#import <Firebase.h>    
#import "RNFirebaseNotifications.h"    
#import "RNFirebaseMessaging.h"


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure];
  [RNFirebaseNotifications configure];

  [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
  [application registerForRemoteNotifications];
  [Fabric with:@[[Crashlytics class]]];


  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge

                                                   moduleName:@"CymmAuth"

                                            initialProperties:nil];



  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];



  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

  UIViewController *rootViewController = [UIViewController new];

  rootViewController.view = rootView;

  self.window.rootViewController = rootViewController;

  [self.window makeKeyAndVisible];

  return YES;

}



- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge

{

#if DEBUG

  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

#else

  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

#endif

}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
  [[RNFirebaseNotifications instance] didReceiveLocalNotification:notification];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
  [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
  [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings];
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[FIRMessaging messaging].APNSToken = deviceToken;
}
@end

AppDelegate.h

#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
#import <Firebase.h>
#import <UserNotifications/UserNotifications.h>
@import UserNotifications; 
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>

@property (nonatomic, strong) UIWindow *window;

@end

This will get the notification on your Apple Device.

To test the notification, FCM token validity, and to regenerate valid FCM token from APNs token, there is an API call of Firebase. This could be an additional help to test.

  1. Send Push Notification

Endpoint: https://fcm.googleapis.com/fcm/send
Type: POST
Header: Authorization: "key:fcm_server_key"
Body: { "to": "fcm_token", "content_available": true, "mutable_content": true, "data": { "message": "Batman!", "mediaUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/FloorGoban.JPG/1024px-FloorGoban.JPG" }, "notification": { "body": "Enter your message", "sound": "default" } }

  1. Validate your FCM token

Endpoint: https://iid.googleapis.com/iid/info/your_fcm_token
Type: GET
Header: Authorization: "key:fcm_server_key"

  1. Regenerate FCM token using APNs token

Endpoint: https://iid.googleapis.com/iid/v1:batchImport
Type: POST
Header: Authorization: "key:fcm_server_key"
Body: { "application":"package Id", "sandbox":true, "apns_tokens":[ "apnstoken 1","apnstoken 2" ] }

I hope this helps. Thank you.

Upvotes: 17

Related Questions