FirebaseRemoteConfig.fetch() does not trigger OnCompleteListener every time
Asked Answered
B

5

30

I'm trying to implement Firebase Remote Config :

override fun onCreate(savedInstanceState: Bundle?) {

    val configSettings = FirebaseRemoteConfigSettings.Builder().setDeveloperModeEnabled(BuildConfig.DEBUG).build()

    mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance()
    mFirebaseRemoteConfig.setConfigSettings(configSettings)
    mFirebaseRemoteConfig.setDefaults(R.xml.remote_config_defaults)
    fetchRemoteConfig()
}

private fun fetchRemoteConfig() {
    var cacheExpiration = 3600L
    if (mFirebaseRemoteConfig.info.configSettings.isDeveloperModeEnabled) {
        cacheExpiration = 0L
    }

    mFirebaseRemoteConfig.fetch(cacheExpiration)
        .addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    Log.d(TAG, "Remote config fetch succeeded")
                    mFirebaseRemoteConfig.activateFetched()
                } else {
                    Log.d(TAG, "Remote config fetch failed - ${task.exception?.message}")
                }

                setupView()
            }
}

private fun setupView() {
    val text = mFirebaseRemoteConfig.getString("my_text")
    //...
}

My problem is that the OnCompleteListener is not always called. If I close/open my app several times, the setupView() is not always triggered.

The OnCompleteListener should always be called right? Even if I'm hitting cache?

EDIT: Even if I disable the developper mode the behavior is the same. Sometimes the callback is triggered, sometimes not.

Butter answered 28/5, 2016 at 16:0 Comment(5)
I have this same problem..but of course debugging can't get in there and see what is going on and I can't figure out how to turn up logging.Paleontography
for what it's worth.. it seems like oncomplete will not be called until you see this log message "FirebaseInstanceId: topic sync succeeded" then subsequent calls to fetch will work.Paleontography
@Paleontography where did you fire the fetch() ? In onCreate(), onResume(), elsewhere ? Because I moved the fetch() in onResume() and now It seems to work. By the way my workaround like your are working because they delayed the moment where the fetch() is triggered. Maybe if we call fetch() to early we can't retrieve remote config.Butter
In onCreate.. our config is managed in a singleton that is created by our DI framework which happens at Application onCreatePaleontography
Similar issue: #37312082Hying
B
28

I was facing the same issue and contacted the firebase support. They replied the following:

There currently is a bug that has been reported where onComplete, onSuccess, and onFailure listeners doesn't get called if fetch() is called too early. [...] Currently there is a work around where you can put the fetch() inside a postResume. You can try using this in the meantime before a solution has been released.

I implemented the workaround accordingly

protected void onPostResume() {
    super.onPostResume();

    mFirebaseRemoteConfig.fetch(cacheExpiration)
            .addOnSuccessListener(new OnSuccessListener<Void>() {
                @Override
                public void onSuccess(Void aVoid) {
                    Log.d(TAG, "Fetch Succeeded");
                    // Once the config is successfully fetched it must be activated before newly fetched values are returned.
                    mFirebaseRemoteConfig.activateFetched();
                    // Do whatever should be done on success
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception exception) {
                    Log.d(TAG, "Fetch failed");
                    // Do whatever should be done on failure
                }
            });
}

So far it seems their proposed workaround has resolved the issue.

UPDATE:

I just got notice from the firebase support. According to them the issue is resolved with the latest Google Play Services update.

A fix to Remote Config not calling listeners after fetching has been released in the newest Google play services update. I'll be closing this case for now. However if you are still experiencing issues, feel free to reach out and let me know.

Blunt answered 6/6, 2016 at 18:59 Comment(6)
Thanks, Max! Did they provide a link to the bug to track this?Paleontography
No, unfortunately not. However, the Firebase support said they would keep me posted on the bug fix when there is more to be released. I will let you know.Blunt
Unfortunately, calling fetch() on postResume doesn't seem to work reliably for me either.Curcio
@Blunt please update this SO when they get back to you. thanks!Steamship
@Blunt can you provide a link to that issue ? On which google playservices is this bug fixed ?Selfrespect
Bang on. Moved the load call from onCreate to onResume, and the completion block now gets called.Aggression
E
2

If your device run an old Google Play Service and incompatible version, you should see in logs:

GooglePlayServicesUtil: Google Play services out of date. Requires 11020000 but found 10930470

One solution is to upgrade your device Google Play services, but if you cannot, you can also simply downgrade firebase version to match the expected version (here change 11.0.2 to 10.9.3). Not ideal, but still a solution if you cannot upgrade your device (for instance the simulator is running 10.9.3 as of today):

compile 'com.google.firebase:firebase-core:10.2.6'
compile 'com.google.firebase:firebase-messaging:10.2.6'
compile 'com.google.firebase:firebase-config:10.2.6'
Ens answered 6/7, 2017 at 13:22 Comment(0)
T
1

For those of you who cannot make it by simply calling fetch() onPostResume (and really willing to make this work better), you may try calling fetch method inside Handler.postDelayed() to delay your fetch timing. For our team it increased the chance of fetch method working correctly. Of course this solution does not work reliably just like calling fetch onPostResume though.

@Override
public void onPostResume() {
   new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
         mFirebaseRemoteConfig.fetch(cacheExpiration)...
         ...
      }
   }, 500L);
}
Tweet answered 21/7, 2016 at 6:33 Comment(0)
N
0

For my case, I can 100% reproduce the issue when phone screen is locked, somehow onCompleteListener does not get triggered at all.

And in my case I don't need to add any delay, I just need call it after a Handler post, even in onCreate method and it works. I am using fetchAndActivate though.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Handler(Looper.getMainLooper()).post {
        FirebaseRemoteConfig.getInstance().fetchAndActivate().addOnCompleteListener(activity) { task ->
            ...
        }
    }
}
Nadaha answered 22/5, 2023 at 6:13 Comment(0)
P
-1

UPDATE version 9.2.0 of firebase works as one would expect and this hack is no longer needed.

I got this "working" reliably... but you may not like my solution. In order to get the config fetch to happen when firebase is ready I had to do this:

FirebaseAuth.getInstance()
   // I don't actually want to or need to sign in..(and this actually throws an error for us.. but we ignore it)
  .signInAnonymously()
  // when it completes (error or no error) we can do our business
  .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
      @Override
      public void onComplete(@NonNull Task<AuthResult> task) {
        // do the remote config fetch you were doing before
        remoteConfig.fetch(...).addOnComplete(...);
      }
  });

This ensures that the firebase internals are ready to do that initial config fetch... on first app open this seems to take about 6-10 seconds on my crappy test device (the entire thing including the auth and config fetch). On subsequent opens the entire thing takes like 2-5 seconds. Obviously that's all arbitrary depending on device/network and YMMV.

I would love to know why this is required.. seems like remote config should be able to manage this internally and not expose this to us.

p.s. you will need this dependency in addition to the firebase-config

compile 'com.google.firebase:firebase-auth:9.0.1'

Paleontography answered 1/6, 2016 at 20:8 Comment(2)
Indeed I don't really like this workaround. I sent an email to Firebase support team to have more details or at least to signal this weird behavior. I will probably still use my personal remote config before switch to Firebase. But thanks anyway :)Butter
Sounds good! Please update this question if you get a response!Paleontography

© 2022 - 2024 — McMap. All rights reserved.