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.69k stars 2.21k forks source link

[🐛] onNotificationOpenedApp and getInitialNotification are not called (Android, not splash screen issue ) #4574

Closed Olgagr closed 3 years ago

Olgagr commented 3 years ago

Issue

This is a similar issue to this one: https://github.com/invertase/react-native-firebase/issues/4005. However, I don't use react-native-bootsplash or react-native-splash-screen. I use firebase together with react-native-push-notification

I register callbacks on onNotificationOpenedApp and getInitialNotification. However, when I open the app from push notification, callbacks are never called.

I also register onMessage and setBackgroundMessageHandler. They work.

messaging().setBackgroundMessageHandler(remoteMessage => {
    return new Promise((resolve, reject) => {
      if (isAndroid()) {
        console.log('handle');
        NotificationService.handleNotification(remoteMessage, resolve);
      } else {
        resolve();
      }
    });
  });

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

  messaging().onMessage(m => console.log('onMessage'));

  messaging()
    .getInitialNotification()
    .then(remoteMessage => {
      if (remoteMessage) {
        console.log(
          'Notification caused app to open from quit state:',
          remoteMessage,
        );
      }
    });

Does anybody have similar issue?

Project Files

Javascript

Click To Expand

#### `package.json`: ```json { "name": "some_app", "version": "5.2.2", "private": true, "scripts": { "postinstall": "patch-package && npx jetify && cd ./node_modules/@twipemobilesolutions/twipe-app-react-native-iap && npm install && npm run build", "start": "react-native start", "run:android": "react-native run-android", "run:ios": "react-native run-ios", "lint": "tslint --project .", "lint:fix": "yarn lint --fix", "storybook": "start-storybook --config-dir ./src/components/storybook -p 7007", "storybook:android": "yarn storybook & ENVFILE=./src/components/storybook/storybook.env react-native run-android", "storybook:ios": "yarn storybook & ENVFILE=./src/components/storybook/storybook.env react-native run-ios", "test": "TZ=UTC jest", "test:win": "test.cmd", "tmg-ttg-ios": "yarn install && cd ios && pod install && cd .. && scripts/run.sh ios tmg ttg", "tmg-ttg-android": "yarn install && scripts/run.sh android tmg ttg" }, "dependencies": { "@react-native-community/async-storage": "^1.6.2", "@react-native-community/netinfo": "^4.1.1", "@react-native-community/push-notification-ios": "1.2.0", "@react-native-community/slider": "2.0.7", "@react-native-firebase/analytics": "7.6.8", "@react-native-firebase/app": "8.4.6", "@react-native-firebase/crashlytics": "8.4.11", "@react-native-firebase/messaging": "7.9.1", "@twipemobilesolutions/twipe-app-background": "git+ssh://git@bitbucket.org/twipemobilesolutions/twipe-app-background.git#1.1.3", "@twipemobilesolutions/twipe-app-react-native-iap": "git+ssh://git@bitbucket.org/twipemobilesolutions/twipe-app-react-native-iap.git#f438d6d219c728a4f1cde43180c46772ea359faa", "@twipemobilesolutions/twipe-app-rn-fetch-blob": "git+ssh://git@bitbucket.org/twipemobilesolutions/twipe-app-rn-fetch-blob.git#f62b61bdbb72605700a2ed87ec3c0ffd8a11c2fe", "@types/react-native-mail": "^3.0.0", "@types/react-native-push-notification": "^3.0.7", "@types/sinon": "^7.0.13", "axios": "0.18.1", "axios-auth-refresh": "^1.0.7", "axios-retry": "^3.1.2", "babel-plugin-idx": "^2.4.0", "date-fns": "^2.7.0", "date-fns-tz": "^1.0.10", "deep-object-diff": "^1.1.0", "filesize": "^5.0.3", "humps": "^2.0.1", "i18n-js": "^3.3.0", "idx": "^2.5.6", "iso8601-duration": "^1.2.0", "lodash": "^4.17.11", "patch-package": "^6.1.2", "postinstall-postinstall": "^2.0.0", "react": "16.8.6", "react-native": "0.60.0", "react-native-background-fetch": "^2.7.1", "react-native-config": "^0.11.7", "react-native-device-info": "^5.3.1", "react-native-exception-handler": "^2.10.8", "react-native-fs": "2.15.2", "react-native-gesture-handler": "^1.5.0", "react-native-get-random-values": "^1.4.0", "react-native-image-zoom-viewer": "^2.2.26", "react-native-inappbrowser-reborn": "^3.0.0", "react-native-inset-shadow": "^1.0.2", "react-native-keyboard-aware-scroll-view": "^0.9.1", "react-native-localize": "^1.1.4", "react-native-mail": "^4.1.0", "react-native-material-textfield": "^0.16.1", "react-native-orientation-locker": "^1.1.6", "react-native-progress": "^3.6.0", "react-native-push-notification": "^3.1.9", "react-native-rate": "^1.1.10", "react-native-safe-area-context": "^3.1.8", "react-native-safe-area-view": "^2.0.0", "react-native-svg": "^9.8.4", "react-native-swiper": "^1.5.14", "react-native-webview": "^10.10.2", "react-native-zip-archive": "^5.0.1", "react-navigation": "^4.0.10", "react-navigation-stack": "^1.7.3", "react-redux": "^7.1.0", "recyclerlistview": "^2.0.12", "redux": "^4.0.2", "redux-act": "^1.7.7", "redux-devtools-extension": "^2.13.8", "redux-persist": "^5.10.0", "redux-persist-filesystem-storage": "^2.1.0", "redux-saga": "^1.0.5", "reselect": "^4.0.0", "shallow-equal": "^1.2.0", "styled-components": "^4.3.2", "uuid": "^8.1.0", "yarn": "^1.19.2" }, "devDependencies": { "@babel/core": "^7.5.0", "@babel/runtime": "^7.5.2", "@react-native-community/cli": "^2.9.0", "@react-native-community/eslint-config": "^0.0.5", "@storybook/addon-actions": "^5.1.9", "@storybook/addon-info": "^5.1.9", "@storybook/addon-knobs": "^5.1.9", "@storybook/addon-links": "^5.1.9", "@storybook/addon-ondevice-knobs": "^5.1.9", "@storybook/addon-storyshots": "^5.1.9", "@storybook/addons": "^5.1.9", "@storybook/react-native": "^5.1.9", "@storybook/react-native-server": "^5.1.9", "@types/axios": "^0.14.0", "@types/humps": "^1.1.2", "@types/i18n-js": "^3.0.1", "@types/jest": "^24.0.15", "@types/lodash": "^4.14.136", "@types/node": "^12.6.2", "@types/react": "^16.8.23", "@types/react-native": "^0.60.0", "@types/react-native-material-textfield": "^0.16.0", "@types/react-navigation": "^3.0.7", "@types/react-redux": "^7.1.1", "@types/react-test-renderer": "^16.8.2", "@types/redux-logger": "^3.0.7", "@types/redux-persist": "^4.3.1", "@types/rn-fetch-blob": "^1.2.1", "@types/storybook__addon-knobs": "^5.0.2", "@types/storybook__addon-storyshots": "^4.0.1", "@types/storybook__react": "^4.0.2", "@types/styled-components": "^4.1.16", "@types/uuid": "^3.4.5", "@welldone-software/why-did-you-render": "^3.3.8", "axios-mock-adapter": "^1.17.0", "babel-jest": "^24.8.0", "babel-loader": "^8.0.6", "babel-plugin-transform-remove-console": "^6.9.4", "eslint": "^6.0.1", "husky": ">=1", "jest": "^24.8.0", "jetifier": "^1.6.1", "lint-staged": ">=8", "metro-react-native-babel-preset": "^0.55.0", "prettier": "1.18.2", "react-docgen-typescript-loader": "^3.1.0", "react-dom": "16.8.6", "react-native-asset": "github://femiveys/react-native-asset.git#d052f2371aa035017379031f7709d4fb5a71cd0f", "react-storybook-addon-props-combinations": "^1.1.0", "react-test-renderer": "16.8.6", "redux-logger": "^3.0.6", "redux-saga-test-plan": "^4.0.0-rc.3", "sinon": "^7.3.2", "ts-jest": "^24.0.2", "tslint": "^5.18.0", "tslint-config-prettier": "^1.18.0", "tslint-config-standard": "^8.0.1", "tslint-plugin-prettier": "^2.0.1", "tslint-react": "^4.0.0", "tslint-react-native": "^0.0.7", "typescript": "^3.5.3" }, "resolutions": { "react-native-safe-area-view": "^2.0.0" }, "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "*.{ts, tsx, css, json, md}": [ "prettier --write", "git add" ], "*.{ts, tsx}": [ "yarn lint --fix", "git add" ] } } ``` #### `firebase.json` for react-native-firebase v6: ```json { "crashlytics_auto_collection_enabled": true, "crashlytics_debug_enabled": true, "crashlytics_ndk_enabled": false, "react-native": { "messaging_android_headless_task_timeout": 180000 } } ```

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? - [ x] 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 supportLibVersion = "28.0.0" } repositories { google() jcenter() maven { url 'https://maven.fabric.io/public' } } dependencies { classpath("com.android.tools.build:gradle:3.4.1") classpath 'com.google.gms:google-services:4.2.0' classpath 'io.fabric.tools:gradle:1.28.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() } } ``` #### `android/app/build.gradle`: ```groovy buildscript { repositories { } dependencies { } } apply plugin: "com.android.application" apply plugin: 'io.fabric' repositories { } project.ext.envConfigFiles = [ tmgttgdebug: "clients/1/1/client.env", tmgttgrelease: "clients/1/ttg1client.env", ] apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" import com.android.build.OutputFile ``` #### `android/settings.gradle`: ```groovy rootProject.name = 'some_project' include ':rn-fetch-blob' project(':rn-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/rn-fetch-blob/android') include ':react-native-push-notification' project(':react-native-push-notification').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-push-notification/android') include ':react-native-background-fetch' project(':react-native-background-fetch').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-fetch/android') include ':react-native-orientation-locker' project(':react-native-orientation-locker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-orientation-locker/android') include ':react-native-gesture-handler' project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android') include ':react-native-config' project(':react-native-config').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-config/android') apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' ``` #### `MainApplication.java`: ```java package com.some_application; import android.app.Application; import android.content.Context; import androidx.multidex.MultiDex; import com.facebook.react.PackageList; import com.facebook.react.ReactApplication; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.soloader.SoLoader; 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 getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List 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() { setTheme(R.style.AppTheme); super.onCreate(); SoLoader.init(this, /* native exopackage */ false); } @Override protected void attachBaseContext(Context context) { super.attachBaseContext(context); MultiDex.install(this); } } ``` #### `AndroidManifest.xml`: ```xml ```


Environment

Click To Expand

**`react-native info` output:** ``` System: OS: macOS 10.15.7 CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz Memory: 1.51 GB / 32.00 GB Shell: 5.7.1 - /bin/zsh Binaries: Node: 12.18.4 - ~/n/bin/node Yarn: 1.19.2 - ~/Documents/projects/app/node_modules/.bin/yarn npm: 6.14.6 - ~/n/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: iOS SDK: Platforms: iOS 14.2, DriverKit 20.0, macOS 11.0, tvOS 14.2, watchOS 7.1 Android SDK: API Levels: 28, 29, 30 Build Tools: 28.0.3, 29.0.2, 30.0.2 System Images: android-29 | Intel x86 Atom, android-29 | Intel x86 Atom_64, android-29 | Google APIs Intel x86 Atom, android-30 | Google APIs Intel x86 Atom, android-30 | Google Play Intel x86 Atom IDEs: Android Studio: 4.1 AI-201.8743.12.41.6858069 Xcode: 12.2/12B45b - /usr/bin/xcodebuild npmPackages: @react-native-community/cli: ^2.9.0 => 2.9.0 react: 16.8.6 => 16.8.6 react-native: 0.60.0 => 0.60.0 ``` - **Platform that you're experiencing the issue on**: - [ ] iOS - [ ] Android - [ ] **iOS** but have not tested behavior on Android - [ x] **Android** but have not tested behavior on iOS - [ ] Both - **`react-native-firebase` version you're using that has this issue:** - 7.9.1 - **`Firebase` module(s) you're using that has the issue:** - messaging - **Are you using `TypeScript`?** - Yes, 3.5.


mikehardy commented 3 years ago

handlers aren't async? regardless - why wouldn't you use the notification packages' notification handling? That's what it's for! The notification functionality in this module is the absolute most bare implementation possible and I would expect a full featured local notification package to be far superior. I use notifee hooks for my initial notification work, for instance

Olgagr commented 3 years ago

@mikehardy Thanks for response. What do you mean by "handlers aren't async"? According to docs we should pass there a function.

mikehardy commented 3 years ago

you should pass an async function: https://rnfirebase.io/reference/messaging#getInitialNotification

Olgagr commented 3 years ago

@mikehardy I'm looking at the signature of getInitialNotification:

getInitialNotification(): Promise<RemoteMessage | null>;

You pass nothing to this function. It returns a Promise that resolves with RemoteMessage or null

onNotificationOpenedApp: https://rnfirebase.io/reference/messaging#onNotificationOpenedApp

onNotificationOpenedApp(listener: (message: RemoteMessage) => any): () => void;

You pass as a listener a function (synchronous) that returns any.

The examples from docs about notifications (https://rnfirebase.io/messaging/notifications)

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

    // Check whether an initial notification is available
    messaging()
      .getInitialNotification()
      .then(remoteMessage => {
        if (remoteMessage) {
          console.log(
            'Notification caused app to open from quit state:',
            remoteMessage.notification,
          );
          setInitialRoute(remoteMessage.data.type); // e.g. "Settings"
        }
        setLoading(false);
      });

I'm confused why do you suggest passing an async function to getInitialNotification or onNotificationOpenedApp.

mikehardy commented 3 years ago

Sorry I think I've gotten confused with the various startup hooks (messages, notifications, links)

Here's what I do in a bootstrap sequence prior to registering the root component in AppRegistry


    notifee.onForegroundEvent((event: Event) => {
      EventStreamService.logEvent('NOTIFICATION_FOREGROUND', UserStore.getUser()?.kullkiId);

      console.log('NotificationStore::onForegroundEvent listener', JSON.stringify(event, null, 2));

      if (event.type === EventType.PRESS) {
        console.log('NotificationStore::onForegroundEvent - notification pressed');
        if (event.detail.notification) {
          this.handleNotification(event.detail.notification);
        }
      }
    });

    notifee
      .getInitialNotification()
      .then((notification) => {
        if (notification !== undefined && notification !== null) {
          console.log(
            `NotificationStore::startup - notifee initial notification: ${JSON.stringify(
              notification,
              null,
              2
            )}`
          );
          NotificationStore.initialNotification = notification.notification;
          this.trigger();
          EventStreamService.logEvent('NOTIFICATION_OPEN_INITIAL', UserStore.getUser()?.kullkiId);
        }
      })
      .catch((err) => console.log('NotificationStore::startup - getInitialNotification error', err))
      .finally(() => console.log('NotificationStore::startup async link fetch finished.'));

    firebase
      .messaging()
      .onNotificationOpenedApp(async (message: FirebaseMessagingTypes.RemoteMessage) => {
        console.log(
          `NotificationStore::startup - firebase initial notification: ${JSON.stringify(
            message,
            null,
            2
          )}`
        );
      });
Olgagr commented 3 years ago

@mikehardy It makes no difference. It can be an async or sync function. In any case, it doesn't work for me.

What I figured out:

pavm035 commented 3 years ago

Same issue any solution?

Olgagr commented 3 years ago

@pavm035 I think in our case it was an issue with React Native version. When we bumped the version up, it started working.

CDBridger commented 2 years ago

I'm getting the same issue on react native 0.68.2 and 0.69.3 (I tried upgrading my react native after seeing your message, And no i'm not using splash-screen library either). onNotificationOpenedApp is working on ios but not for me on android.