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

:fire:[🐛] Android Secondary App - Remote config not fetching #5763

Closed stevenvp closed 1 year ago

stevenvp commented 3 years ago

Issue

The remote config fetching works perfectly fine when using the default firebase app. When using a secondary firebase app, the fetching is not occurring.

While logging, the app is correctly linked with the secondary firebase app. When using the fetch & activate methods, no errors are thrown. But while logging the status, it is kept at no_fetch_yet.

Output of logs === Remote config initialized ===

firebase.app('DEV').remoteConfig.getAll output

Project Files

package.json:

{
  "name": "ReactNativeProject",
  "version": "5.5.1",
  "engines": {
    "node": "12.x"
  },
  "private": true,
  "scripts": {
    "postinstall": "patch-package && npx jetify",
    "start": "react-native start"
  },
  "dependencies": {
    "@adobe/react-native-acpanalytics": "1.3.0",
    "@adobe/react-native-acpcore": "1.5.1",
    "@react-native-community/art": "^1.2.0",
    "@react-native-community/async-storage": "^1.6.2",
    "@react-native-community/netinfo": "^4.7.0",
    "@react-native-community/push-notification-ios": "1.2.0",
    "@react-native-community/slider": "2.0.7",
    "@react-native-firebase/analytics": "^12.8.0",
    "@react-native-firebase/app": "^12.8.0",
    "@react-native-firebase/crashlytics": "^12.8.0",
    "@react-native-firebase/messaging": "^12.8.0",
    "@react-native-firebase/remote-config": "^12.8.0",
    "@welldone-software/why-did-you-render": "^6.1.1",
    "Base64": "^1.1.0",
    "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",
    "pako": "^2.0.3",
    "patch-package": "^6.4.7",
    "postinstall-postinstall": "^2.0.0",
    "react": "17.0.1",
    "react-native": "0.64.2",
    "react-native-appsflyer": "6.2.42",
    "react-native-background-fetch": "^2.8.0",
    "react-native-config": "^1.4.2",
    "react-native-device-info": "5.3.1",
    "react-native-exception-handler": "^2.10.8",
    "react-native-flash-message": "^0.1.23",
    "react-native-fs": "2.15.2",
    "react-native-gesture-handler": "^1.10.3",
    "react-native-get-random-values": "^1.4.0",
    "react-native-iap": "^6.2.3",
    "react-native-image-zoom-viewer": "^2.2.27",
    "react-native-inappbrowser-reborn": "^3.0.0",
    "react-native-inset-shadow": "^1.0.2",
    "react-native-keyboard-aware-scroll-view": "^0.9.4",
    "react-native-localize": "^1.4.3",
    "react-native-mail": "^4.1.0",
    "react-native-modal": "^12.0.2",
    "react-native-orientation-locker": "^1.1.6",
    "react-native-pager-view": "^6.0.0-rc.0",
    "react-native-progress": "^4.1.2",
    "react-native-push-notification": "^8.1.1",
    "react-native-rate": "^1.1.10",
    "react-native-safe-area-context": "^3.1.8",
    "react-native-safe-area-view": "^2.0.0",
    "react-native-scalable-image": "^1.1.0",
    "react-native-screens": "^1.0.0 || ^1.0.0-alpha",
    "react-native-svg": "^9.13.6",
    "react-native-webview": "^11.6.4",
    "react-native-zip-archive": "^5.0.6",
    "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.2.0",
    "redux-saga": "^1.0.5",
    "reselect": "^4.0.0",
    "rn-material-ui-textfield": "^1.0.3",
    "shallow-equal": "^1.2.0",
    "styled-components": "^4.4.1",
    "uuid": "^8.1.0",
    "yarn": "^1.19.2"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/runtime": "^7.12.5",
    "@react-native-community/eslint-config": "^2.0.0",
    "@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",
    "@storybook/theming": "^6.2.8",
    "@types/axios": "^0.14.0",
    "@types/humps": "^1.1.3",
    "@types/i18n-js": "^3.0.1",
    "@types/jest": "^24.9.1",
    "@types/lodash": "^4.14.136",
    "@types/node": "^12.20.15",
    "@types/react": "^16.14.10",
    "@types/react-native": "^0.60.31",
    "@types/react-native-mail": "^3.0.0",
    "@types/react-native-material-textfield": "^0.16.0",
    "@types/react-native-push-notification": "^3.0.9",
    "@types/react-navigation": "^3.0.7",
    "@types/react-redux": "^7.1.1",
    "@types/react-test-renderer": "^16.9.5",
    "@types/redux-logger": "^3.0.7",
    "@types/redux-persist": "^4.3.1",
    "@types/rn-fetch-blob": "^1.2.1",
    "@types/sinon": "^7.5.2",
    "@types/storybook__addon-knobs": "^5.0.2",
    "@types/storybook__addon-storyshots": "^4.0.2",
    "@types/storybook__react": "^4.0.2",
    "@types/styled-components": "^4.4.3",
    "@types/uuid": "^3.4.9",
    "axios-mock-adapter": "^1.17.0",
    "babel-jest": "^26.6.3",
    "babel-loader": "^8.0.6",
    "babel-plugin-transform-remove-console": "^6.9.4",
    "eslint": "^7.14.0",
    "husky": ">=1",
    "jest": "^24.8.0",
    "jetifier": "^1.6.8",
    "lint-staged": ">=8",
    "metro-react-native-babel-preset": "^0.64.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": "17.0.1",
    "redux-logger": "^3.0.6",
    "redux-saga-test-plan": "^4.0.1",
    "sinon": "^7.5.0",
    "ts-jest": "^24.0.2",
    "tslint": "^6.1.3",
    "tslint-config-prettier": "^1.18.0",
    "tslint-config-standard": "^8.0.1",
    "tslint-plugin-prettier": "^2.0.1",
    "tslint-react": "^4.2.0",
    "tslint-react-native": "^0.0.7",
    "typescript": "^4.2.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"
    ]
  }
}

TypeScript

Click To Expand

#### React Native remote config usage ```typescript import firebase from '@react-native-firebase/app'; import remoteConfig from '@react-native-firebase/remote-config'; import { config } from '../config'; class RemoteConfigBaseService { private useDev: boolean = false; private get appRemoteConfig(): any { const firebaseEnvironment = this.useDev ? 'DEV' : '[DEFAULT]'; return firebase.app(firebaseEnvironment).remoteConfig(); } public async init(useDev: boolean = false) { try { this.useDev = useDev; // Not sure why this check is needed, but otherwise the initializeApp // method throws an error // Firebase App named 'DEV' already exists // but this is the only place where the init happens and the init method is only called once if (!firebase.apps.some(app => app.name === 'DEV')) { await firebase.initializeApp( { appId: 'appId', apiKey: 'apiKey', databaseURL: '', projectId: 'projectId', storageBucket: 'storageBucket', clientId: 'clientId', messagingSenderId: 'messagingSenderId', }, 'DEV', ); } // necessary to enable the remoteConfig module inside the firebase app remoteConfig(); await this.appRemoteConfig.setConfigSettings({ minimumFetchIntervalMillis: 60 * 1000, fetchTimeMillis: 8 * 1000, // Timeout fetching after 8s }); await this.appRemoteConfig.setDefaults({ fetch: JSON.stringify(config.defaultParams), }); await this.appRemoteConfig.fetch(); await this.appRemoteConfig.activate(); const printStatus = ` === Remote config initialized === - fetchTimeMillis: ${this.appRemoteConfig.fetchTimeMillis} - lastFetchStatus: ${this.appRemoteConfig.lastFetchStatus} - settings: ${JSON.stringify(this.appRemoteConfig.settings)} `; console.log(printStatus); const params = JSON.parse( this.appRemoteConfig.getValue('params').asString(), ); console.log('params ', params); } catch (e) { console.log('Remote config - Error occurred while initializing ', e); } } public async getParams(): TParams[] { try { console.log(this.appRemoteConfig.getAll()); const params = JSON.parse( this.appRemoteConfig.getValue('params').asString(), ); console.log('params ', params); return params; } catch (e) { return config.defaultParams; } } } export const RemoteConfigService = new RemoteConfigBaseService(); ```

firebase.json for react-native-firebase v6:

{
  "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? - [x] 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 // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext { buildToolsVersion = "31.0.0" minSdkVersion = 21 compileSdkVersion = 31 targetSdkVersion = 31 ndkVersion = "20.1.5948944" } repositories { google() jcenter() maven { url 'https://maven.fabric.io/public' } } dependencies { classpath("com.android.tools.build:gradle:4.1.0") 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() maven { url 'https://www.jitpack.io' } } } ``` #### `android/app/build.gradle`: ```groovy buildscript { repositories { } dependencies { } } apply plugin: "com.android.application" apply plugin: 'io.fabric' repositories { } project.ext.envConfigFiles = [ debug: "clients/debug.env", release: "clients/release.env", ] apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" import com.android.build.OutputFile project.ext.react = [ enableHermes: false, // 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 { ndkVersion rootProject.ext.ndkVersion compileSdkVersion rootProject.ext.compileSdkVersion flavorDimensions "default" compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } defaultConfig { applicationId "com.reactnative" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion resValue "string", "build_config_package", "com.reactnative" multiDexEnabled true ndk { abiFilters "armeabi-v7a", "armeabi", "x86", "arm64-v8a", "x86_64" } // react-native-iap: we only use the Google Play flavor missingDimensionStrategy 'store', 'play' } splits { abi { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK include "armeabi-v7a", "armeabi", "x86", "arm64-v8a", "x86_64" } } packagingOptions { pickFirst 'lib/x86/libc++_shared.so' pickFirst 'lib/x86/libjsc.so' pickFirst 'lib/x86_64/libjsc.so' pickFirst 'lib/arm64-v8a/libjsc.so' pickFirst 'lib/arm64-v8a/libc++_shared.so' pickFirst 'lib/x86_64/libc++_shared.so' pickFirst 'lib/armeabi-v7a/libc++_shared.so' pickFirst 'lib/armeabi-v7a/libjsc.so' } signingConfigs { } buildTypes { debug { debuggable true } release { minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } flavorDimensions "client", "env" productFlavors { } applicationVariants.all { variant -> variant.outputs.each { output -> def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { output.versionCodeOverride = defaultConfig.versionCode * 1000 + versionCodes.get(abi) } } } dexOptions { javaMaxHeapSize "4g" } } dependencies { implementation project(':react-native-push-notification') implementation project(':react-native-background-fetch') implementation project(':react-native-orientation-locker') implementation project(':react-native-gesture-handler') implementation project(':react-native-config') implementation fileTree(dir: "libs", include: ["*.jar"]) implementation 'com.android.support:multidex:1.0.3' implementation "com.facebook.react:react-native:+" implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation project(':reactnativereplicareader') // JSC from node_modules 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' exclude group:'com.squareup.okhttp3', module:'okhttp' } debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { exclude group:'com.facebook.flipper' } if (enableHermes) { def hermesPath = "../../node_modules/hermes-engine/android/"; debugImplementation files(hermesPath + "hermes-debug.aar") releaseImplementation files(hermesPath + "hermes-release.aar") } else { implementation jscFlavor } } task copyDownloadableDepsToLibs(type: Copy) { from configurations.compile into 'libs' } apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) apply plugin: 'com.google.gms.google-services' ``` #### `android/settings.gradle`: ```groovy rootProject.name = 'reactnative' include ':@adobe_react-native-acpcore' project(':@adobe_react-native-acpcore').projectDir = new File(rootProject.projectDir, '../node_modules/@adobe/react-native-acpcore/android') include ':@adobe_react-native-acpanalytics' project(':@adobe_react-native-acpanalytics').projectDir = new File(rootProject.projectDir, '../node_modules/@adobe/react-native-acpanalytics/android') 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') include ':react-native-art' project(':react-native-art').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/art/android') apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' ``` #### `MainApplication.java`: ```java package com.reactnative; import android.app.Activity; import android.content.Context; import android.app.Application; import android.content.Context; import android.os.Bundle; import android.util.Log; import androidx.appcompat.app.AppCompatDelegate; import androidx.multidex.MultiDex; import com.facebook.react.PackageList; import com.facebook.react.ReactApplication; import com.facebook.react.ReactInstanceManager; import com.adobe.marketing.mobile.reactnative.RCTACPCorePackage; import com.adobe.marketing.mobile.reactnative.analytics.RCTACPAnalyticsPackage; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; import java.lang.reflect.InvocationTargetException; import com.adobe.marketing.mobile.reactnative.RCTACPCorePackage; import com.adobe.marketing.mobile.AdobeCallback; import com.adobe.marketing.mobile.MobileCore; // import MobileCore import com.adobe.marketing.mobile.Identity; import com.adobe.marketing.mobile.Lifecycle; import com.adobe.marketing.mobile.Signal; import com.adobe.marketing.mobile.WrapperType; import com.adobe.marketing.mobile.LoggingMode; import com.adobe.marketing.mobile.InvalidInitException; import com.adobe.marketing.mobile.Analytics; import com.reactnativereplicareader.RCTReplicaReaderPackage; import java.util.Arrays; 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()); packages.add(new RCTReplicaReaderPackage()); 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); initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); if(BuildConfig.LOAD_ADOBE_SDK == "true"){ MobileCore.setApplication(this); MobileCore.setLogLevel(LoggingMode.ERROR); MobileCore.setWrapperType(WrapperType.REACT_NATIVE); try { Identity.registerExtension(); Lifecycle.registerExtension(); Signal.registerExtension(); Analytics.registerExtension(); MobileCore.start(new AdobeCallback() { @Override public void call(Object o) { MobileCore.configureWithAppID(BuildConfig.ADOBE_ID); } }); } catch (InvalidInitException e) { Log.e("MainApplication", String.format("Error while registering extensions %s", e.getLocalizedMessage())); } registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle bundle) { /*no-op*/ } @Override public void onActivityStarted(Activity activity) { /*no-op*/ } @Override public void onActivityResumed(Activity activity) { MobileCore.setApplication(MainApplication.this); MobileCore.lifecycleStart(null); } @Override public void onActivityPaused(Activity activity) { MobileCore.lifecyclePause(); } @Override public void onActivityStopped(Activity activity) { /*no-op*/ } @Override public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { /*no-op*/ } @Override public void onActivityDestroyed(Activity activity) { /*no-op*/ } }); } } @Override protected void attachBaseContext(Context context) { super.attachBaseContext(context); MultiDex.install(this); } /** * 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.rndiffapp.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 11.4 CPU: (8) arm64 Apple M1 Memory: 87.48 MB / 16.00 GB Shell: 5.8 - /bin/zsh Binaries: Node: 16.3.0 - ~/.nvm/versions/node/v16.3.0/bin/node Yarn: 1.22.10 - ~/.nvm/versions/node/v16.3.0/bin/yarn npm: 7.15.1 - ~/.nvm/versions/node/v16.3.0/bin/npm Watchman: 4.9.0 - /opt/local/bin/watchman Managers: CocoaPods: 1.11.2 - /usr/local/bin/pod SDKs: iOS SDK: Platforms: iOS 15.0, DriverKit 20.4, macOS 11.3, tvOS 15.0, watchOS 8.0 Android SDK: Not Found IDEs: Android Studio: 4.2 AI-202.7660.26.42.7486908 Xcode: 13.0/13A233 - /usr/bin/xcodebuild Languages: Java: 13.0.2 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 17.0.1 => 17.0.1 react-native: 0.64.2 => 0.64.2 react-native-macos: Not Found 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 - **`Firebase` module(s) you're using that has the issue:** - "@react-native-firebase/analytics": "^12.8.0" - "@react-native-firebase/app": "^12.8.0" - "@react-native-firebase/crashlytics": "^12.8.0" - "@react-native-firebase/messaging": "^12.8.0" - "@react-native-firebase/remote-config": "^12.8.0" - **Are you using `TypeScript`?** - Y v4.2.3

mikehardy commented 3 years ago

Hmm - on a glance your firebase dependencies look mostly up to date but:

        classpath("com.android.tools.build:gradle:4.1.0")
        classpath 'com.google.gms:google-services:4.2.0'
        classpath 'io.fabric.tools:gradle:1.28.1'

Unfortunately for this issue, none of that really matters. I've never used remote-config for a secondary app so this isn't a use case of mine, sorry.

Does this happen on iOS and android? Is there anything remotely relevant in either of the upstream SDK issues lists https://github.com/firebase/firebase-android-sdk/ / https://github.com/firebase/firebase-ios-sdk/ or stack overflow? Without personal experience or an App.js we can drop in to test (https://stackoverflow.com/help/minimal-reproducible-example) I'm not even sure where the problem is (your code, our wrapper module, underlying SDKs...)

stevenvp commented 3 years ago

The problem is only occurring on Android. On iOS the secondary app is working fine. When looking at the example code of react-native-firebase, the implementation should be fine.

https://rnfirebase.io/app/usage#secondary-apps https://rnfirebase.io/remote-config/usage

The issue was also occurring on older react-native-firebase versions, I was wondering if we should do anything extra for android. When using the DEV environments google-services.json, it fetches correctly.

mikehardy commented 3 years ago

I was wondering if we should do anything extra for android.

Unknown, I asked several other questions apart from ios vs android although that's great to know - indicates backend is working, and firebase-ios-sdk appears okay, which allows a focus of the effort on the android pathway here and firebase-android-sdk.

stevenvp commented 3 years ago

I've created a minimal reproducible project which will be handy for investigating the issue.

The problem is still occurring, you will see that on iOS the values are being retrieved correctly while on android the value is never coming back from the secondary app. When fetching with the primary app first, it will even return that value when using the secondary app.

https://github.com/stevenvp/remote-config-secondary-app-example

DaviGn commented 3 years ago

Same problem here. I have two projects on Firebase (prod and dev). I've created the prod's project before dev. I'm getting prod configs correctly. However, when I change the google-services file to dev, I'm still getting prod values.

mikehardy commented 3 years ago

Sorry to hear this is affecting you @DaviGn - the issue itself is obviously still open and @stevenvp did fantastic work creating a reproduction but I haven't had time to dig in yet and may not for a little while longer yet. This is wide open for anyone else that wants to dive in, in other words

DaviGn commented 3 years ago

After many tests, I realized that values in values.xml on path android\app\build\generated\res\google-services\debug\values\values.xml weren't beeing refreshed. I don't if it's a Google Service or react-native-firebase bug, but now it's working, I changed the values manually.

mikehardy commented 3 years ago

well, there are a lot of firebase options ;-) - but I think if you mean "is that where the FirebaseApp options are serialized to send across to the native side, then yes.

Thing is, we do other testing with secondary apps and the initialization works - we are sending things through, and the FirebaseApp is the secondary:

mike@osxvm-little:~/work/Invertase/react-native-firebase (@mikehardy/android12 *) % grep -ri secondary packages/**/e2e
packages/app/e2e/app.e2e.js:    should.equal(firebase.app('secondaryFromNative')._nativeInitialized, true);
packages/app/e2e/app.e2e.js:    should.equal(firebase.app('secondaryFromNative').name, 'secondaryFromNative');
packages/app/e2e/app.constants.e2e.js:      // secondaryFromNative + default
packages/auth/e2e/auth.e2e.js:        .auth(firebase.app('secondaryFromNative'))
packages/auth/e2e/auth.e2e.js:        .app.name.should.equal('secondaryFromNative');
packages/auth/e2e/auth.e2e.js:      firebase.app('secondaryFromNative').auth().app.name.should.equal('secondaryFromNative');
packages/database/e2e/database.e2e.js:        .database(firebase.app('secondaryFromNative'))
packages/database/e2e/database.e2e.js:        .app.name.should.eql('secondaryFromNative');
packages/database/e2e/database.e2e.js:      firebase.app('secondaryFromNative').database().app.name.should.eql('secondaryFromNative');
packages/database/e2e/database.e2e.js:      .database(firebase.app('secondaryFromNative'))
packages/database/e2e/database.e2e.js:      .app.name.should.eql('secondaryFromNative');
packages/database/e2e/database.e2e.js:    firebase.app('secondaryFromNative').database().app.name.should.eql('secondaryFromNative');
packages/firestore/e2e/DocumentReference/isEqual.e2e.js:      firebase.firestore(firebase.app('secondaryFromNative')).doc(`${COLLECTION}/baz`),
packages/firestore/e2e/WriteBatch/set.e2e.js:      const app2 = firebase.app('secondaryFromNative');
packages/firestore/e2e/WriteBatch/delete.e2e.js:      const app2 = firebase.app('secondaryFromNative');
packages/firestore/e2e/WriteBatch/update.e2e.js:      const app2 = firebase.app('secondaryFromNative');
packages/firestore/e2e/firestore.e2e.js:        .firestore(firebase.app('secondaryFromNative'))
packages/firestore/e2e/firestore.e2e.js:        .app.name.should.equal('secondaryFromNative');
packages/firestore/e2e/firestore.e2e.js:      firebase.app('secondaryFromNative').firestore().app.name.should.equal('secondaryFromNative');
packages/firestore/e2e/Query/isEqual.e2e.js:    const q1 = firebase.firestore(firebase.app('secondaryFromNative')).collection(subCol);
packages/ml/e2e/ml.e2e.js:      firebase.ml(firebase.app('secondaryFromNative')).app.name.should.equal('secondaryFromNative');
packages/ml/e2e/ml.e2e.js:      firebase.app('secondaryFromNative').ml().app.name.should.equal('secondaryFromNative');
packages/remote-config/e2e/config.e2e.js:        .firestore(firebase.app('secondaryFromNative'))
packages/remote-config/e2e/config.e2e.js:        .app.name.should.equal('secondaryFromNative');
packages/remote-config/e2e/config.e2e.js:        .app('secondaryFromNative')
packages/remote-config/e2e/config.e2e.js:        .app.name.should.equal('secondaryFromNative');
packages/storage/e2e/storage.e2e.js:        .storage(firebase.app('secondaryFromNative'))
packages/storage/e2e/storage.e2e.js:        .app.name.should.equal('secondaryFromNative');
packages/storage/e2e/storage.e2e.js:      firebase.app('secondaryFromNative').storage().app.name.should.equal('secondaryFromNative');

https://github.com/invertase/react-native-firebase/blob/4871131c3587e138398719ef5537731ee4fbe90a/packages/remote-config/e2e/config.e2e.js?#L26-L37

https://github.com/invertase/react-native-firebase/runs/4093905857?check_suite_focus=true#step:21:1598

So...the secondary app itself may be initialized and seen through the remote-config module, but clearly it's not loading the actual remote-config values from the secondary app.

I just scanned all the java code in packages/remote-config and it appears we are passing appName through everywhere and using that everywhere to get the correct native FirebaseApp and then the correct FirebaseRemoteConfig instance.

This seems like it might be a native issue in the underlying firebase-android-sdk - I wonder if it is possible to repro starting from https://github.com/firebase/quickstart-android/tree/master/config

mikehardy commented 3 years ago

the XML writing is the province of google-services-plugin: https://developers.google.com/android/guides/google-services-plugin https://github.com/google/play-services-plugins/#google-services-plugin

mikehardy commented 3 years ago

Am I correct in thinking if you do ./gradlew clean in the android directory then rebuild this works then?

DaviGn commented 3 years ago

Maybe it works, I'll try it, thanks. I'll make a script in package.json to do it every time I build the app.

JakobLierman commented 2 years ago

Having the same issue here.

The ./gradle clean seems to work only when the secondary app instance is active in the app. Switching back to the primary app is working as well. But when you switch back to the secondary, you have to do the clean again.

Also noticed it works best when stopping the Metro instance and even removing the application from the device to perform a fresh installation.

stale[bot] commented 2 years ago

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.

github-actions[bot] commented 1 year ago

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 attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

arthurgeron-work commented 1 year ago

I have the exact same problem, rechecked api tokens/client id to make sure they were right, remote config simply will not fetch on Android using secondary firebase instances, the fact that it's impossible to get debug logs aside from lastFetchedStatus does not help.