Search code examples
androidandroid-lifecyclefirebase-remote-config

Remote config value fetching is inconsistent


I am fetching Firebase remote config values both in onStart() and in onStop(). The variable I am holding in "min_version", used for in-app updates feature. So my problem is that when I am going to remote config and updating the values, they are not updated immediately but save their old values for one more app lifecycle iteration before being updated to the new value. That means that if I make the decision that I want all users from a certain version to updated, they will not get the in-app update immediately, but only after one iteration through onStop and than get it.

here are my codes for onStart() and onStop() -


@Override
  protected void onStart() {
    /**
     * We are fetching the minimum version that we want the user to have from Firebase Remote Config, only after we have the results we can proceed to start the app.
     */
    getMinAppVersion("onStart", () -> {
      // navigation drawer
      checkValidFacebookSession();
      initDrawerMenu();

      // network monitoring
      registerNetworkReceiver();

      // monitoring upload
      LocalBroadcastManager.getInstance(this).registerReceiver(mUploadReceiver, new IntentFilter(ULBroadcastConstants.UPLOAD_STATUS_ACTION));
      LocalBroadcastManager.getInstance(this).registerReceiver(mFCMReceiver, new IntentFilter(MyFirebaseMessagingService.RECEIVED_FCM_ACTION));

      checkInAppUpdate();
    });
    super.onStart();
  }

@Override
  protected void onStop() {
    getMinAppVersion("onStop", () -> {
      mNavigationView.setNavigationItemSelectedListener(null);
      mDrawerLayout.removeDrawerListener(mBadgeDrawerToggle);


      // network monitor
      unregisterNetworkReceiver();

      // unregister upload
      LocalBroadcastManager.getInstance(this).unregisterReceiver(mUploadReceiver);
      LocalBroadcastManager.getInstance(this).unregisterReceiver(mFCMReceiver);
    });

    super.onStop();
  }

here is my 'getMinAppVersion()' method -


private void getMinAppVersion(String didComeFrom, OnRemoteConfigFetchComplete listener){
    //fetching the min_version parameter from 'remote config' of Firebase and saves it to our local variable.
    FirebaseRemoteConfig mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
    FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder().setMinimumFetchIntervalInSeconds(200).build();
    mFirebaseRemoteConfig.setConfigSettingsAsync(configSettings);
    mFirebaseRemoteConfig.fetch(0);
    mFirebaseRemoteConfig.activate().addOnCompleteListener(task -> {
      if (task.isSuccessful()) {
        min_version = mFirebaseRemoteConfig.getLong(RemoteConfigUtil.MIN_VERSION);
        Timber.tag("min_version_" + didComeFrom).d(String.valueOf(min_version));
        if (listener != null)
          listener.onFetchComplete();
      } else {
        Timber.tag("min version").d("error while fetching and activating remove config");
      }
    });
  }


Solution

  • Here is why it's happening. The Remote Config caches the value in a local storage according to official docs. You can refer here and consider

    "Remote Config includes a client library that handles important tasks like fetching parameter values and caching them, while still giving you control over when new values are activated so that they affect your app's user experience. This lets you safeguard your app experience by controlling the timing of any changes."

    When you use the client library to fetch remote-config parameter, The cached value will be returned to you if it's there(TL;DL) for more information, you can read the official docs here. It uses minimum time interval to fetch the value to avoid app crashes, For that minimum interval time, last fetched value served as a cache

    mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
    FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
            .setMinimumFetchIntervalInSeconds(3600)
            .build();
    mFirebaseRemoteConfig.setConfigSettingsAsync(configSettings);
    

    Here 3600 is time of minimum interval between new fetch, You can adjust the time according to your requirement. If you have recently called fetch() and once again you are calling it, client-library determines according to minimum-interval time that the new API call should be carried out or serve a cached value. Firebase remote config works on REST api and uses Throttling as well.