Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[馃悰] 馃敟 @react-native-firebase/messaging (Android) - Messaging() gets the wrong ReactContext when there is another Activity instantiated by ReactInstanceManager? #7768

Open
3 tasks done
longb1997 opened this issue Apr 27, 2024 · 10 comments
Labels
Help: Needs Triage Issue needs additional investigation/triaging. Impact: Bug New bug report Workflow: Needs Review Pending feedback or review from a maintainer.

Comments

@longb1997
Copy link

longb1997 commented Apr 27, 2024

Issue

Hello, first of all, thank you for the wonderful library.
In my app chat. I have an "Bubble Chat" which uses Bubbles API. It will show Bubbles when it receives new notifications.
And when you press on the bubble, then will display a window that runs startReactApplication display conversation screen (like Messenger).

The problem is that after pressing the Bubble, messaging() function in my Main App code doesn't works anymore, but if I use these codes in Bubble Chat code (separate from MainApp code) it still works. But if i delete Main App from Recent Apps, then reopen, from now on it work fine until I press a new bubble => start new conversation screen. (Ah sh*t, here we go again) => So i think when a react app start, this lib will use the most recent ReactContext of the app that just started.

Since messaging() in Main App was not working, it caused all my messaging().onNotificationOpenedApp, messaging().onMessage, messaging().getInitialNotification() to not working anymore
Thanks for helping me

i will provide some code here:

Project Files

BubbleActivity.kt:

class BubbleActivity : AppCompatActivity(), DefaultHardwareBackBtnHandler, PermissionAwareActivity {

    private lateinit var reactRootView: ReactRootView
    private lateinit var reactInstanceManager: ReactInstanceManager
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(null)
        SoLoader.init(this, false)

        val channelId = intent.getStringExtra("channelId")
        val initialProps = Bundle()
        if (channelId != null) {
            initialProps.putString("channelId", channelId)
        }

        reactRootView = ReactRootView(this)
        val packages: List<ReactPackage> = PackageList(application).packages
        // Packages that cannot be autolinked yet can be added manually here, for example:
        // packages.add(MyReactNativePackage())
        // Remember to include them in `settings.gradle` and `app/build.gradle` too.
            reactInstanceManager = ReactInstanceManager.builder()
                .setApplication(application)
                .setCurrentActivity(this)
                .setBundleAssetName("index2.android.bundle") => This Bubble has seperated code with MainApp, and it bundle will be generated before build.
                .setJSMainModulePath("index2") => entry file seperated with MainApp(index.js)
                .addPackages(packages)
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setJavaScriptExecutorFactory(HermesExecutorFactory())
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build()

        reactRootView.startReactApplication(reactInstanceManager, "chathead", initialProps) => It will start an ReactApp after pressed Bubble
        setContentView(reactRootView)
    }

    override fun onNewIntent(intent: Intent) {
        setIntent(intent)
        super.onNewIntent(intent)
    }
    override fun invokeDefaultOnBackPressed() {
        onBackPressedDispatcher.onBackPressed()
    }

    override fun onPause() {
        super.onPause()
        reactInstanceManager.onHostPause(this)
    }

    override fun onResume() {
        super.onResume()
        reactInstanceManager.onHostResume(this, this)
    }

    override fun onDestroy() {
        super.onDestroy()
        reactInstanceManager.onHostDestroy(this)
        reactRootView.unmountReactApplication()
    }

    override fun onBackPressed() {
        reactInstanceManager.onBackPressed()
        onBackPressedDispatcher.onBackPressed()
    }
}

And this is now in MainApp, where i use messaging() for handle notification

NotificationHandler.tsx

const NotificationHandler = memo(
  () => {
    // action press notify when app in background or active

    useEffect(() => {
      let unsubscribeOnNotificationOpenedApp: any = null;
      let unsubscribe: any = null;
      setTimeout(() => {
        unsubscribeOnNotificationOpenedApp = messaging().onNotificationOpenedApp(value => {
          return _.debounce(handleMessage, 300)(value);
        });
        
        unsubscribe = messaging().onMessage(message => {
          return require('lodash').debounce(handleRemoteMessage, 300)(message);
        });
      }, 1000);

      if (Platform.OS === 'android') {
        messaging()
          .getInitialNotification()
          .then(value => {
            return require('lodash').debounce(handleGetInitNotification, 1500)(value);
          });
      }

      return () => {
        unsubscribe && unsubscribe();
        unsubscribeOnNotificationOpenedApp && unsubscribeOnNotificationOpenedApp();
      };
    }, []);
    return null;
  },
  () => true
)

Then i used it like a component in MainApp

###App.tsx

<>
        <NotificationHandler />
        <Routes />
</>

package.json:

    "react-native": "0.71.13",
    "@react-native-firebase/analytics": "^18.3.0",
    "@react-native-firebase/app": "^18.6.1",
    "@react-native-firebase/crashlytics": "^18.3.0",
    "@react-native-firebase/messaging": "^18.6.1",

Android

Click To Expand

Have you converted to AndroidX?

  • my application is an AndroidX application?
  • I am using android/gradle.settings jetifier=true for Android compatibility?
  • I am using the NPM package jetifier for react-native compatibility?

android/build.gradle:

buildscript {
    ext {
        buildToolsVersion = "33.0.0"
        minSdkVersion = 23
        compileSdkVersion = 33
        targetSdkVersion = 33

        // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
        ndkVersion = "23.1.7779620"
        playServicesLocationVersion = "21.0.1"
        kotlinVersion = '1.8.0'
        kotlin_version = '1.8.0'
    }
    repositories {
        google()
        mavenCentral()
        maven { url "https://jitpack.io" }
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.3.1")
        classpath("com.facebook.react:react-native-gradle-plugin")

        // Make sure that you have the Google services Gradle plugin dependency
        classpath("com.google.gms:google-services:4.3.15")
        classpath('com.google.firebase:firebase-crashlytics-gradle:2.9.9')


        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

android/app/build.gradle:

apply plugin: "com.android.application"
apply plugin: "com.google.gms.google-services" // <- Add this line
apply plugin: "com.facebook.react"
apply plugin: 'kotlin-android'

import com.android.build.OutputFile

/**
 * This is the configuration block to customize your React Native Android app.
 * By default you don't need to apply any configuration, just uncomment the lines you need.
 */
react {
    /* Folders */
    //   The root of your project, i.e. where "package.json" lives. Default is '..'
    // root = file("../")
    //   The folder where the react-native NPM package is. Default is ../node_modules/react-native
    // reactNativeDir = file("../node_modules/react-native")
    //   The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen
    // codegenDir = file("../node_modules/react-native-codegen")
    //   The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
    // cliFile = file("../node_modules/react-native/cli.js")

    /* Variants */
    //   The list of variants to that are debuggable. For those we're going to
    //   skip the bundling of the JS bundle and the assets. By default is just 'debug'.
    //   If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
    // debuggableVariants = ["liteDebug", "prodDebug"]

    /* Bundling */
    //   A list containing the node command and its flags. Default is just 'node'.
    // nodeExecutableAndArgs = ["node"]
    //
    //   The command to run when bundling. By default is 'bundle'
    // bundleCommand = "ram-bundle"
    bundleCommand = "webpack-bundle"
    //   The path to the CLI configuration file. Default is empty.
    // bundleConfig = file(../rn-cli.config.js)
    //
    //   The name of the generated asset file containing your JS bundle
    // bundleAssetName = "MyApplication.android.bundle"
    //
    //   The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
    // entryFile = file("../js/MyApplication.android.js")
    //
    //   A list of extra flags to pass to the 'bundle' commands.
    //   See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
    // extraPackagerArgs = []

    /* Hermes Commands */
    //   The hermes compiler command to run. By default it is 'hermesc'
    // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
    //
    //   The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
    // hermesFlags = ["-O", "-output-source-map"]
}

/**
 * Set this to true to create four separate APKs instead of one,
 * one for each native architecture. This is useful if you don't
 * use App Bundles (https://developer.android.com/guide/app-bundle/)
 * and want to have separate APKs to upload to the Play Store.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
 */
def enableProguardInReleaseBuilds = true

/**
 * The preferred build flavor of JavaScriptCore (JSC)
 *
 * 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:+'

def localPropertiesFile = rootProject.file('local.properties')
def localProperties = new Properties()
localProperties.load(new FileInputStream(localPropertiesFile))

/**
 * Private function to get the list of Native Architectures you want to build.
 * This reads the value from reactNativeArchitectures in your gradle.properties
 * file and works together with the --active-arch-only flag of react-native run-android.
 */
def reactNativeArchitectures() {
    def value = project.getProperties().get("reactNativeArchitectures")
    return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
}

android {
    ndkVersion rootProject.ext.ndkVersion

    compileSdkVersion rootProject.ext.compileSdkVersion

    namespace "com.example.app"
    defaultConfig {
        applicationId "com.example.app"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 8409223
        versionName "7.3.3"
        multiDexEnabled true
        buildConfigField("String", "SECRET_KEY", localProperties["SECRET_KEY"])
    }

    // for react-native-twilio-video-webrtc
    dexOptions {
        jumboMode true
    }

    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include (*reactNativeArchitectures())
        }
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
    }

//    compileOptions {
//        sourceCompatibility JavaVersion.VERSION_17
//        targetCompatibility JavaVersion.VERSION_17
//    }

    buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://reactnative.dev/docs/signed-apk-android.
            signingConfig signingConfigs.debug
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }

    // 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
            // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
            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 =
                        defaultConfig.versionCode * 1000 + versionCodes.get(abi)
            }

        }
    }
}

dependencies {
    // The version of react-native is set by the React Native Gradle Plugin
    implementation("com.facebook.react:react-android")

    implementation 'com.google.android.play:core:1.10.2'
    implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")

    // for firebase
    // Import the BoM for the Firebase platform
    implementation(platform("com.google.firebase:firebase-bom:32.5.0"))


    // for HW keyboard
    implementation project(':react-native-hw-keyboard-event')
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

    debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
    debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
        exclude group:'com.squareup.okhttp3', module:'okhttp'
    }

    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
    if (hermesEnabled.toBoolean()) {
        implementation("com.facebook.react:hermes-android")
    } else {
        implementation jscFlavor
    }

    // add kotlin version
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21"
    implementation "androidx.core:core-ktx:1.8.0"

    // more
    // If your app supports Android versions before Ice Cream Sandwich (API level 14)
    implementation 'com.facebook.fresco:animated-base-support:1.3.0'

    implementation 'com.facebook.fresco:fresco:2.6.0'
    // For animated GIF support
    implementation 'com.facebook.fresco:animated-gif:2.5.0'

    // For WebP support, including animated WebP
    implementation 'com.facebook.fresco:animated-webp:2.5.0'
    implementation 'com.facebook.fresco:webpsupport:2.5.0'

    // For WebP support, without animations
    implementation 'com.facebook.fresco:webpsupport:2.5.0'

    // for react-natie-video
    implementation "androidx.appcompat:appcompat:1.6.1"

    // using for geo location services
    implementation 'com.google.android.gms:play-services-location:21.0.1'

    implementation "androidx.cardview:cardview:1.0.0"

    implementation 'com.github.bumptech.glide:glide:4.12.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'

}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'

android/settings.gradle:

rootProject.name = 'chatapp'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

include ':react-native-hw-keyboard-event'
project(':react-native-hw-keyboard-event').projectDir = new File(settingsDir, '../node_modules/react-native-hw-keyboard-event/android')


include ':app'
includeBuild('../node_modules/react-native-gradle-plugin')

MainApplication.java:

package com.example.app;

import android.app.Application;

import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.soloader.SoLoader;
import java.util.List;
import cl.json.ShareApplication;

import org.wonday.orientation.OrientationActivityLifecycle;

public class MainApplication extends Application implements ReactApplication, ShareApplication {

  private final ReactNativeHost mReactNativeHost =
      new DefaultReactNativeHost(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());
          packages.add(new BubblePackage());
          return packages;
        }

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

        @Override
        protected boolean isNewArchEnabled() {
          return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
        }

        @Override
        protected Boolean isHermesEnabled() {
          return BuildConfig.IS_HERMES_ENABLED;
        }
      };

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

  @Override
  public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(OrientationActivityLifecycle.getInstance());
    SoLoader.init(this, /* native exopackage */ false);
    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
      // If you opted-in for the New Architecture, we load the native entry point for this app.
      DefaultNewArchitectureEntryPoint.load();
    }
    ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  }

  @Override
      public String getFileProviderAuthority() {
          return "com.example.app";
      }
}

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />

    <!-- Request Permission for Image Picker -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission
            android:name="android.permission.WRITE_EXTERNAL_STORAGE"
            tools:node="replace" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission
            android:name="android.permission.ACCESS_MEDIA_LOCATION"
            tools:node="replace" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- RN-FETCH-BLOB -->
    <uses-permission
            android:name="android.permission.READ_EXTERNAL_STORAGE"
            tools:node="replace" />
    <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
    <uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

    <!--    remove AD_ID permission -->
    <uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove"/>

    <!-- Needed only if your app communicates with already-paired Bluetooth
           devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <!--bibo01 : hardware option-->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <uses-feature
            android:name="android.hardware.camera"
            android:required="false" />
    <uses-feature
            android:name="android.hardware.camera.autofocus"
            android:required="false" />
    <uses-feature
            android:name="android.hardware.microphone"
            android:required="false" />
    <!--    for permission -->

    <application
            android:name=".MainApplication"
            android:allowBackup="false"
            android:allowNativeHeapPointerTagging="false"
            android:exported="true"
            android:hardwareAccelerated="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:largeHeap="true"
            android:requestLegacyExternalStorage="true"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:theme="@style/AppTheme"
            android:usesCleartextTraffic="true"
            tools:replace="android:allowBackup,android:theme">


        <!--        android:hardwareAccelerated="false" if true it's crash on some devices android-->
        <activity android:name=".BubbleActivity"
            android:resizeableActivity="true"
            android:allowEmbedded="true"
            android:launchMode="singleTop"
            tools:targetApi="n" />

        <activity
                android:name=".MainActivity"
                android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
                android:exported="true"
                android:label="@string/app_name"
                android:launchMode="singleTask"
                android:windowSoftInputMode="adjustResize"
        >
            <!-- Note that if you set android:windowSoftInputMode to adjustResize or adjustPan,
           only keyboardDidShow and keyboardDidHide events will be available on Android-->

            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
                <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
            </intent-filter>

            <!-- This is for everything else -->
            <intent-filter android:label="ChatApp" android:autoVerify="true">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="com.example.app"/>
                <data android:scheme="message"/>
            </intent-filter>


            <intent-filter android:label="ChatApp" android:autoVerify="true">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="base-message"/>
            </intent-filter>

            <intent-filter android:label="ChatApp" android:autoVerify="true">
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <!--TODO:  Add this filter, if you want support opening urls into your app-->
                <data  android:scheme="https" android:pathPrefix="/" android:host="*.chatapp"/>
            </intent-filter>

            <!--TODO: Add this filter, if you want to support sharing text into your app-->
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.SEND"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="text/*"/>
            </intent-filter>

            <!--TODO: Add this filter, if you want to support sharing any type of files-->
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.SEND"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="*/*"/>
            </intent-filter>
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.SEND_MULTIPLE"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="*/*"/>
            </intent-filter>
            <!--TODO: Add this filter, if you want to support sharing videos into your app-->
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.SEND"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="video/*"/>
            </intent-filter>
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.SEND_MULTIPLE"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="video/*"/>
            </intent-filter>
            <!--TODO: Add this filter, if you want to support sharing any type of files-->
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.SEND"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="*/*"/>
            </intent-filter>
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.SEND_MULTIPLE"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="*/*"/>
            </intent-filter>

        </activity>

        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
        <meta-data
                android:name="com.google.firebase.messaging.default_notification_icon"
                android:resource="@mipmap/ic_notification" tools:replace="android:resource"/>
        <meta-data
                android:name="com.google.firebase.messaging.default_notification_color"
                android:resource="@color/primary" tools:replace="android:resource"/>
        <meta-data
                android:name="com.google.firebase.messaging.default_notification_channel_id"
                android:value="@string/base_default_channel"
                tools:replace="android:value"/>

        <!-- https://firebase.google.com/docs/cloud-messaging/android/client#prevent-auto-init -->
        <!-- This for prevent generating new token -->
        <meta-data
                android:name="firebase_messaging_auto_init_enabled"
                android:value="false"
                tools:replace="android:value"/>
        <meta-data
                android:name="firebase_analytics_collection_enabled"
                tools:replace="android:value"
                android:value="false"/>
        <!-- React-Native-Share -->
        <provider
                tools:replace="android:exported"
                android:name="androidx.core.content.FileProvider"
                android:authorities="${applicationId}.provider"
                android:exported="false"
                android:multiprocess="true"
                android:grantUriPermissions="true">
            <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/filepaths"
                    tools:replace="android:resource"/>
        </provider>

        <meta-data
                android:name="firebase_crashlytics_collection_enabled"
                android:value="true"
                tools:replace="android:value"/>

        <uses-library
                android:name="org.apache.http.legacy"
                android:required="false"/>
    </application>
</manifest>


Environment

Click To Expand

react-native info output:

 System:
    OS: macOS 14.4.1
    CPU: (4) x64 Intel(R) Core(TM) i3-8100 CPU @ 3.60GHz
    Memory: 25.89 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.20.2 - /usr/local/bin/node
    Yarn: 1.22.22 - /usr/local/bin/yarn
    npm: 10.5.0 - /usr/local/bin/npm
    Watchman: 2024.04.15.00 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.15.2 - /usr/local/lib/ruby/gems/3.3.0/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 23.4, iOS 17.4, macOS 14.4, tvOS 17.4, visionOS 1.1, watchOS 10.4
    Android SDK: Not Found
  IDEs:
    Android Studio: 2023.2 AI-232.10300.40.2321.11567975
    Xcode: 15.3/15E204a - /usr/bin/xcodebuild
  Languages:
    Java: 17.0.11 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 18.2.0 => 18.2.0 
    react-native: 0.71.13 => 0.71.13 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found```

<!-- change `[ ]` to `[x]` to select an option(s) -->

- **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:**
      "@react-native-firebase/analytics": "^18.3.0",
    "@react-native-firebase/app": "^18.6.1",
    "@react-native-firebase/crashlytics": "^18.3.0",
    "@react-native-firebase/messaging": "^18.6.1",
- **`Firebase` module(s) you're using that has the issue:**
  "@react-native-firebase/messaging": "^18.6.1",
- **Are you using `TypeScript`?**
  - YES

</p>
</details>

<!-- Thanks for reading this far down 鉂わ笍  -->
<!-- High quality, detailed issues are much easier to triage for maintainers -->

<!-- For bonus points, if you put a 馃敟 (:fire:) emojii at the start of the issue title we'll know -->
<!-- that you took the time to fill this out correctly, or, at least read this far -->

---

- 馃憠 Check out [`React Native Firebase`](https://twitter.com/rnfirebase) and [`Invertase`](https://twitter.com/invertaseio) on Twitter for updates on the library.
@longb1997 longb1997 added Help: Needs Triage Issue needs additional investigation/triaging. Impact: Bug New bug report labels Apr 27, 2024
@longb1997 longb1997 changed the title [馃悰] 馃敟 @react-native-firebase/messaging (Android) - messaging() take wrong reactContext when have another Activity initialize by ReactInstanceManager? [馃悰] 馃敟 @react-native-firebase/messaging (Android) - Messaging() gets the wrong ReactContext when there is another Activity instantiated by ReactInstanceManager? Apr 27, 2024
@longb1997
Copy link
Author

If you need me to provide more information, feel free to ask me @mikehardy
Thank you so much

@mikehardy
Copy link
Collaborator

Hey there - two thoughts,

1- can you use current versions please, just to make sure we're not chasing ghosts?
2- version skew within react-native-firebase packages violates our versioning expectations --> https://invertase.io/blog/react-native-firebase-versioning - all the same all the time is the rule

    "react-native": "0.71.13",
    "@react-native-firebase/analytics": "^18.3.0",
    "@react-native-firebase/app": "^18.6.1",
    "@react-native-firebase/crashlytics": "^18.3.0",
    "@react-native-firebase/messaging": "^18.6.1",

@mikehardy
Copy link
Collaborator

For troubleshooting:

So i think when a react app start, this lib will use the most recent ReactContext of the app that just started.

What makes you think that? I suggest using System.out.println or similar in the native code (yours and you can add it easily to react-native-firebase/messaging) to log out exactly what context is in use to see if they are different and/or incorrect.

In general it sounds like inference on a problem but without direct proof, and direct proof / ability to fix + test fixes will be difficult in the context of a large app whereas a https://stackoverflow.com/help/minimal-reproducible-example that was purpose built to expose the issue in could make it trivial to spot + verify fix

@longb1997
Copy link
Author

longb1997 commented May 2, 2024

For troubleshooting:

So i think when a react app start, this lib will use the most recent ReactContext of the app that just started.

What makes you think that? I suggest using System.out.println or similar in the native code (yours and you can add it easily to react-native-firebase/messaging) to log out exactly what context is in use to see if they are different and/or incorrect.

In general it sounds like inference on a problem but without direct proof, and direct proof / ability to fix + test fixes will be difficult in the context of a large app whereas a https://stackoverflow.com/help/minimal-reproducible-example that was purpose built to expose the issue in could make it trivial to spot + verify fix

I think so because if I copy notificationHandler's code and use in Bubble code, messages() works properly in Bubble code

MainApp uses index.js entry file, Bubble uses index2.js entry file, each file leads to its own folder in the source code

Edit: I put Log in onReceive inside ReactNativeFirebaseMessagingReceiver.java, it is the same context. But I don't know why messaging() code only runs in Bubble Code after opening the Bubble screen. If I close Bubble and close the app in recent apps. Then use it normally without open Bubble it works normally

@longb1997
Copy link
Author

Hey there - two thoughts,

1- can you use current versions please, just to make sure we're not chasing ghosts? 2- version skew within react-native-firebase packages violates our versioning expectations --> https://invertase.io/blog/react-native-firebase-versioning - all the same all the time is the rule

    "react-native": "0.71.13",
    "@react-native-firebase/analytics": "^18.3.0",
    "@react-native-firebase/app": "^18.6.1",
    "@react-native-firebase/crashlytics": "^18.3.0",
    "@react-native-firebase/messaging": "^18.6.1",

my bad, thanks for your reply. I just updated all React-native-firebase to the latest version (19.2.2). But the result is still the same.

@longb1997
Copy link
Author

longb1997 commented May 2, 2024

<activity android:name=".BubbleActivity" android:resizeableActivity="true" android:allowEmbedded="true" tools:targetApi="n" />

I updated BubbleActivity in AndroidManifest, when I open MainApp without closing Bubble, it looks like messaging() "thinks" MainApp is not in foreground

@mikehardy
Copy link
Collaborator

In general it sounds like inference on a problem but without direct proof, and direct proof / ability to fix + test fixes will be difficult in the context of a large app whereas a https://stackoverflow.com/help/minimal-reproducible-example that was purpose built to expose the issue in could make it trivial to spot + verify fix

@longb1997
Copy link
Author

longb1997 commented May 3, 2024

In general it sounds like inference on a problem but without direct proof, and direct proof / ability to fix + test fixes will be difficult in the context of a large app whereas a https://stackoverflow.com/help/minimal-reproducible-example that was purpose built to expose the issue in could make it trivial to spot + verify fix

Hi there,
Sorry for my interpretation, as you said, it's difficult to spot and verify fix using only my description
So I created a mini-repo to reproduce this error, please take a look https://github.com/longb1997/rn-fcm-issue-7768
Thank you for your time, I really appreciate it

@longb1997
Copy link
Author

if you have any confusion, please tell me @mikehardy
Thank you very much

@mikehardy mikehardy added the Workflow: Needs Review Pending feedback or review from a maintainer. label May 9, 2024
@decisionnguyen
Copy link

Same issue :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Help: Needs Triage Issue needs additional investigation/triaging. Impact: Bug New bug report Workflow: Needs Review Pending feedback or review from a maintainer.
Projects
None yet
Development

No branches or pull requests

3 participants