invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.66k stars 2.21k forks source link

iOS Background Notification troubleshooting #3367

Closed aslanon closed 4 years ago

aslanon commented 4 years ago

Issue

Hello, notifications run while the app is on the foregound, but I didn't receive any messages when the app is in the background or killed.

There are a lot of documentation but I can't solve this problem. What am I doing wrong?


Project Files

Javascript

Click To Expand

#### `package.json`: ```json "dependencies": { "@react-native-community/push-notification-ios": "^1.1.0", "@react-native-firebase/app": "^6.4.0-rc4", "@react-native-firebase/messaging": "^6.4.0-rc4", "react": "16.9.0", "react-native": "0.61.5", "react-native-push-notification": "^3.1.9", } ```

iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```ruby platform :ios, '10.0' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' target 'Myapp' do # Pods for Myapp pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" pod 'React', :path => '../node_modules/react-native/' pod 'React-Core', :path => '../node_modules/react-native/' pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon" pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga' pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' pod 'react-native-orientation', :path => '../node_modules/react-native-orientation' target 'MyappTests' do inherit! :search_paths # Pods for testing end use_native_modules! end target 'Myapp-tvOS' do # Pods for Myapp-tvOS target 'Myapp-tvOSTests' do inherit! :search_paths # Pods for testing end end ``` #### `AppDelegate.m`: ```objc /** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "AppDelegate.h" #import #import #import #import #import #import #import "Orientation.h" @implementation AppDelegate // 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]; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Myapp" 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]; [FIRApp configure]; UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; return YES; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } @end ```


Environment

Click To Expand

**`react-native info` output:** ``` info Fetching system and libraries information... System: OS: macOS 10.15.1 CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz Memory: 2.36 GB / 16.00 GB Shell: 5.7.1 - /bin/zsh Binaries: Node: 12.13.0 - /usr/local/bin/node Yarn: 1.19.1 - /usr/local/bin/yarn npm: 6.12.0 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: iOS SDK: Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1 IDEs: Xcode: 11.3.1/11C504 - /usr/bin/xcodebuild npmPackages: react: 16.9.0 => 16.9.0 react-native: 0.61.5 => 0.61.5 npmGlobalPackages: react-native-cli: 2.0.1 ``` - **Platform that you're experiencing the issue on**: - [x ] iOS - [ ] Android - [ x] **iOS** but have not tested behavior on Android - [ ] **Android** but have not tested behavior on iOS - [ ] Both - **`react-native-firebase` version you're using that has this issue:** - `none // because I removed when I use to 6.4.0-rc4` - **`Firebase` module(s) you're using that has the issue:** - `e.g. Instance ID` - **Are you using `TypeScript`?** - `N`


Think react-native-firebase is great? Please consider supporting all of the project maintainers and contributors by donating via our Open Collective where all contributors can submit expenses. [Learn More]

bsonmez commented 4 years ago

@bsonmez deleted the app and reinstalled again, what could change? The token I think. You may be addressing the old token.

Hey Mike. Thank you for the fast reply!

I'm 100% sure that I am replacing the newest token every time. I can see in the logs that I receive remote messages when the app in the foreground. When it goes in the background the notification is not triggered.

mikehardy commented 4 years ago

I apologize that I can't find the link but there's a great video on troubleshooting the cloud message delivery from the main video guy in all the firebase developer videos. My best pointer is to watch (or re-watch that) and my vague/weak pointer is that between foreground and background it's possible that one is using FCM direct and one is APNS and, maybe the one using APNS isn't setting the right priority to get through and wake the app up. Or maybe APNS is throttling you. Nothing concrete unfortunately, sorry

bsonmez commented 4 years ago

I apologize that I can't find the link but there's a great video on troubleshooting the cloud message delivery from the main video guy in all the firebase developer videos. My best pointer is to watch (or re-watch that) and my vague/weak pointer is that between foreground and background it's possible that one is using FCM direct and one is APNS and, maybe the one using APNS isn't setting the right priority to get through and wake the app up. Or maybe APNS is throttling you. Nothing concrete unfortunately, sorry

It also happens in Android as well.*

What do you think I'm missing? Or Could this be a bug? I think I'm not the only one who has experienced this issue.

*Edit. Sorry while quoting the previous part of the message's gone.

mikehardy commented 4 years ago

I honestly don't know. The Invertase crew just went through all of this while integrating Notifee and it all works. But it's not easy. And on iOS it's flaky because of the aforementioned APNS throttle issues etc. It's just not an easy area.

Ehesp commented 4 years ago

@bockc Everything mentioned in the rnfirebase.io docs is possible, and we got them working whilst reworking the messaging module. iOS can run JS code in the background (totally different from how Android works), it's something we had working. What are you doing to actually check it runs code in the background? I've seen users doing console logs - this wont work.

That being said, it was very painful. If we sent too many messages we'd get blocked by the device for a few hours and everything would just stop working - how can you document that?

For example, @Salakar was testing on an old iPhone (5s maybe?) whilst I was on a iPhone 7 - everything worked on both of them, but the older iPhone also experienced more frequent blocking of messages due to system resource issues.

What we didn't understand was that even on the latest iPhone/iPad with nothing installed, it still happened. Incredibly infuriating.

@bsonmez

I think there is no stability. It was working without making any changes before. But it doesn't work since I deleted the app and installed it again. I couldn't understand the reason.

Yep, it's not fun & there is practically nothing on Apple docs/forums to help :/

mikehardy commented 4 years ago

@Ehesp thinking about, simply having a page where you document that experience - while it's fresh in your mind with as many of those anecdotes as you can remember, is tremendously valuable as an external observer like myself - even after doing this for a year! I didn't know console.log didn't work in background for instance. And the obvious subtlety on background throttling between devices, showing how minor device differences affect it even. You're right that doesn't exist anywhere and simply a bloggy chronicle of it linked into the docs would avert an unbelievable (or totally believable maybe) volume of issues comments and new issues

Salakar commented 4 years ago

@bsonmez as mentioned above; if it was working before and now it isn't without any changes made then it's most likely your device throttling the messages.

I posted a small guide above on how to see these being throttled using the Console app on your Mac. Let me know your findings.


I previously summarised all the working scenarios here: https://github.com/invertase/react-native-firebase/issues/3367#issuecomment-607368063 - and as you can see they are all working, though subject to throttling, with older devices (e.g. my 5s) getting what appears to be random throttling (with no given reason) - of which we can't do anything about 🙈

The throttling scenarios that I know of:

Ross-Gibson commented 4 years ago

I previously had this working on a device (foreground & background notifications) and then it suddenly appeared to stop working, and I could not see the granted permission in the iOS system settings - as mentioned by othrs above.

Make sure you are requesting permissions correctly. That was the issue for me. When I migrated from v5 to v6 my hasPermission check broke because now it returns a number (-1, 0, or 1) instead of a boolean to signify the permission status.

Resolved it for me. Explicitly checking for 1, rather than a boolean check fixed the issue.

yusufozcan commented 4 years ago

I solved like this. Before I was calling registerDeviceForRemoteMessages() in main a component. I moved it to index.js and now it is working.

package.json

"@react-native-firebase/app": "^6.7.1",
"@react-native-firebase/messaging": "^6.7.1",

index.js

import 'react-native-gesture-handler';
import React, { useEffect } from 'react'
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import messaging from '@react-native-firebase/messaging';

messaging().setBackgroundMessageHandler(remoteMessage => {
  console.log('Message handled in the background!', remoteMessage);
});

function HeadlessCheck({isHeadless}) {
    useEffect(
        React.useCallback(()=>{
            (async()=>{
                console.log("registration", await messaging().registerDeviceForRemoteMessages());
            })()
        })
    )

    if (isHeadless) {
      // App has been launched in the background by iOS, ignore
      return null;
    }
    return <App />;
  }
AppRegistry.registerComponent(appName, () => HeadlessCheck);
Ehesp commented 4 years ago

Can you show some code of how you request permission? If that's fixed your problems then the docs need updating.

thehappydinoa commented 4 years ago

Hey, I am having the same issue, we had it working perfectly yesterday, we made no changes to the notification code and it stopped working today. This is quite frustrating and is currently holding back the release of our app. I am not sure how to proceed without stable notifications. I am happy to provide any information that is needed and will respond to emails if I can.

Salakar commented 4 years ago

@thehappydinoa see my comment above: https://github.com/invertase/react-native-firebase/issues/3367#issuecomment-624104860

yusufozcan commented 4 years ago

I will try to explain every thing. My code was working perfect last week and today it wasn't. I spent too much effort to solve it. And finally I combined some thing I found and it worked. I don't know all is necessary or not but this way is working. Yes, it is time to explain.

First to make it together I will add the code from my previous post.

package.json

...
"@react-native-firebase/app": "^6.7.1",
"@react-native-firebase/messaging": "^6.7.1",
....

index.js

import 'react-native-gesture-handler';
import React, { useEffect } from 'react'
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import messaging from '@react-native-firebase/messaging';

messaging().setBackgroundMessageHandler(remoteMessage => {
  console.log('Message handled in the background!', remoteMessage);
});

function HeadlessCheck({isHeadless}) {
    useEffect(
        React.useCallback(()=>{
            (async()=>{
                console.log("registration", await messaging().registerDeviceForRemoteMessages());
            })()
        })
    )

    if (isHeadless) {
      // App has been launched in the background by iOS, ignore
      return null;
    }
    return <App />;
  }
AppRegistry.registerComponent(appName, () => HeadlessCheck);

AppDelegate.m.

...
#import <UserNotifications/UserNotifications.h>
#import <Firebase.h>
#import <FirebaseInstanceID/FirebaseInstanceID.h>
#import <FirebaseMessaging.h>
...
...
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 

//I ADDED BELOW CODE

  // Use Firebase library to configure APIs
  [FIRApp configure];
  if ([UNUserNotificationCenter class] != nil) {
   // iOS 10 or later
   // For iOS 10 display notification (sent via APNS)
   [UNUserNotificationCenter currentNotificationCenter].delegate = self;
   UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
   UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
   [[UNUserNotificationCenter currentNotificationCenter]
   requestAuthorizationWithOptions:authOptions
   completionHandler:^(BOOL granted, NSError * _Nullable error) {
   // …
   }];
   } else {
   // iOS 10 notifications aren’t available; fall back to iOS 8–9 notifications.
   UIUserNotificationType allNotificationTypes =
   (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
   UIUserNotificationSettings *settings =
   [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
   [application registerUserNotificationSettings:settings];
   }
  [application registerForRemoteNotifications];
  [FIRMessaging messaging].delegate = self;
  [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result,
   NSError * _Nullable error) {
   if (error != nil) {
   NSLog(@"Error fetching remote instance ID: %@", error);
   } else {
   NSLog(@"Remote instance ID token: %@", result.token);
   NSString* message =
   [NSString stringWithFormat:@"Remote InstanceID token: %@", result.token];
   }
   }];
  [FIRMessaging messaging].autoInitEnabled = YES;

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

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
 NSLog(@"FCM registration token: %@", fcmToken);
 // Notify about received token.
 NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
 [[NSNotificationCenter defaultCenter] postNotificationName:
 @"FCMToken" object:nil userInfo:dataDict];

 // TODO: If necessary send token to application server.
 // Note: This callback is fired at each app startup and whenever a new token is generated.
}
// With “FirebaseAppDelegateProxyEnabled”: NO
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
   [FIRMessaging messaging].APNSToken = deviceToken;
}

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

//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
@end

App.tsx

export default function App() {
  useEffect(() => {
    // Assume a message-notification contains a "type" property in the data payload of the screen to open
    messaging().onMessage(async remoteMessage => {
      console.log("Message received when application in show",remoteMessage)
    });

    messaging().onNotificationOpenedApp(remoteMessage => {
      console.log(
        'Notification caused app to open from background state:',
        remoteMessage.notification,
      );
    });

    // Check whether an initial notification is available
    messaging()
      .getInitialNotification()
      .then(remoteMessage => {
        if (remoteMessage) {
          console.log(
            'Notification caused app to open from quit state:',
            remoteMessage.notification,
          );
        }
      });
  }, []);

  return (
    <React.Fragment>
      <StatusBar backgroundColor="#F0F5F9" barStyle='dark-content' />

      <Navigation />
    </React.Fragment>
  );
}

And the last, In one component, for me it is Home.tsx and it is a functional component. In Class component I guess you can use componentDidMount fucntion instead of useEffect function

export function Home(){
/*
State definitions here.
*/
.....

    const getFCMToken = async () => {
        try {
            const authorized = await messaging().hasPermission();
            const fcmToken = await getToken();

            if (authorized) return fcmToken;

            await messaging().requestPermission();
            return fcmToken;
        } catch (error) {
            console.log(error);
        }
    };

    const registerAppWithFCM = async () => {
        let fcmToken: any = await Services.getData('fcmToken')    //READING FROM ASYNC STORAGE
        if (fcmToken.result === undefined) {
            console.log("registration", await messaging().registerDeviceForRemoteMessages());
        }
    }

    const getToken = async () => {
        try {
            const token = await messaging().getToken();
            console.warn("taken token", token)

            if (token) return token;
        } catch (error) {
            console.log(error);
        }
    };

 useEffect(
        React.useCallback(()=>{
            (async()=>{
                     let fcmToken = await getFCMToken()
                     await Services.storeData("fcmToken", fcmToken) //WRITING TO ASYNC STORAGE

                     // HERE, I AM SENDING TO BACKEND SERVICE TO MATCH WITH DEVICE ID AND TOKEN IN MY DATABASE.

            })()

            registerAppWithFCM()
        })
    )
}

In Home.tsx I am asking for permission directly. If you want, you can call getFCMToken()funtion in an event e.g. onPress() of Button.

I wish it is helpful. As I said I am not sure all above is necessary but It is working.

thehappydinoa commented 4 years ago

@yusufozcan I tried using that code exactly and it did not work. Do you have any other suggestions?

@Salakar I tried that and received logs, but nothing related to notifications, besides granting them permissions. What would next steps look like?

thehappydinoa commented 4 years ago

I was able to get background and foreground notifications working using the following code in my AppDelegate.m:

#import <UserNotifications/UserNotifications.h>
#import <Firebase.h>
#import <FirebaseInstanceID/FirebaseInstanceID.h>
#import <FirebaseMessaging.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }

if ([UNUserNotificationCenter class] != nil) {
    // iOS 10 or later
    // For iOS 10 display notification (sent via APNS)
    [UNUserNotificationCenter currentNotificationCenter].delegate = self;
    UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
    UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
    [[UNUserNotificationCenter currentNotificationCenter]
    requestAuthorizationWithOptions:authOptions
    completionHandler:^(BOOL granted, NSError * _Nullable error) {
    // …
    }];
   } else {
    // iOS 10 notifications aren’t available; fall back to iOS 8–9 notifications.
    UIUserNotificationType allNotificationTypes =
    (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
    UIUserNotificationSettings *settings =
    [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
    [application registerUserNotificationSettings:settings];
   }
  [application registerForRemoteNotifications];
  [FIRMessaging messaging].delegate = self;
  [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result,
    NSError * _Nullable error) {
      if (error != nil) {
        NSLog(@"Error fetching remote instance ID: %@", error);
      } else {
        NSLog(@"Remote instance ID token: %@", result.token);
        NSString* message = [NSString stringWithFormat:@"Remote InstanceID token: %@", result.token];
      }
    }
  ];
  [FIRMessaging messaging].autoInitEnabled = YES;

...
}

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
  NSLog(@"FCM registration token: %@", fcmToken);
  NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
  [[NSNotificationCenter defaultCenter] postNotificationName: @"FCMToken" object:nil userInfo:dataDict];
}

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

I also removed FirebaseAppDelegateProxyEnabled: YES from my Info.plist

bsonmez commented 4 years ago

@yusufozcan Thank you! It worked by changing only AppDelegate.m as you mentioned.

Ehesp commented 4 years ago

That's super weird if that's working for you, that's what the messaging module should be doing.

Ehesp commented 4 years ago

I'd be careful just pasting native code into your own delegates, that looks like it's been copied and pasted from somewhere different and may cause other issues.

We'd like to get things working without you needing to do that, because it shouldn't be needed.

Ehesp commented 4 years ago

@thehappydinoa @bsonmez @yusufozcan Would any of you be able to share the full project with us? There must be something else iOS specific causing it not to work for you which we could look for. We'd love to nail why so others dont have these issues.

Ross-Gibson commented 4 years ago

This code works for me. It's slightly edited to what was in the documentation to include an explicit check for the permission status. It's using redux-saga, but if it's helpful to you I can share a version with async / await.

import { call, take, fork } from 'redux-saga/effects';
import { eventChannel } from 'redux-saga';
import AsyncStorage from '@react-native-community/async-storage';
import messaging from '@react-native-firebase/messaging';
import { Alert } from 'react-native';

// On Android, you do not need to request user permission. This method
// can still be called on Android devices; however, and will always
// resolve successfully.
function* checkPermissions() {
  const status = yield call([messaging(), messaging().hasPermission]);

  switch (status) {
    case messaging.AuthorizationStatus.NOT_DETERMINED:
    case messaging.AuthorizationStatus.DENIED: {
      console.log('User has notification permissions disabled');
      yield call(requestPermission);
      break;
    }
    case messaging.AuthorizationStatus.AUTHORIZED: {
      console.log('User has notification permissions enabled.');
      yield call(getToken);
      break;
    }
    case messaging.AuthorizationStatus.PROVISIONAL: {
      // The app is currently authorized to post non-interrupting user notifications
      // platform ios iOS >= 12 only
      console.log('User has provisional notification permissions.');
      break;
    }
    default: {
      // TODO: Handle
      break;
    }
  }
}

function* getToken() {
  let fcmToken = yield call(
    [AsyncStorage, AsyncStorage.getItem],
    '@mxvue:fcmToken',
  );

  if (!fcmToken) {
    fcmToken = yield call([messaging(), messaging().getToken]);

    if (fcmToken) {
      // user has a device token
      yield call(
        [AsyncStorage, AsyncStorage.setItem],
        '@mxvue:fcmToken',
        fcmToken,
      );
    }
  }

  console.log('fcmToken', fcmToken);
}

// Triggers a native permission dialog requesting the user's permission
// On Android, you do not need to request user permission. This method
// can still be called on Android devices; however, and will always
// resolve successfully.
function* requestPermission() {
  const status = yield call([messaging(), messaging().requestPermission]);

  switch (status) {
    case messaging.AuthorizationStatus.NOT_DETERMINED:
    case messaging.AuthorizationStatus.DENIED: {
      console.log('User has notification permissions disabled');
      break;
    }
    case messaging.AuthorizationStatus.AUTHORIZED: {
      console.log('User has notification permissions enabled.');
      yield call(getToken);
      break;
    }
    case messaging.AuthorizationStatus.PROVISIONAL: {
      // The app is currently authorized to post non-interrupting user notifications
      // platform ios iOS >= 12 only
      console.log('User has provisional notification permissions.');
      break;
    }
    default: {
      // TODO: Handle
      break;
    }
  }
}

function createFirebaseNotificationsChannel() {
  return eventChannel(emit => {
    const unsubscribe = messaging().onMessage(async remoteMessage =>
      emit(remoteMessage),
    );
    return unsubscribe;
  });
}

function* watchForFirebaseNotifications() {
  const firebaseNotificationsChannel = yield call(
    createFirebaseNotificationsChannel,
  );

  while (true) {
    const remoteMessage = yield take(firebaseNotificationsChannel);

    // TODO: Handle messages and present on the UI
    console.log('NOTIFICATION:', remoteMessage);
    Alert.alert('A new FCM message arrived!', JSON.stringify(remoteMessage));
  }
}

function* notificationsSaga() {
  yield fork(watchForFirebaseNotifications);
  yield call(checkPermissions);
}

export default notificationsSaga;
Ross-Gibson commented 4 years ago

Also, using the above code I did not have to make any modifications to the project such as changing the AppDelegate.m - everything worked following the documentation.

tranvanquang commented 4 years ago

Can u show me a example project in git!! I'm trying use It but, dont show :(

bsonmez commented 4 years ago

@thehappydinoa @bsonmez @yusufozcan Would any of you be able to share the full project with us? There must be something else iOS specific causing it not to work for you which we could look for. We'd love to nail why so others dont have these issues.

@Ehesp Hey Elliot. I guess I'm not allowed to share the full project, but I'd like to give information on my side. I can say that everything is the same as documentation except AppDelegate.m. I updated it as @yusufozcan suggested and also there is one only extra FBSDK. The rest of the file is the same.

Another weird point was when I applied AppDelegate.m the solution, I started receiving the notifications immediately and there was no setBackgroundMessageHandler function implemented yet. However, the app was giving a yellow box warning. Then I implemented it as @yusufozcan mentioned in index.js and stopped giving the warning and started working how it suppose to work.

If you need more information, I'd like to share.

Ehesp commented 4 years ago

@Ehesp Hey Elliot. I guess I'm not allowed to share the full project, but I'd like to give information on my side. I can say that everything is the same as documentation except AppDelegate.m. I updated it as @yusufozcan suggested and also there is one only extra FBSDK. The rest of the file is the same.

We're thinking it's more of a project problem than actual code, e.g. some project setting disabled which is preventing things from working.

Is it not possible at all to share it? We'd even be fine signing an NDA or something to try and get this solved, or even screenshare. There's all sorts of settings which iOS can apply to break things (e.g. disabling Swizzling).

Another weird point was when I applied AppDelegate.m the solution, I started receiving the notifications immediately and there was no setBackgroundMessageHandler function implemented yet.

setBackgroundMessageHandler doesn't need to be in place for notification to show, or at least it shouldn't need to be.

yusufozcan commented 4 years ago

@thehappydinoa @bsonmez @yusufozcan Would any of you be able to share the full project with us? There must be something else iOS specific causing it not to work for you which we could look for. We'd love to nail why so others dont have these issues.

I already shared all the codes related with firebase notifications. I can't share all the project because it is belongs to one client of me.

sungmen999 commented 4 years ago

I tried everything in there comments, but I can't receive message from background process.

NilsBaumgartner1994 commented 4 years ago

Hi guys, I'm having also trouble with Notification. On my Simulator everything works fine, but on a real device I'm always get an error.

My Backend Server responds for real Devices.

registration-token-not-registered

Yes I am registering the device. Funny thing here:

"registerDeviceForRemoteMessages" not found But the deprecated function works ..

"@react-native-firebase/app": "^6.7.1", "@react-native-firebase/messaging": "^6.7.1",

I will follow this Issue and try the change of the AppDelegate.m

Gabsys commented 4 years ago

I've tried many kind of changes to AppDelegate.m and I still can't receive background notification (Foreground was fine). But setting FirebaseAppDelegateProxyEnabled to YES really solved the issue although I see ppl saying that shouldn't be necessary O.O

SABRYX commented 4 years ago

I still can't receive notifications in the background.

kashmiry commented 4 years ago

I've tried many kind of changes to AppDelegate.m and I still can't receive background notification (Foreground was fine). But setting FirebaseAppDelegateProxyEnabled to YES really solved the issue although I see ppl saying that shouldn't be necessary O.O

I confirm this has worked with me after adding FirebaseAppDelegateProxyEnabled with YES. why is that? and what kind of difference does it make now, when its set to True?

ccanalesb commented 4 years ago

I've tried many kind of changes to AppDelegate.m and I still can't receive background notification (Foreground was fine). But setting FirebaseAppDelegateProxyEnabled to YES really solved the issue although I see ppl saying that shouldn't be necessary O.O

I confirm this has worked with me after adding FirebaseAppDelegateProxyEnabled with YES. why is that? and what kind of difference does it make now, when its set to True?

in what part you add FirebaseAppDelegateProxyEnabled with YES.? can you show a example?

kashmiry commented 4 years ago

@ccanalesb You add it in info.plist

thehappydinoa commented 4 years ago

Okay y'all, I got it working. I did not add any FirebaseAppDelegateProxyEnabled to my Info.plist I followed Google's Guide on setting up notifictions and receiving notifictions. Here is my working AppDelegate.m (Check the "I added" comments for the important code):

#import "AppDelegate.h"

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

// We use these, but you don't have to.
#import "RNBootSplash.h"
#import <CodePush/CodePush.h>

// Start I added
#import <RNCPushNotificationIOS.h>
#import <UserNotifications/UNUserNotificationCenter.h>

@import Firebase;
// End I added

#if DEBUG
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if DEBUG
  InitializeFlipper(application);
#endif

// Start I added
  [FIRApp configure];

  if ([UNUserNotificationCenter class] != nil) {
    // iOS 10 or later
    // For iOS 10 display notification (sent via APNS)
    [UNUserNotificationCenter currentNotificationCenter].delegate = self;
    UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
        UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
    [[UNUserNotificationCenter currentNotificationCenter]
        requestAuthorizationWithOptions:authOptions
        completionHandler:^(BOOL granted, NSError * _Nullable error) {
          // ...
        }];
  } else {
    // iOS 10 notifications aren't available; fall back to iOS 8-9 notifications.
    UIUserNotificationType allNotificationTypes =
    (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
    UIUserNotificationSettings *settings =
    [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
    [application registerUserNotificationSettings:settings];
  }

  [application registerForRemoteNotifications];

  [FIRMessaging messaging].delegate = self;

  [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result,
                                                      NSError * _Nullable error) {
    if (error != nil) {
      NSLog(@"Error fetching remote instance ID: %@", error);
    } else {
      NSLog(@"Remote instance ID token: %@", result.token);
    }
  }];

  [FIRMessaging messaging].autoInitEnabled = YES;

// End I added

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"appname"
                                            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;
  [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

// Start I added

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
    NSLog(@"FCM registration token: %@", fcmToken);
    // Notify about received token.
    NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
    [[NSNotificationCenter defaultCenter] postNotificationName:
     @"FCMToken" object:nil userInfo:dataDict];
}

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

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

// 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
{
  [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
  [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];
}

// Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
  {
    NSDictionary *userInfo = notification.request.content.userInfo;
    [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
    completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
  }

// End I added

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [CodePush bundleURL];
#endif
}

@end
VasiliSolodar commented 4 years ago

For anyone still having troubles: delete pods folder and podfile.lock. After fresh install everything works fine without any changes in appDelegate.m and info.plist.

rizwanatta commented 4 years ago

Okay y'all, I got it working. I did not add any FirebaseAppDelegateProxyEnabled to my Info.plist I followed Google's Guide on setting up notifictions and receiving notifictions. Here is my working AppDelegate.m (Check the "I added" comments for the important code):

#import "AppDelegate.h"

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

// We use these, but you don't have to.
#import "RNBootSplash.h"
#import <CodePush/CodePush.h>

// Start I added
#import <RNCPushNotificationIOS.h>
#import <UserNotifications/UNUserNotificationCenter.h>

@import Firebase;
// End I added

#if DEBUG
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if DEBUG
  InitializeFlipper(application);
#endif

// Start I added
  [FIRApp configure];

  if ([UNUserNotificationCenter class] != nil) {
    // iOS 10 or later
    // For iOS 10 display notification (sent via APNS)
    [UNUserNotificationCenter currentNotificationCenter].delegate = self;
    UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
        UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
    [[UNUserNotificationCenter currentNotificationCenter]
        requestAuthorizationWithOptions:authOptions
        completionHandler:^(BOOL granted, NSError * _Nullable error) {
          // ...
        }];
  } else {
    // iOS 10 notifications aren't available; fall back to iOS 8-9 notifications.
    UIUserNotificationType allNotificationTypes =
    (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
    UIUserNotificationSettings *settings =
    [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
    [application registerUserNotificationSettings:settings];
  }

  [application registerForRemoteNotifications];

  [FIRMessaging messaging].delegate = self;

  [[FIRInstanceID instanceID] instanceIDWithHandler:^(FIRInstanceIDResult * _Nullable result,
                                                      NSError * _Nullable error) {
    if (error != nil) {
      NSLog(@"Error fetching remote instance ID: %@", error);
    } else {
      NSLog(@"Remote instance ID token: %@", result.token);
    }
  }];

  [FIRMessaging messaging].autoInitEnabled = YES;

// End I added

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"appname"
                                            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;
  [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

// Start I added

- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
    NSLog(@"FCM registration token: %@", fcmToken);
    // Notify about received token.
    NSDictionary *dataDict = [NSDictionary dictionaryWithObject:fcmToken forKey:@"token"];
    [[NSNotificationCenter defaultCenter] postNotificationName:
     @"FCMToken" object:nil userInfo:dataDict];
}

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

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

// 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
{
  [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
  [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];
}

// Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
  {
    NSDictionary *userInfo = notification.request.content.userInfo;
    [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
    completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
  }

// End I added

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [CodePush bundleURL];
#endif
}

@end

for imports of userNotification block! you used @community based notificaion ios package?

alex-mironov commented 4 years ago

Are there any breaking changes in v.7 of firebase/messaging? I was considering upgrading but didn't find any info if it's backward compatible with v.7.

My current version is

    "@react-native-firebase/app": "6.4.0-rc4",
mikehardy commented 4 years ago

@alex-mironov From that version not that I know of - the version you are on was the major thing for messaging because of #3339 (which you're probably aware of or you would not have been on an RC I think and talking about messaging), after that one the bump to v7 was not an actual user-facing breaking change, it was an internal cross-versioning thing as the monorepo transitioned from lockstep versioning to independent versioning. So you shouldn't have any problems.

alex-mironov commented 4 years ago

@mikehardy thank you. Just updated so far so good ✌︎

davidcort commented 4 years ago

Tried everything on this thread nothing works. I can still receive foreground messages but background messages don't work.

And those with edited AppDeligate.m file I didn’t see any where in the documentation with that information.

Hi, i resolved this way:

1.- yarn remove @react-native-firebase/messaging 2.- go to ios directory, comment this line in the pod file: // pod 'RNFBMessaging', :path => '../node_modules/@react-native-firebase/messaging' and do "pod install" 3.- Delete the app 4.- Shutdown the device (Apagar dispositivo en español) Sorry my english not good 5.- Turn on the device 6.- Install your app 7.- Send push notification, works for me.

yerkejs commented 4 years ago

@davidcort may you share your AppDelegate

hishamhadraoui commented 4 years ago

@davidcort the steps u described are basically removing firebase messaging from the app and deleting it from Podfile

yerkejs commented 4 years ago

@hishamhadraoui I did not understand you, do you mean that these steps works ?

hishamhadraoui commented 4 years ago

@030131550542 what I mean is that the steps that he described are basically just removing firebase messaging, I don't think that will work, to be honest. nevertheless, without these steps, it worked for me by deploying the application to Testflight, the remote notification worked for both when quitted or in the background. That didn't work in the simulator only when the app was active, but in Testflight they worked in every state. but I do believe u need to add the APNS certificate that u create in apple into ur main folder of ios

mikehardy commented 4 years ago

Testing cloud messaging in the simulator is effectively pointless. Only test cloud messaging in real devices.

AndreyPatseiko commented 4 years ago

I still can't get notifications in background mode, in foreground work normal. RN 0.62.2. It didn't help me: 1) Any manipulations with FirebaseAppDelegateProxyEnabled; 2) Clear/Reinstall all dependences/Reboot phone

I use package.json

"@react-native-firebase/app": "^7.1.0",
"@react-native-firebase/crashlytics": "^7.1.0",
"@react-native-firebase/messaging": "^7.1.0",

When run pod install

Fabric (1.10.2)
Installing Firebase (6.25.0)
Installing FirebaseAnalytics (6.5.1)
Installing FirebaseAnalyticsInterop (1.5.0)
Installing FirebaseCore (6.7.1)
Installing FirebaseCoreDiagnostics (1.3.0)
Installing FirebaseCoreDiagnosticsInterop (1.2.0)
Installing FirebaseInstallations (1.2.0)
Installing FirebaseInstanceID (4.3.4)
Installing FirebaseMessaging (4.4.1)

Only after updating AppDelegate.m from this comment, resolved my problem. Big thanks @thehappydinoa!

yerkejs commented 4 years ago

@mikehardy I uploaded .p8 into firebase console. Is it enough for handling certificate. Am I need to create .p12 (development or production) ?

rizwanatta commented 4 years ago

so here it goes, I have been through almost all of the things in the comments above

  1. info.plist update
  2. adding apn key to the root folder of project /ios
  3. updating delegate.m 4.adding support via @rn-community/push-notification-ios 5: I have apn key setup in my firebase project 6: I do use the permission and register handlers early as app loads in legacy old index.js 7: did pod disintegrations, lock file deletion, package reinstallations, device restarts, Xcode clean builds

I got only foreground notifications

I was on 7.0.1 before then shifted to 7.1.0 version of firebase packages I even upgraded RN version to 0.62.2 to try a solution provided above had no luck

NOTE! yes, I tested on a real device! asked on the invertase Discord!

But I am still a dud on this one! no solution at all is working with this package of messaging! any help?

EDIT

I uploaded the version to test flight and then sent a notification and it did come in the background too! guess its with apple APNs thingy! I hope it helps!

but still not able to have notifications in the background while testing/debugging! that is a drag

roni-castro commented 4 years ago

I don't know if it is might be the same error, but I also had the same problem and apparently it has been solved by sending the notification payload, as it seems the push notification is not being shown on the iOS when it is data only (even with "priority" : "high" and "content_available": true). I am using these libs below, and now I am able to receive push with the default lib configuration and a real device (12.4.4). On iOS emulator I don't receive them.

    "@react-native-firebase/app": "^7.1.0",
    "@react-native-firebase/messaging": "^7.1.0",
    "@notifee/react-native": "^0.5.1",

Here is what makes my iOS app starts receiving push on Background/Killed state:

POST in: https://fcm.googleapis.com/fcm/send Authorization: key=#Your Firebase project Server key for iOS Content-Type: application/json

{
   "priority" : "high",
   "content_available": true,
   "notification": {
        "body" : "notification - body",
        "title": "notification - title"
   },
    "data": {
        "body" : "Data - body",
        "title": "Data - title"
   },
    "to": "your device token"
}

With this payload I do not receive any notification on background/killed state:

{
   "priority" : "high",
   "content_available": true,
   "data": {
        "body" : "Data - body",
        "title": "Data - title"
   },
    "to": "your device token"
}
mikehardy commented 4 years ago

Without notification in the payload, the SDK will not show it, no.

Whether it is delivered and/or your app is started with data-only / no-notification depends on if you are being throttled etc (watch the Xcode logs on a real device connected to Xcode

With the notification in the payload the firebase SDK will show the notification but your app won't get a chance to process the data payload until the user clicks.

It's a complicated set of "is this is set, then this happens..." and it's not possible to recommend any given JSON FCM payload as "the solution" because someone else's requirements might be different.

Buwaneka-Sumanasekara commented 4 years ago

For anyone who struggling this matter, check this out. For me its worked https://github.com/invertase/react-native-firebase/issues/3699#issuecomment-638110794