Firebase Remote Config: Can't read any values, but fetch is successful
Asked Answered
B

12

51

I'm trying to have a remote config parameter using the new Remote Config feature of Firebase, and I'm having an issue.

Here's my Remote Config console: remote config console

I'm doing a fetch and update in my Application's onCreate():

final FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.getInstance();
remoteConfig.fetch().addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(@NonNull Task<Void> task) {
        if (task.isSuccessful()) {
            remoteConfig.activateFetched();
        }
    }
});

And here's how I'm reading it:

FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.getInstance();
String value = remoteConfig.getString("active_subscriptions");

Value is returning null.

If I call remoteConfig.getInfo().getLastFetchStatus(), it returns LAST_FETCH_STATUS_SUCCESS, so it seems the fetch is going through successfully.

Any idea why my value is blank?

Bellerophon answered 18/5, 2016 at 23:20 Comment(3)
Steven, see my comment below - I tried your fix, and it didn't work for me, but I was able to make it work by moving the fetch out of onCreate.Slam
I'm having the same problem and moving the fetch out of onCreate doesn't work for me .. if I move it into onResume, it will work on a second on Resume but not the initial onResume. This isn't exactly ideal as I want to configure aspects of my app remotely from first launch, not "at some point later down the line" :(Plankton
See #37501624.Oleson
B
12

Found the problem.

After adding some logging, I found that the fetch job's onComplete() was never being called. I moved the fetch from my Application's onCreate to a fragment's, and now it works properly!

(Ian Barber, this might be something to look into or clarify, as the logs indicated that Firebase was initialized without an issue when it was in the Application, and the fetches were silent failures.)

Bellerophon answered 21/5, 2016 at 13:51 Comment(5)
what if you need to use a fragment?Kendalkendall
I am using a fragment. Moving the fetch() call into the fragment fixed it for me.Bellerophon
That's interesting, we'll look into that. Thanks for the feedback!Terrorize
@IanBarber I have it in an activity, in onCreate, just like in the samples : github.com/firebase/quickstart-android/blob/master/config/app/… , but for some reason, the function onComplete doesn't get called on most devices, while it seems ok on Nexus 5 with Android 6. How come? What can I do to fix it? I tried running it on both UI thread and background thread. Both didn't work well.Bakerman
in my case am using 10.2.4 and facing the same issue, code reached in onComplete but value is always null.Delaney
T
19

You're likely hitting the caching in Remote Config. The way it works is that Config will cache incoming items locally, and return them. So your last (cached) fetch status was probably before the value was defined, and we get a cached blank value.

You can control the cache expiry, but if you fetch too often you risk getting throttled.

Because this is a common development problem though, there is a developer mode that lets you request more rapidly (for small groups of users):

FirebaseRemoteConfigSettings configSettings = 
    new FirebaseRemoteConfigSettings.Builder()
        .setDeveloperModeEnabled(BuildConfig.DEBUG)
        .build();
FirebaseRemoteConfig.getInstance().setConfigSettings(configSettings);

When you call fetch you can then pass a short cache expiration time

long cacheExpiration = 3600;
FirebaseRemoteConfig mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
if (mFirebaseRemoteConfig.getInfo().getConfigSettings().isDeveloperModeEnabled()) {
     cacheExpiration = 0;
}
mFirebaseRemoteConfig.fetch(cacheExpiration)
     .addOnCompleteListener(new OnCompleteListener<Void>() {
     // ...
});

That's how its done in the quickstart sample if you want a full reference.

Terrorize answered 18/5, 2016 at 23:58 Comment(7)
Unfortunately that didn't change anything.Bellerophon
This seems to be a different issue. I can confirm using gFirebaseRemoteConfig.getInfo() that fetch had never returned, so it wasn't a caching issuePlankton
fetching on onCreate() is okay and there's no need to put them in onStart(). The only things you have to do are enabling development mode and passing less seconds (i.e. 100) to the fetching method. It works very well. ThanksZaslow
Hi all, I have a simple boolean parameter but I can't seem to get the right value from the server. I'm calling fetch from onCreate. I have two listeners one for success and one for failure. The success one gets called and then I use the activateFetched. But I still can't get the right value, it's coming as false when is set to true.Injurious
Me again, keep testing and it's seems like Result inside the task response object is empty. It's like there is nothing to fetch but I have 3 properties now set LIVE on Firebase.Injurious
It's now working, haven't changed anything just updated to the new version 9.0.2Injurious
And me again. Couple of weeks later, I removed old parameters and add new ones, and I'm not getting the new ones, just the old ones, more than 24h later.Injurious
S
19

Workaround found! See below

I'm running into the "silent completion" thing - I call "fetch" but onComplete, onSuccess, or onFailure listeners never fire. I tried moving it to an activity onCreate, and still nothing happened, and therefore, the config items never get loaded from the server. I've got Developer Mode enabled, and am calling fetch with a cache value of 0.

I was able to (once) put a breakpoint on the line "public void onComplete(@NonNull Task task) {", which got hit, and then I was able to step through and the onComplete fired. I was then unable to reproduce this same result any other way, including doing the same thing (I think) a second time.

Seems like a timing or concurrency issue, but that makes little sense, given this is an asynchronous call.

Workaround

If you fetch from Activity#onResume (or, I presume, Activity#onStart), it works perfectly. Calling fetch from Activity#onCreate or Application#onCreate results in a call that seemingly never gets handled, and in fact, performance of the app degrades noticeably after the fetch begins, so I think there's a looper running or something.*

Workaround #2

If you really want this to run from Application#onCreate (which I do), this seems to work as well:

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        // Run mFirebaseRemoteConfig.fetch(timeout) here, and it works
    }
}, 0);
Slam answered 22/5, 2016 at 15:42 Comment(5)
I had this issue as well and a handler (#2) got config fetch to work properly. Very strange.Colcannon
Recently (I'm now using Firebase 9.0.1), the code I use in Workaround 2 isn't working for me anymore (and the bug still exists). So it looks like Workaround 1 is the only valid workaround now.Slam
This fixed it for me. I am running mine in a DialogFragment. I tried moving it from onViewCreated to onResume, but it still didn't work. Once I added the Handler.post(Runnable), the fetch call started working correctly.Veritable
I was using this workaround since version 9.0.0. Version 9.4.0 solved this problem, it's working checking it out.Reconcile
Version 9.4.0 does the trick for me too. If you still have the problem that the callback is not called, then check your device time. In my case the test device was 2 weeks in the past and therefore the fetching didn't work.Holcombe
B
12

Found the problem.

After adding some logging, I found that the fetch job's onComplete() was never being called. I moved the fetch from my Application's onCreate to a fragment's, and now it works properly!

(Ian Barber, this might be something to look into or clarify, as the logs indicated that Firebase was initialized without an issue when it was in the Application, and the fetches were silent failures.)

Bellerophon answered 21/5, 2016 at 13:51 Comment(5)
what if you need to use a fragment?Kendalkendall
I am using a fragment. Moving the fetch() call into the fragment fixed it for me.Bellerophon
That's interesting, we'll look into that. Thanks for the feedback!Terrorize
@IanBarber I have it in an activity, in onCreate, just like in the samples : github.com/firebase/quickstart-android/blob/master/config/app/… , but for some reason, the function onComplete doesn't get called on most devices, while it seems ok on Nexus 5 with Android 6. How come? What can I do to fix it? I tried running it on both UI thread and background thread. Both didn't work well.Bakerman
in my case am using 10.2.4 and facing the same issue, code reached in onComplete but value is always null.Delaney
H
8

I also encountered this problem. Turns out I hadn't seen the 'Publish' button in the the Firebase console. :facepalm:

Hogan answered 4/2, 2019 at 17:15 Comment(0)
S
6

I had the same problem and no workarounds were helpful in my case. The problem was in the testing device. I used emulator without installing Google Mobile Services, because of this the Complete event was not fired. I tried my phone with GMS and everything worked great. Good luck.

Salvador answered 23/10, 2016 at 16:1 Comment(0)
B
2

First thing in such case is check if you have the correct firebase config and you are connected to firebase .If you have android studio 2.2 got to Tools->Firebase->RemoteConfig - Connect to Firebase and see if you get a notification saying connected.Once Connected do the following in your code: mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();

    /** NOTE: At this point, your app can use in-app default parameter values.To use in-app
     *        default values,skip the next section. You can deploy your app without setting
     *        parameter values on the server,and then later set values on the server to
     *        override the default behavior and appearance of your app.
     */

    mFirebaseRemoteConfig.setDefaults(R.xml.remote_config_defaults);
    FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
            .setDeveloperModeEnabled(true)
            .build();
    mFirebaseRemoteConfig.setConfigSettings(configSettings);

And then for fetching config do the following long cacheExpiration = 2000; // Can increase this usually 12hrs is what is recommended

    /** If in developer mode cacheExpiration is set to 0 so each fetch will retrieve values from
     * the server.*/

    if (mFirebaseRemoteConfig.getInfo().getConfigSettings().isDeveloperModeEnabled()) {
        cacheExpiration = 0;
    }

   /**  cacheExpirationSeconds is set to cacheExpiration here, indicating that any previously
    * fetched and cached config would be considered expired because it would have been fetched
    * more than cacheExpiration seconds ago. Thus the next fetch would go to the server unless
    * throttling is in progress. The default expiration duration is 43200 (12 hours).
    */

    mFirebaseRemoteConfig.fetch(cacheExpiration)//TODO Bring this from a config file
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Firebase Remote config Fetch Succeeded");
                        // Once the config is successfully fetched it must be activated before newly fetched
                        // values are returned.
                        mFirebaseRemoteConfig.activateFetched();
                    } else {
                        Log.d(TAG, "Firebase Remote config Fetch failed");
                    }
                    showRemoteConfig();
                }
            });

Run your App and check in logs " Firebase Remote config Fetch Succeeded ". If you see the same your remote configs are loaded and activated.

Belittle answered 14/6, 2016 at 12:28 Comment(0)
W
2

I've used a similar code like @Ian Barber (copy):

FirebaseRemoteConfigSettings configSettings = 
    new FirebaseRemoteConfigSettings.Builder()
        .setDeveloperModeEnabled(BuildConfig.DEBUG)
        .build();
FirebaseRemoteConfig.getInstance().setConfigSettings(configSettings);

My problem was the "BuildConfig.DEBUG", it returns false. So it takes the value 1h in cache until it was fetched again!

Wreath answered 28/6, 2016 at 10:53 Comment(1)
Just make sure that BuildConfig is actually from you app, not some other packageSicard
R
2

Well in my case, I am able to receive control in addOnCompleteListener for fetch method but I have fetched values firebaseRemoteConfig just after I called firebaseRemoteConfig.activate(), so when I have tried to get the values from firebaseRemoteConfig it returns me previously saved values because firebaseRemoteConfig.activate() runs asynchronously and new values didn't saved before I am getting them from firebaseRemoteConfig, so I have added complete listener for activate() method also, Here:

firebaseRemoteConfig.fetch()
            .addOnCompleteListener(activity, OnCompleteListener {
                if (it.isSuccessful)
                {
                    Log.d("task","success")
                    firebaseRemoteConfig.activate().addOnCompleteListener {  // here I have added a listener
                        val base_url=firebaseRemoteConfig.getString("base_url")
                        Log.d("base url",base_url)
                        Toast.makeText(activity, "Base url: $base_url",Toast.LENGTH_SHORT).show()
                    }
                }
                else
                {
                    Log.d("task","failure")
                }

            })
Raguelragweed answered 13/6, 2019 at 11:31 Comment(0)
O
1

I had a problem that Firebase Remote Config didn't fire OnCompleteListener with fetch(0), but with fetch() did.

Looking at FirebaseRemoteConfig.fetch() does not trigger OnCompleteListener every time, I found that the first answer was working sometimes even with fetch(0). Then I again set 3600 seconds for interval, as errors continued to appear:

override fun onPostResume() {
    super.onPostResume()

    // Initialize FirebaseRemoteConfig here.
    ...

    firebaseRemoteConfig.fetch(3600).addOnCompleteListener { task ->
        if (task.isSuccessful) {
            firebaseRemoteConfig.activateFetched()
            //calling function to check if new version is available or not
            checkForUpdate(currentVersionCode, firebaseRemoteConfig.getString(VERSION_CODE_KEY))
        } else
            Toast.makeText(this@MainActivity, "Someting went wrong please try again",
                Toast.LENGTH_SHORT).show()
    }

}
Oleson answered 1/2, 2019 at 10:59 Comment(0)
S
0

I work on a big project and the problem was buried in an unexpected place. Long story short: the firebase application id(normally set through google-services.json) was changed through code:

FirebaseOptions.Builder builder = new FirebaseOptions.Builder();
builder.setApplicationId(applicationId);
builder.setApiKey(apiKey);
FirebaseOptions options = builder.build();
FirebaseApp.initializeApp(context, options);

The solution was to remove that code and let firebase use the info from "google-services.json".

Southernly answered 26/8, 2019 at 12:41 Comment(0)
K
0

Use fetchAndActivate instead of fetch

I was facing the same problem. After fetching, no listener get call for first time only. I try fetchAndActivate in single line and it works for me. Use below code

mFirebaseRemoteConfig.fetchAndActivate()
    .addOnCompleteListener(this, new OnCompleteListener<Boolean>() {
        @Override
        public void onComplete(@NonNull Task<Boolean> task) {
            if (task.isSuccessful()) {
                boolean updated = task.getResult();
                Log.d(TAG, "Config params updated: " + updated);
                Toast.makeText(MainActivity.this, "Fetch and activate succeeded",
                        Toast.LENGTH_SHORT).show();

            } else {
                Toast.makeText(MainActivity.this, "Fetch failed",
                        Toast.LENGTH_SHORT).show();
            }
            displayWelcomeMessage();
        }
    });

It will fetch and activate immediately. You can find this way in official documentation here

Kristof answered 6/8, 2022 at 10:2 Comment(0)
P
0

Does Android Studio's Build Variant match your intended Firebase project?

Papillose answered 10/8, 2022 at 2:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.