Closed jbohman closed 4 years ago
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.
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:
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:
@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.
Issue
Hello react-native-firebase team,
I observed the following crash in production:
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`: ```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: ```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 # N/A ``` #### `AppDelegate.m`: ```objc // 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`: ```groovy 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`: ```groovy 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`: ```groovy rootProject.name = 'myapp' apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' ``` #### `MainApplication.java`: ```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 getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List 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`:
```xml
```
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`