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.63k stars 2.2k forks source link

🔥 Does RNFirebase support receiving notifications directly from APNs #3479

Closed sanjaypojo closed 4 years ago

sanjaypojo commented 4 years ago

Issue

We've been using RNFirebase v6 successfully on android for some time now. For iOS, we were using a separate library as we send push notifications directly through APNs (not using FCM). However, in order to simplify our client side code, we've been exploring if it's possible to correctly process / handle push notifications sent directly via APNs using RNFirebase on the client.

We are able to successfully build and generate the APNS token on iOS, but the library doesn't seem to process the incoming notifications. The same notifications display correctly in the background, so it's not a push token issue.

Happy to provide more details if that helps!


Project Files

Javascript

Click To Expand

#### `package.json`: ```json "dependencies": { "@lingui/core": "2.9.1", "@react-native-community/async-storage": "1.6.1", "@react-native-firebase/app": "6.4.0", "@react-native-firebase/messaging": "6.4.0", "apollo-boost": "0.4.3", "graphql": "14.4.2", "graphql-tag": "2.10.1", "immer": "3.2.0", "immutable": "4.0.0-rc.12", "intl": "1.2.5", "jwt-decode": "2.2.0", "lodash.debounce": "4.0.8", "moment": "2.24.0", "react": "16.9.0", "react-native": "0.61.5", "react-native-android-open-settings": "1.3.0", "react-native-animatable": "1.3.2", "react-native-better-clipboard": "0.5.0", "react-native-branch": "2.3.3", "react-native-config": "0.12.0", "react-native-country-picker-modal": "0.8.0", "react-native-device-info": "2.3.2", "react-native-extra-dimensions-android": "1.2.5", "react-native-idfa": "4.1.0", "react-native-keep-awake": "4.0.0", "react-native-keyboard-aware-scroll-view": "0.8.0", "react-native-linear-gradient": "^2.5.6", "react-native-modal": "11.3.1", "react-native-permissions": "1.2.0", "react-native-rate": "1.1.7", "react-native-responsive-screen": "1.2.2", "react-native-version-info": "1.0.1", "react-redux": "7.1.0", "redux": "4.0.4", "redux-logger": "3.0.6", "redux-saga": "1.1.3", "redux-thunk": "2.3.0", "reselect": "4.0.0" } ``` #### `firebase.json` for react-native-firebase v6: ```json # N/A ```

iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```ruby platform :ios, '9.0' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' target 'Rune' do # React core 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' # Autolinking for packages use_native_modules! # Manually linked packages pod "Branch-SDK", path: "../node_modules/react-native-branch/ios" end ``` #### `AppDelegate.m`: ```objc /** * Copyright (c) 2015-present, Facebook, Inc. * * 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 "RNBranch.h" // Docs recommend using but XCode complains (probably because we use use_frameworks! #import #import "ReactNativeConfig.h" #import "RNCallKeep.h" #import "RNBootSplash.h" #import @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Initialize the Branch Session (library for deep links) [RNBranch initSessionWithLaunchOptions:launchOptions isReferrable:YES]; // Initialize Firebase if ([FIRApp defaultApp] == nil) { [FIRApp configure]; } RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"Rune" 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]; // Initialize RNBootSplash self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; return YES; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG NSString *bundlerIPAddress = [ReactNativeConfig envFor:@"BUNDLER_IP_ADDRESS"]; NSString *debugBundleUrl = [NSString stringWithFormat:@"%@%@%@", @"http://", bundlerIPAddress, @":8082/index.bundle?platform=ios&dev=true"]; NSLog(@"%@", debugBundleUrl); return [NSURL URLWithString:debugBundleUrl]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } // Needed by Branch - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { if (![RNBranch.branch application:app openURL:url options:options]) { // do other deep link routing for the Facebook SDK, Pinterest SDK, etc } return YES; } // Needed by Branch - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { return [RNBranch continueUserActivity:userActivity]; } @end ```


Android

Click To Expand

#### Have you converted to AndroidX? - [ ] my application is an AndroidX application? - [ ] I am using `android/gradle.settings` `jetifier=true` for Android compatibility? - [ ] I am using the NPM package `jetifier` for react-native compatibility? #### `android/build.gradle`: ```groovy // N/A ``` #### `android/app/build.gradle`: ```groovy // N/A ``` #### `android/settings.gradle`: ```groovy // N/A ``` #### `MainApplication.java`: ```java // N/A ``` #### `AndroidManifest.xml`: ```xml ```


Environment

Click To Expand

**`react-native info` output:** ``` System: OS: macOS 10.15.3 CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz Memory: 2.52 GB / 32.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 12.7.0 - /usr/local/bin/node Yarn: 1.22.4 - ~/.yarn/bin/yarn npm: 6.14.4 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: iOS SDK: Platforms: iOS 13.4, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2 Android SDK: API Levels: 23, 25, 26, 27, 28 Build Tools: 26.0.2, 27.0.3, 28.0.2, 28.0.3 System Images: android-22 | Google APIs Intel x86 Atom, android-24 | Google APIs Intel x86 Atom, android-26 | Google APIs Intel x86 Atom_64, android-28 | Google Play Intel x86 Atom IDEs: Android Studio: 3.6 AI-192.7142.36.36.6241897 Xcode: 11.4/11E146 - /usr/bin/xcodebuild npmPackages: react: 16.9.0 => 16.9.0 react-native: 0.61.5 => 0.61.5 npmGlobalPackages: create-react-native-app: 2.0.2 react-native-cli: 2.0.1 react-native-create-library: 3.1.2 react-native-rename: 2.4.0 ``` - **Platform that you're experiencing the issue on**: - [x] iOS - [ ] Android - [ ] **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:** - `6.4.0` - **`Firebase` module(s) you're using that has the issue:** - `Messaging` - **Are you using `TypeScript`?** - `N`


mikehardy commented 4 years ago

I think you are really going to want to try the @next tag on the RNFBv6 versions so you get the benefit of a big pile of fixes that should be released as stable shortly: #3339 - users report problems similar to yours, which generated those fixes, and same users report success using the @next tag with that PR in it

sanjaypojo commented 4 years ago

@mikehardy thanks for the quick response! Awesome, I'll give the @next tag a try 😄

sanjaypojo commented 4 years ago

@mikehardy I tried the @next tag, but still face the same issue.

Ehesp commented 4 years ago

@Salakar did you try this with the pusher app?

@sanjaypojo have you followed the ios steps, specifically https://rnfirebase.io/messaging/usage/ios-setup#linking-apns-with-fcm ?

sanjaypojo commented 4 years ago

@Ehesp I've followed all steps except linking uploading the APNS auth key to FCM (since we send messages directly). I'm also only testing foreground messages. Would I still need to upload the auth key to FCM?

Ehesp commented 4 years ago

Interesting, when the device is in the foreground a direct websocket connection is used between the device and fcm rather than going via apns.

I'm not 100% sure how that works with apns... Maybe a method is missing from the delegate, I'd have to investigate.

sanjaypojo commented 4 years ago

@Ehesp ah didn't realize FCM used its own socket in the foreground on ios. I guess we need the onMessage callback to be invoked from something along the lines of this code block from the official docs:

func userNotificationCenter(_ center: UNUserNotificationCenter,
         willPresent notification: UNNotification,
         withCompletionHandler completionHandler: 
            @escaping (UNNotificationPresentationOptions) -> Void) {
    // pass to onMessage here
}
sanjaypojo commented 4 years ago

@Ehesp I just looked through the source code, and I'm guessing it doesn't work because the code seems to check for a gcm id before processing:

if (notification.request.content.userInfo[@"gcm.message_id"]) {
programmer-RN commented 4 years ago

Hi, my iOS background notification is working well, but in foreground received notification, but failed to display it. Now using react-native-push-notification to display local notification.

 PushNotification.localNotification({
      title: title,
      message: body,
      bigText: body,
    });

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

sanjaypojo commented 4 years ago

@Ehesp just wanted to follow up to see if you think this will be solved / supported in the near future?

Ehesp commented 4 years ago

I'm not sure it should be really, the Messaging module should only interact with FCM messages otherwise it would absorb everything.

That being said, you should be able to put in your own handler into the AppDelegate file which should handle APNs messages & also FCM messages.

sanjaypojo commented 4 years ago

Thanks @Ehesp, that makes sense! Wanted to see if I understood correctly -- if there are two different handlers, is it safe to assume that they will both be invoked by incoming notifications?

Ehesp commented 4 years ago

Yeah this is the overall issue we've been having on iOS, if a user puts something in their AppDelegate, iOS only calls that and not any internal library ones.

We have implemented Swizzling to get around that, so it should work!

sanjaypojo commented 4 years ago

Awesome, thanks for clarifying :)

navneet10sep commented 4 months ago

Could you please confirm whether support for receiving notifications directly from APNs will continue? Adding gcm.message_id in the payload has worked for me, but I'm concerned about future changes that might affect this setup. A simple yes or no will greatly assist in my project planning. I need an official answer on this. @Invertase

mikehardy commented 4 months ago

I cannot confirm anything, we are a layer at least over this functionality, it sounds like you want to contact support in firebase-ios-sdk