React-native-firebase: :fire: getInitialNotification crashed in production - Android

Created on 14 Apr 2020  路  19Comments  路  Source: invertase/react-native-firebase


Issue



Hello react-native-firebase team,

I observed the following crash in production:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Intent android.app.Activity.getIntent()' on a null object reference
       at io.invertase.firebase.messaging.ReactNativeFirebaseMessagingModule.getInitialNotification(ReactNativeFirebaseMessagingModule.java:58)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:372)
       at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:151)
       at com.facebook.react.bridge.queue.NativeRunnable.run(NativeRunnable.java)
       at android.os.Handler.handleCallback(Handler.java:761)
       at android.os.Handler.dispatchMessage(Handler.java:98)
       at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:27)
       at android.os.Looper.loop(Looper.java:156)
       at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:226)
       at java.lang.Thread.run(Thread.java:776)

The log is from crashlytics, I've not been able to reproduce it locally yet. What else can I help with to debugging this issue further? I've filled in the form below with as much information I could.

Thanks


Project Files






Javascript

Click To Expand

#### `package.json`:

{
  "name": "myapp",
  "version": "0.1.0",
  "private": true,
  "engines": {
    "node": "^10.16.0",
    "npm": "^6.11.3"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/runtime": "^7.6.2",
    "@react-native-community/eslint-config": "^0.0.5",
    "babel-jest": "^24.9.0",
    "babel-plugin-transform-remove-console": "^6.9.4",
    "eslint": "^6.5.1",
    "jest": "^24.9.0",
    "metro-react-native-babel-preset": "0.58.0",
    "react-test-renderer": "16.11.0"
  },
  "scripts": {
    "start": "react-native start",
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "test": "node node_modules/jest/bin/jest.js",
    "eslint": "eslint src/",
    "lint": "eslint ."
  },
  "jest": {
    "preset": "react-native"
  },
  "dependencies": {
    "@notifee/react-native": "^0.4.0",
    "@react-native-community/datetimepicker": "^2.3.0",
    "@react-native-community/netinfo": "^5.6.2",
    "@react-native-firebase/analytics": "^6.4.0",
    "@react-native-firebase/app": "^6.4.0",
    "@react-native-firebase/auth": "^6.4.0",
    "@react-native-firebase/crashlytics": "^6.4.0",
    "@react-native-firebase/database": "^6.4.0",
    "@react-native-firebase/dynamic-links": "^6.4.0",
    "@react-native-firebase/firestore": "^6.4.0",
    "@react-native-firebase/functions": "^6.4.0",
    "@react-native-firebase/messaging": "^6.4.0",
    "@react-native-firebase/perf": "^6.4.0",
    "@react-native-firebase/remote-config": "^6.4.0",
    "@react-native-firebase/storage": "^6.4.0",
    "moment": "^2.22.2",
    "moment-timezone": "^0.5.28",
    "prop-types": "^15.7.2",
    "react": "16.11.0",
    "react-native": "0.62.2",
    "react-native-camera": "^3.21.0",
    "react-native-dialog": "^5.6.0",
    "react-native-easy-markdown": "^1.5.0",
    "react-native-elements": "^1.2.6",
    "react-native-gesture-handler": "^1.4.1",
    "react-native-gifted-chat": "^0.13.0",
    "react-native-home-indicator": "^0.2.5",
    "react-native-image-picker": "^1.1.0",
    "react-native-immersive-mode": "^1.1.0",
    "react-native-linkedin": "^1.3.1",
    "react-native-modal": "^11.5.6",
    "react-native-modal-datetime-picker": "^8.5.1",
    "react-native-orientation-locker": "^1.1.8",
    "react-native-permissions": "2.0.0-rc.0",
    "react-native-static-safe-area-insets": "^2.0.0",
    "react-native-svg": "9.6.4",
    "react-native-vector-icons": "6.6.0",
    "react-native-video": "^5.0.2",
    "react-navigation": "^3.13.0",
    "react-navigation-hooks": "^1.1.0",
    "react-navigation-stack": "^1.10.3",
    "react-redux": "^7.1.1",
    "redux": "^4.0.5",
    "redux-thunk": "^2.3.0",
    "reselect": "^4.0.0",
    "urijs": "^1.19.2"
  }
}
#### `firebase.json` for react-native-firebase v6:
# N/A
--- ### iOS
Click To Expand

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

# N/A
#### `AppDelegate.m`:
// N/A


Android

Click To Expand

#### Have you converted to AndroidX? - [x] my application is an AndroidX application? - [x] 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`:

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 21
        compileSdkVersion = 28
        targetSdkVersion = 28
    }
    repositories {
        google()
        jcenter()
        maven {
            url 'https://maven.fabric.io/public'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.3'
        classpath 'com.google.gms:google-services:4.3.3'
        classpath 'io.fabric.tools:gradle:1.25.4'
        classpath 'com.google.firebase:perf-plugin:1.3.1'

        // 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"
apply plugin: "io.fabric"
apply plugin: "com.google.firebase.firebase-perf"

import com.android.build.OutputFile

task switchToDebug(type: Copy) {
    description = 'Switches to DEBUG google-services.json'
    from "src/debug"
    include "google-services.json"
    into "."
}

task switchToRelease(type: Copy) {
    description = 'Switches to RELEASE google-services.json'
    from "src/release"
    include "google-services.json"
    into "."
}

project.ext.react = [
    entryFile: "index.js",
    enableHermes: true,  // clean and rebuild if changing
]

apply from: "../../node_modules/react-native/react.gradle"
def enableSeparateBuildPerCPUArchitecture = false
def enableProguardInReleaseBuilds = false
def jscFlavor = 'org.webkit:android-jsc:+'
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.myapp"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        multiDexEnabled true
        versionCode 78
        versionName "1.4.8"
        missingDimensionStrategy 'react-native-camera', 'mlkit'
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    buildTypes {
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            signingConfig signingConfigs.release
        }
    }

    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
            }
        }
    }
}

crashlytics {
  enableNdk true
}

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

    implementation "androidx.appcompat:appcompat:1.0.0"
    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'
    }

    implementation "androidx.multidex:multidex:2.0.1"
}

// 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'
}

afterEvaluate {
    processDebugGoogleServices.dependsOn switchToDebug
    processReleaseGoogleServices.dependsOn switchToRelease
}

project.ext.vectoricons = [
    iconFontNames: [ 'MaterialIcons.ttf', 'MaterialCommunityIcons.ttf' ]
]

apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
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 = 'myapp'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

include ':app'
#### `MainApplication.java`:
import android.app.Application;
import android.content.Context;
import androidx.multidex.MultiDexApplication;

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 MultiDexApplication 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();
      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.myapp.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.myapp">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize"
        android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
          <intent-filter>
              <action android:name="android.intent.action.VIEW"/>
              <category android:name="android.intent.category.DEFAULT"/>
              <category android:name="android.intent.category.BROWSABLE"/>
              <data android:host="..." android:scheme="http"/>
              <data android:host="..." android:scheme="https"/>
              <data android:host="..." android:scheme="http"/>
              <data android:host="..." android:scheme="https"/>
          </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
      <meta-data
          android:name="com.google.firebase.ml.vision.DEPENDENCIES"
          android:value="ocr" />
    </application>

</manifest>


Environment

Click To Expand

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

System:
    OS: macOS Mojave 10.14.6
    CPU: (4) x64 Intel(R) Core(TM) i7-4558U CPU @ 2.80GHz
    Memory: 649.67 MB / 16.00 GB
    Shell: 3.2.57 - /bin/bash
  Binaries:
    Node: 10.19.0 - /usr/local/bin/node
    Yarn: 1.19.0 - /usr/local/bin/yarn
    npm: 6.13.4 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.7.5 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
    Android SDK:
      API Levels: 23, 25, 26, 27, 28, 29
      Build Tools: 23.0.1, 25.0.2, 26.0.2, 27.0.1, 27.0.3, 28.0.1, 28.0.2, 28.0.3, 29.0.0, 29.0.1
      System Images: android-23 | Google APIs Intel x86 Atom, android-26 | Google Play Intel x86 Atom, android-27 | Google Play Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-29 | Google Play Intel x86 Atom
      Android NDK: Not Found
  IDEs:
    Android Studio: 3.1 AI-173.4819257
    Xcode: 11.3.1/11C505 - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_91 - /usr/bin/javac
    Python: 2.7.16 - /usr/local/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 - [x] 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`



Messaging Stale >= 6

Most helpful comment

Hello, I'm facing this problem too.
I'm listening for messaging().getInitialNotification() from within a componentDidMount, but Firebase is throwing the same error:

image

@Ehesp can you tell us if your safe check is already available in any of these newer versions?

- 6.0.0-alpha.25
- 6.7.1
- 6.4.0-rc4
- 6.4.1-alpha.0

All 19 comments

Huh, normally I'd say it's because you have integrated something else as your launch activity and it ate the intent (this is common with splash screen integrations) but it doesn't seem that way from AndroidManifest

You elided your package.json so that's inconclusive

Can you try using the @next tag for your firebase dependencies to get the current code which includes a mountain of messaging/notification bugfixes past 6.4.0?

I've updated the post with the full package.json content.

I'll see if I can reproduce this in a testing environment / emulator, then I can see if version @next will solve it. Do you have any more information what changes are included?

And to add a bit more context, the place where it fails in my code is in a React.Component constructor. In that constructor I call

auth().onAuthStateChanged(async (user) => {
  // ...
  try {
    const initialNotification = await messaging().getInitialNotification();
    // Handle notification
  } catch (error) {
    // Handle error
  }
  // ...
})

But as this crash happens in the native code my try/catch doesn't help. The crash seems to be that getCurrentActivity() is null here: https://github.com/invertase/react-native-firebase/blob/master/packages/messaging/android/src/main/java/io/invertase/firebase/messaging/ReactNativeFirebaseMessagingModule.java#L58

It's a pretty big update, as this is the react-native-firebase release that will happen at the same time the Invertase Notifee library stabilizes the iOS release, and all sorts of rough edges needed smoothing as identified by Mike and Eliot while they were building Notifee - https://github.com/invertase/react-native-firebase/pull/3339

noticed this as well; tho, it's hard to test as app can't be launched in debug build from notification if killed previously

with android:launchMode="singleTop" in AndroidManifest, it doesn't crash, but also doesn't get initial notification if app was quitted

@softatac you can do Run -> Attach Debugger to Android Process in studio as the app is booting to debug.

@jbohman are you using any "non-standard" navigation library like the wix one?

@Ehesp I'm using the following navigation packages:

    "react-navigation": "^3.13.0",
    "react-navigation-hooks": "^1.1.0",
    "react-navigation-stack": "^1.10.3",

@Ehesp thanks, making progress
In debug build, I now get when receiving push notification, with app in DEAD state.
first this:

getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array

later on it crashes here

    java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Intent android.app.Activity.getIntent()' on a null object reference
        at io.invertase.firebase.messaging.ReactNativeFirebaseMessagingModule.getInitialNotification(ReactNativeFirebaseMessagingModule.java:58)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.facebook.react.bridge.JavaMethodWrapper.invoke(JavaMethodWrapper.java:371)
        at com.facebook.react.bridge.JavaModuleWrapper.invoke(JavaModuleWrapper.java:150)
        at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:26)
        at android.os.Looper.loop(Looper.java:224)
        at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(MessageQueueThreadImpl.java:225)
        at java.lang.Thread.run(Thread.java:919)
2020-04-18 09:37:16.423 18087-18087/com.soferonline.soferonline E/unknown:ReactNative: Unable to launch redbox because react activity is not available, here is the error that redbox would've displayed: Attempt to invoke virtual method 'android.content.Intent android.app.Activity.getIntent()' on a null object reference

When opening notification, only app theme is loaded, but no Component gets rendered. Not even the main HOC.

Looks like getCurrentActivity() is returning null then, which is odd. @softatac where are you calling that method in your JS code?

@Ehesp inside a redux saga:

async function init(onRegister, onNotification, onNotificationClick) {
  try {
    if (Platform.OS === 'ios' && !isSimulator()) {
      const settings = await messaging().requestPermission();
      if (!settings) return;
    }

    // receiving
    messaging().registerDeviceForRemoteMessages().then(async () => {
      const token = await messaging().getToken();
      onRegister({ token });
    });
    messaging().onMessage(async (remoteMessage) => {
      await onNotification(remoteMessage, true);
    });
    messaging().setBackgroundMessageHandler(async (remoteMessage) => {
      await onNotification(remoteMessage, false);
    });
    messaging().onNotificationOpenedApp(async (remoteMessage) => {
      await onNotificationClick(remoteMessage, true);
    });

    // app was quitted
    try {
      // TODO, does not work WHEN: push received, app quitted then re-opened from push
      messaging().getInitialNotification().then(async (initialMessage) => {
        if (initialMessage) await onNotificationClick(initialMessage, false);
      });
    } catch (error) {
      _error('@PUSH - get initial', error);
    }
  } catch (error) {
    _error('@PUSH - generalError', error);
  }
}

function* initSaga() {
  const eventEmitter = new EventEmitter();
  const channel = yield call(notificationChannelCreator, eventEmitter);
  yield init(
    registerData => eventEmitter.emit('register', registerData),
    (notification, isForeground = false) => eventEmitter.emit('notification', notification, isForeground),
    notification => eventEmitter.emit('notificationClick', notification),
  );

  while (true) {
    const action = yield take(channel);
    yield put(action);
  }
}

export function* mainSaga() {
  yield all([
    fork(initSaga),
    // fork(testSaga),
  ]);
}

This only happens when app is killed from Task view.

  • using XIAOMI MIUI
  • firebase 6.4.0 (crashalytics, analytics, remote config, messaging, performance monitoring)

Looks like getCurrentActivity() is returning null then, which is odd. @softatac where are you calling that method in your JS code?

I think in react-native owing to the asynchronicity of the JS/native bridge you are never guaranteed that your native code will execute while an Activity is actually present, it might have been destroyed by the time you attempt something. Last time I deep-dived on a bug related to the getCurrentActivity being unexpectedly null I came with the personal rule to never trust it / always check for null

Looks like getCurrentActivity() is returning null then, which is odd. @softatac where are you calling that method in your JS code?

I think in react-native owing to the asynchronicity of the JS/native bridge you are never guaranteed that your native code will execute while an Activity is actually present, it might have been destroyed by the time you attempt something. Last time I deep-dived on a bug related to the getCurrentActivity being unexpectedly null I came with the personal rule to never trust it / always check for null

Do you have a solution for this issue? Currently, this library is not very useful for my project which is a bummer because there is no good alternative.

I think I might have found a solution for this issue. The fact that the getCurrentActivity method returns null means that there is nu Activity (yet) at the moment the getInitialNotification method is called. I have no idea how the React Native startup process looks like and at what point the Activity gets instantiated but if you call the getInitialNotification method later on in the process, e.g. in the useEffect hook of the App, it all seems to work fine. The App does not crash and the RemoteMessage object even contains the correct data.

@softatac I don't have experience with saga, but what @sander48k said makes sense - the call may be being made before the app/activity is ready. Generally, I do all of the startup process within the useEffect. Setting up the listeners is fine since it's registering a JS event, not calling native.

@softatac @sander48k have you managed to reproduce it in the emulator? If so, could either of you outline how you managed it? I can only see it in production crashes at the moment.

Based on your feedback @sander48k it might be solved if I move the call from React.Component constructor to componentDidMount lifecycle method. But if possible I would like to confirm it before I roll out a new version of my app.

If you're doing it in the constructor, that could well, is probably the issue.

@sander48k thanks for the instructions, I managed to solve it;
As you mentioned, getInitialNotification gets called before ReactActivity is ready.

This happens only on Android, when notification is received and app is quitted: a HeadlessTask is started in the background. I think (haven't investigated) ReactActivity get initialised only when UI is rendered only.

@jbohman
So, the solution was to call getInitialNotification only when app was fully ready.
This depends on your implementation, for me with sagas it looked smth like this:

  • in global state app.ready is true when app is fully ready (e.g. db initialised, react activity is ready, etc.);
  • an APP_READY action gets emitted when state.app.ready is changed
function* processInitialNotifiation(onPresentCallback) {
  yield whenAppReady();
  try {
    messaging().getInitialNotification().then(async (initialMessage) => {
      _log('@PUSH - get initial', initialMessage);
      if (initialMessage) await onPresentCallback(initialMessage, false);
    });
  } catch (error) {
    _error('@PUSH - get initial', error);
  }
}
export function* whenAppReady() {
  if (yield select(state => state.app.ready)) return true;

  return yield take(APP_READY);
}

Thanks for your help

Hello, I'm facing this problem too.
I'm listening for messaging().getInitialNotification() from within a componentDidMount, but Firebase is throwing the same error:

image

@Ehesp can you tell us if your safe check is already available in any of these newer versions?

- 6.0.0-alpha.25
- 6.7.1
- 6.4.0-rc4
- 6.4.1-alpha.0

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.

Closing this issue after a prolonged period of inactivity. If this is still present in the latest release, please feel free to create a new issue with up-to-date information.

Was this page helpful?
0 / 5 - 0 ratings