React-native-firebase: 馃敟 Messaging -> sendMessage() doesn't work

Created on 22 Jun 2020  路  21Comments  路  Source: invertase/react-native-firebase

Issue

sendMessage doesnt work nor it reports any error with onSendError()

Only my real senderId in the example bellow is replaced.

try {
    await messaging().sendMessage({
        to: '[email protected]',
        messageId: 'test1',
        messageType: 'test2',
        notification: {
            title: 'Foo',
            body: 'Bar',
        }
    });

    console.warn('Message sent');
} catch(e) {
    console.warn(e);
}

It doesn't throw any error, onSendError() listener is not called.

Actually onMessageSent() listener is not called either.


Project Files

Javascript

Click To Expand

#### `package.json`:

{
  "name": "TestReactNative",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "ios-device": "react-native run-ios --device \"Dusan鈥檚 iPhone\"",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
  },
  "dependencies": {
    "@react-native-community/async-storage": "^1.11.0",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-native-firebase/analytics": "^7.1.4",
    "@react-native-firebase/app": "^7.2.1",
    "@react-native-firebase/messaging": "^7.1.6",
    "@react-navigation/bottom-tabs": "^5.5.2",
    "@react-navigation/drawer": "^5.8.2",
    "@react-navigation/material-bottom-tabs": "^5.2.10",
    "@react-navigation/material-top-tabs": "^5.2.10",
    "@react-navigation/native": "^5.5.1",
    "@react-navigation/stack": "^5.5.1",
    "react": "16.11.0",
    "react-native": "0.62.2",
    "react-native-gesture-handler": "^1.6.1",
    "react-native-paper": "^3.10.1",
    "react-native-reanimated": "^1.9.0",
    "react-native-safe-area-context": "^3.0.5",
    "react-native-screens": "^2.8.0",
    "react-native-size-matters": "^0.3.0",
    "react-native-tab-view": "^2.14.4",
    "react-native-vector-icons": "^6.6.0"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/runtime": "^7.6.2",
    "@react-native-community/eslint-config": "^1.0.0",
    "@types/jest": "^24.0.24",
    "@types/react-native": "^0.62.0",
    "@types/react-native-vector-icons": "^6.4.5",
    "@types/react-test-renderer": "16.9.2",
    "@typescript-eslint/eslint-plugin": "^2.27.0",
    "@typescript-eslint/parser": "^2.27.0",
    "babel-jest": "^24.9.0",
    "eslint": "^6.5.1",
    "jest": "^24.9.0",
    "metro-react-native-babel-preset": "^0.58.0",
    "prettier": "^2.0.4",
    "react-test-renderer": "16.11.0",
    "typescript": "^3.8.3"
  },
  "jest": {
    "preset": "react-native",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json",
      "node"
    ]
  }
}
#### `firebase.json` for react-native-firebase v6: I dont have firebase.json

### iOS
Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like:

platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

def add_flipper_pods!(versions = {})
  versions['Flipper'] ||= '~> 0.33.1'
  versions['DoubleConversion'] ||= '1.1.7'
  versions['Flipper-Folly'] ||= '~> 2.1'
  versions['Flipper-Glog'] ||= '0.3.6'
  versions['Flipper-PeerTalk'] ||= '~> 0.0.4'
  versions['Flipper-RSocket'] ||= '~> 1.0'

  pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug'

  # List all transitive dependencies for FlipperKit pods
  # to avoid them being linked in Release builds
  pod 'Flipper', versions['Flipper'], :configuration => 'Debug'
  pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug'
  pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug'
  pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug'
  pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug'
  pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug'
  pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug'
  pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug'
end

# Post Install processing for Flipper
def flipper_post_install(installer)
  installer.pods_project.targets.each do |target|
    if target.name == 'YogaKit'
      target.build_configurations.each do |config|
        config.build_settings['SWIFT_VERSION'] = '4.1'
      end
    end
  end
end

target 'TestReactNative' do
  # Pods for TestReactNative
  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/callinvoker', :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', :modular_headers => true

  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'

  target 'TestReactNativeTests' do
    inherit! :complete
    # Pods for testing
  end

  use_native_modules!

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable these next few lines.
  add_flipper_pods!
  post_install do |installer|
    flipper_post_install(installer)
  end
end

target 'TestReactNative-tvOS' do
  # Pods for TestReactNative-tvOS

  target 'TestReactNative-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end
end
#### `AppDelegate.m`:
#import "AppDelegate.h"

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

#import <Firebase.h>

#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

  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"TestReactNative"
                                            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
}

@end


Android

Click To Expand

#### Have you converted to AndroidX? I am using the newest react-native 0.62.2 - [ ] 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`:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 16
        compileSdkVersion = 28
        targetSdkVersion = 28
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:3.5.2")
        classpath 'com.google.gms:google-services:4.2.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url("$rootDir/../node_modules/react-native/android")
        }
        maven {
            // Android JSC is installed from npm
            url("$rootDir/../node_modules/jsc-android/dist")
        }

        google()
        jcenter()
        maven { url 'https://www.jitpack.io' }
    }
}

#### `android/app/build.gradle`:
apply plugin: "com.android.application"

import com.android.build.OutputFile

/**
 * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
 * and bundleReleaseJsAndAssets).
 * These basically call `react-native bundle` with the correct arguments during the Android build
 * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
 * bundle directly from the development server. Below you can see all the possible configurations
 * and their defaults. If you decide to add a configuration block, make sure to add it before the
 * `apply from: "../../node_modules/react-native/react.gradle"` line.
 *
 * project.ext.react = [
 *   // the name of the generated asset file containing your JS bundle
 *   bundleAssetName: "index.android.bundle",
 *
 *   // the entry file for bundle generation. If none specified and
 *   // "index.android.js" exists, it will be used. Otherwise "index.js" is
 *   // default. Can be overridden with ENTRY_FILE environment variable.
 *   entryFile: "index.android.js",
 *
 *   // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format
 *   bundleCommand: "ram-bundle",
 *
 *   // whether to bundle JS and assets in debug mode
 *   bundleInDebug: false,
 *
 *   // whether to bundle JS and assets in release mode
 *   bundleInRelease: true,
 *
 *   // whether to bundle JS and assets in another build variant (if configured).
 *   // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
 *   // The configuration property can be in the following formats
 *   //         'bundleIn${productFlavor}${buildType}'
 *   //         'bundleIn${buildType}'
 *   // bundleInFreeDebug: true,
 *   // bundleInPaidRelease: true,
 *   // bundleInBeta: true,
 *
 *   // whether to disable dev mode in custom build variants (by default only disabled in release)
 *   // for example: to disable dev mode in the staging build type (if configured)
 *   devDisabledInStaging: true,
 *   // The configuration property can be in the following formats
 *   //         'devDisabledIn${productFlavor}${buildType}'
 *   //         'devDisabledIn${buildType}'
 *
 *   // the root of your project, i.e. where "package.json" lives
 *   root: "../../",
 *
 *   // where to put the JS bundle asset in debug mode
 *   jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
 *
 *   // where to put the JS bundle asset in release mode
 *   jsBundleDirRelease: "$buildDir/intermediates/assets/release",
 *
 *   // where to put drawable resources / React Native assets, e.g. the ones you use via
 *   // require('./image.png')), in debug mode
 *   resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
 *
 *   // where to put drawable resources / React Native assets, e.g. the ones you use via
 *   // require('./image.png')), in release mode
 *   resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
 *
 *   // by default the gradle tasks are skipped if none of the JS files or assets change; this means
 *   // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
 *   // date; if you have any other folders that you want to ignore for performance reasons (gradle
 *   // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
 *   // for example, you might want to remove it from here.
 *   inputExcludes: ["android/**", "ios/**"],
 *
 *   // override which node gets called and with what additional arguments
 *   nodeExecutableAndArgs: ["node"],
 *
 *   // supply additional arguments to the packager
 *   extraPackagerArgs: []
 * ]
 */

project.ext.react = [
    enableHermes: false,  // clean and rebuild if changing
]

apply from: "../../node_modules/react-native/react.gradle"

/**
 * Set this to true to create two separate APKs instead of one:
 *   - An APK that only works on ARM devices
 *   - An APK that only works on x86 devices
 * The advantage is the size of the APK is reduced by about 4MB.
 * Upload all the APKs to the Play Store and people will download
 * the correct one based on the CPU architecture of their device.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = false

/**
 * The preferred build flavor of JavaScriptCore.
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US.  Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'

/**
 * Whether to enable the Hermes VM.
 *
 * This should be set on project.ext.react and mirrored here.  If it is not set
 * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
 * and the benefits of using Hermes will therefore be sharply reduced.
 */
def enableHermes = project.ext.react.get("enableHermes", false);

android {
    compileSdkVersion rootProject.ext.compileSdkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        applicationId "com.testreactnative"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://facebook.github.io/react-native/docs/signed-apk-android.
            signingConfig signingConfigs.debug
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }

    packagingOptions {
        pickFirst "lib/armeabi-v7a/libc++_shared.so"
        pickFirst "lib/arm64-v8a/libc++_shared.so"
        pickFirst "lib/x86/libc++_shared.so"
        pickFirst "lib/x86_64/libc++_shared.so"
    }

    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // https://developer.android.com/studio/build/configure-apk-splits.html
            def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }

        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    //noinspection GradleDynamicVersion
    implementation "com.facebook.react:react-native:+"  // From node_modules

    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"

    debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
      exclude group:'com.facebook.fbjni'
    }

    debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
        exclude group:'com.facebook.flipper'
    }

    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
        exclude group:'com.facebook.flipper'
    }

    if (enableHermes) {
        def hermesPath = "../../node_modules/hermes-engine/android/";
        debugImplementation files(hermesPath + "hermes-debug.aar")
        releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
        implementation jscFlavor
    }
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply plugin: 'com.google.gms.google-services'
#### `android/settings.gradle`:
rootProject.name = 'TestReactNative'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
#### `MainApplication.java`:
package com.testreactnative;

import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost =
      new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          // Packages that cannot be autolinked yet can be added manually here, for example:
          // packages.add(new MyReactNativePackage());
          return packages;
        }

        @Override
        protected String getJSMainModuleName() {
          return "index";
        }
      };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  }

  /**
   * Loads Flipper in React Native templates. Call this in the onCreate method with something like
   * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
   *
   * @param context
   * @param reactInstanceManager
   */
  private static void initializeFlipper(
      Context context, ReactInstanceManager reactInstanceManager) {
    if (BuildConfig.DEBUG) {
      try {
        /*
         We use reflection here to pick up the class that initializes Flipper,
        since Flipper library is not available in release mode
        */
        Class<?> aClass = Class.forName("com.testreactnative.ReactNativeFlipper");
        aClass
            .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
            .invoke(null, context, reactInstanceManager);
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      } catch (NoSuchMethodException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      }
    }
  }
}

#### `AndroidManifest.xml`:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.testreactnative">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
        android:launchMode="singleTask"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>

</manifest>


Environment

Click To Expand

**`react-native info` output:**

System:
    OS: macOS 10.15.4
    CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
    Memory: 211.88 MB / 16.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 12.16.0 - /usr/local/bin/node
    Yarn: Not Found
    npm: 6.13.4 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.9.3 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 13.5, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK:
      API Levels: 28, 29
      Build Tools: 28.0.3, 29.0.1
      System Images: android-28 | Wear OS Intel x86 Atom, android-28 | Intel x86 Atom_64, android-28 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: 3.4 AI-183.6156.11.34.5692245
    Xcode: 11.5/11E608c - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_222 - /usr/bin/javac
    Python: 2.7.16 - /usr/bin/python
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.11.0 => 16.11.0 
    react-native: 0.62.2 => 0.62.2 
  npmGlobalPackages:
    *react-native*: Not Found
- **Platform that you're experiencing the issue on**: - [ ] iOS - [ ] Android - [ ] **iOS** but have not tested behavior on Android - [ ] **Android** but have not tested behavior on iOS - [x ] Both - **`react-native-firebase` version you're using that has this issue:** - @react-native-firebase/[email protected] - **`Firebase` module(s) you're using that has the issue:** - @react-native-firebase/[email protected] - **Are you using `TypeScript`?** - `Y` & `3.9.5`




Needs Triage Bug Messaging >= 6

All 21 comments

Hmm - does not appear to have test cover for these actual cases unfortunately https://github.com/invertase/react-native-firebase/blob/master/packages/messaging/e2e/remoteMessage.e2e.js

Might be a problem - this functionality has been out for a while with no reports which gives me the thought this is either a failure to use the APIs correctly (happens sometimes!) and everything works (which means triple-check everything), or it's totally broken but no one uses it (which means this will be more of a self-support situation where you may need to propose a PR that corrects the behavior to suit

No idea which way that decision tree will go

I can say as a workaround you can implement a cloud function to send messages in response to user activity, when my devices are sending messages it's actually via a cloud function they call

Thank you on the answer @mikehardy

So I am calling sendMessage with correct arguments as far as you can tell? I just replaced my senderId in "to".

It's a shame none of the test cases give an example that results in success, with correct data entered. That would help a lot cause guides don't cover this use case at all.

Sending messages from Firebase console works correctly on both platforms, so I guess that means I configured everything correctly. And at least one of the onSendError / onMessageSent should be called and they are not.

Thank you for suggesting using Cloud Functions, I will try that.

It does seem that either onSendError or onMessageSent should fire, your reasoning is solid there. I have no experience in this area (I use the cloud function style to intermediate...) so I can't tell you about your arguments but I will assume you have done your homework.

It is possible this area of the code simply isn't functioning.

One thing I can say is that it is incredibly easy to go into the java files directly in node_modules/@react-native-firebase/messaging and hack in some 'System.err.println("ReactNativeJS", "any message you want in double quotes"); and by using the 'ReactNativeJS' tag I think it will show up nicely in your react-native bundler console. You can instrument the APIs all the way down to the native level pretty quickly that way (start with the javascript files to get the API names of course) and many times the error (and a fix PR) is trivial. I don't mean to be condescending but just in case you've never done native java development, strings are always double quotes and concatenation is the same + sign as javascript

Shouldn't take more than 10 minutes or so to have everything printing out so you can at least follow down to the native Firebase SDKs and see if we're both crazy or if it is just non-functional

I would like to contribute to this project at some point, and thanx for the instructions how to do that, sounds easy enough :-) But I am still learning Firebase, going over all services and learning them / trying them all.

I was just surprised I cant make messaging().sendMessage() to work, its definitely core functionality. Now I am learning Cloud Functions so I will try that suggestion you gave.

I only worry that then I will spend both Function and Messaging quotas. If sendMessage() was working properly I would only spent that quota.

cc @dackers86 @russellwheatley - could either of you try this out and see if there's any obvious issues that can be fixed? Thanks

@mi5ha @mikehardy

I have attempted to replicate this, neither the Android or IOS firebase SDKs throw an error when this type of data has been provided. This seems a difficult one to test, the following have been my efforts to reproduce the issue https://github.com/invertase/react-native-firebase/pull/3832

To clarify this is using the following example...

https://rnfirebase.io/reference/messaging/remotemessage#data

Interesting, upstream messaging seems to be a completely different thing than typical FCM using Google's infrastructure. It requires a server implemented by you @mi5ha for your project, that implements the XMPP protocol https://firebase.google.com/docs/cloud-messaging/server#choose / https://firebase.google.com/docs/cloud-messaging/server#implementing-the-xmpp-server-protocol

The protocol XMPP option is both described as "legacy" as well as "required for device to server messaging", so that doesn't seem like a good basis for investment but if you need to do it, can you confirm @mi5ha that you have implemented the XMPP protocol and configured messaging to connect to it? You should have server-side logs from the client if that's the case

If that's not the case, then I think maybe the sendMessage API could see if the RemoteMessage has the correct XMPP items in it + that it wasn't configured for default FCM server (which does not implement XMPP) and the error should be triggered if it looks like there's no way it will work

https://firebase.google.com/docs/cloud-messaging/xmpp-server-ref#upstream

@mi5ha your message would fail simple validation like this because it does not have the required parameters, and I am guessing but I think you may not have been aware of the whole XMPP requirement etc

This may be a documentation issue more than anything, and I'm guessing cloud functions are the way to go in practice.

@mi5ha your message would fail simple validation like this because it does not have the required parameters, and I am guessing but I think you may not have been aware of the whole XMPP requirement etc

You are guessing correctly 馃榾 I am not aware of, or implemented anything else besides called sendMessage() from react native code. Actually I was wondering of security implications of mobile client being able to send messages to all users of the app and how would you limit that to just particular users.

So sendMessage() should not exist in the client SDK? Just in server SDK?

This may be a documentation issue more than anything, and I'm guessing cloud functions are the way to go in practice.

Yes, I just followed what is written in react-native-firebase API docs for sendMessage(). No mention there of any additional configuration/limitation when using it .

Thanx, then I will try to use sendMessage() from Functions. Still learning functions, but I guess if I call sendMessage() from Functions, then it has nothing to do with react-native-firebase? I should check Admin SDK for that?

sendMessage should certainly exist in the SDK. It's a valid API. Just not an easy one to use.

you'll use the admin SDK in the cloud functions execution environment yes

I think this is a mix then of docs not linking people to the upstream docs with a mention that it only works with custom servers that implement XMPP, and RemoteMessage contents validation that could quickly educate exploring developers that they're missing required XMPP message contents with a quick error with a code like 'invalid-xmpp-message' and a message like 'sendMessage requires use of a custom server implementing XMPP protocol messages'. If I ever saw that I would know pretty quickly I had entered an unknown land :-)

If I ever saw that I would know pretty quickly I had entered an unknown land :-)

Exactly 馃榾 if I saw that, I would know what to investigate further. Now it doesn't report neither success nor failure. And/or say it in API docs.

Thank you very much for clearing this up, I am sure it will be useful for any Firebase beginner trying to use sendMessage.

@mikehardy Would this suggest we are missing something in the documentation (or that this function should not be considered) as part of the library?

@mikehardy Would this suggest we are missing something in the documentation (or that this function should not be considered) as part of the library?

@dackers86 yes exactly that

Proposed docs change to mention that it only works with custom servers that implement XMPP

Proposed code change RemoteMessage contents validation when passed to sendMessage that could quickly educate exploring developers that they're missing required XMPP message contents (required properties in link above) with a quick error with a code like 'invalid-xmpp-message' and a message like 'sendMessage requires a custom server implementing XMPP, and valid XMPP protocol messages'

(I'm still playing catchup on work project stuff after the dynamic links PR I posted or I'd do it myself right now but actually doing a PR to handle error cases correctly is both easy and time-consuming so it's back-burner for me to do this, feel free if you like ;-) )

Thanks @mikehardy.

I've been running through scenarios and familiarising myself with the code, there seems to be something that isn't working as expected - but i'm not sure what yet...

Setup
RNF tests running only on messaging and remoteMessaging.
A custom server running for requests using node-xcs

Scenario 1
Test: Using our test api through the e2e tests calling the sendToDevice endpoint.
Result: Successfully intercepts the message, xcs server fails to receive the request.

Scenario 2
Test: Using sendRequest via Messaging Api
Result: Fails to intercept the message, xcs server successfully receives the request.

Example server running as...

async function operation() {
  return new Promise((resolve, reject) => {
    console.log("Listening >>>");
    var Sender = require("node-xcs").Sender;

    var xcs = new Sender(
      "XXXXXXX",
      "XXXXXXX"
    );

    xcs.start();

    xcs.on("message", function (messageId, from, data, category) {
      console.log("received message", messageId, from, data, category);
    });

    xcs.on("receipt", function (messageId, from, data, category) {
      console.log("received receipt", arguments);
    });

    xcs.on("error", (e) => console.warn("XMPP error.", e));
  });
}

async function app() {
  await operation();
}

app();

@mikehardy @mi5ha

After further investigation this week. It appears as we mentioned earlier that these events are only fired through XMPP server.

For example, this was achieved in testing through the use firebase-admin.

In terms of the library, i'm not sure if there is a way to explain that messages have not been received as they have from the client - as with the same token - this can be easily sent and received through XMPP instance.

The best I think we can do is to update the documentation to add a explanation/warning that these are only fired by events passed from remote servers.

What are your thoughts?

@dackers86 documentation with a warning that this is a totally different area than normal messaging might be just enough yeah. I have to admit I was amazed to discover this whole XMPP world when I looked into this initially

@mikehardy Thanks for this, it is a bit confusing. Initial PR added at https://github.com/invertase/react-native-firebase/pull/3873

Hello 馃憢, to help manage issues we automatically close stale issues.
This issue has been automatically marked as stale because it has not had activity for quite some time. Has this issue been fixed, or does it still require the community's attention?

This issue will be closed in 15 days if no further activity occurs.
Thank you for your contributions.

PR documenting behavior has been merged

Was this page helpful?
0 / 5 - 0 ratings