Firebase remote config cache expiration time in release - android

I'm trying to setup firebase remote config for release mode by setting developer mode to false. But with cache expiration time less then 3000(may be a bit less, determined it experimentally) seconds, it fails to fetch data. It throws FirebaseRemoteConfigFetchThrottledException
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setDeveloperModeEnabled(false)
.build();
And with .setDeveloperModeEnabled(true) it allows me to set any time even 0 and works well.
Here is whole hunk:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setDeveloperModeEnabled(false)
.build();
mFirebaseRemoteConfig.setConfigSettings(configSettings);
mFirebaseRemoteConfig.setDefaults(R.xml.remote_config_defaults);
mFirebaseRemoteConfig.fetch(CACHE_EXPIRATION)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.i("info32", "remote config succeeded");
mFirebaseRemoteConfig.activateFetched();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.i("info32", "remote config failed");
}
});
}
}, 0);
Could you please explain what the issue is?

Remote Config implements client-side throttling to prevent buggy or malicious clients from blasting the Firebase servers with high frequency fetch requests. One user has reported the limit is five requests per hour. I haven't found the limit documented anywhere, although I have confirmed that five rapid fetches will activate throttling.
The caching of configuration values is explained in the documentation. Because of the throttling limits, it is not possible for your released app to immediately see changes in Remote Config values. Cached values will be used until the next fetch is allowed. The default cache expiration is 12 hours.

Related

Firebase Remote Config not updating on locale change

I have the below defined:
I first launch the app with the device's language (from Settings) set to English and it loads the lang-EN json.
If I go in the Settings of the device, change the language to French and restart the app, .fetch() will still return the lang-EN value. If I clear cache the app and restart it, it then loads the lang-FR value.
Doesn't .fetch() get ALL the remote config params and locally decide which to show the user? From the functionality i'm getting it seems that .fetch() only gets the parameter values only pertaining to the device at the moment of the call. Either that or there's a bug in the firebase code ... OR ... and i'm hoping this is the case, i'm doing something wrong.
This is how i'm initializing the singleton. Perhaps i'm missing something?
public void initialize(Context applicationContext) {
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setMinimumFetchIntervalInSeconds(5 * 60 * 60)//5 hours
.build();
getConfig().setConfigSettingsAsync(configSettings);
}
And yes, i have the latest version of the remote config sdk in the dependencies 19.2.0
fetch() is not enough.
To fetch parameter values from the Remote Config backend, call the fetch() method. Any values that you set in the backend are fetched and stored in the Remote Config object.
To make fetched parameter values available to your app, call the activate() method.
For cases where you want to fetch and activate values in one call, you can use a fetchAndActivate() request to fetch values from the Remote Config backend and make them available to the app:
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();
}
});
Because these updated parameter values affect the behavior and appearance of your app, you should activate the fetched values at a time that ensures a smooth experience for your user, such as the next time that the user opens your app

Firebase Remote Config isDeveloperModeEnabled() is deprecated

I'm trying to have a remote config parameter using the Remote Config feature of Firebase so I can get values from Firebase and use it in app. I already use it with no problem but after a Firebase update, I get this warning:
I tried to use getMinimumFetchIntervalInSeconds() instead of isDeveloperModeEnabled() in order to avoid the warning.
Here is my code:
final FirebaseRemoteConfig mFirebaseRemopteconfig = FirebaseRemoteConfig.getInstance();
long cachExpiration = 0;
if (mFirebaseRemopteconfig.getInfo().getConfigSettings().isDeveloperModeEnabled()) {
cachExpiration = 0;
}
mFirebaseRemopteconfig.fetch(cachExpiration)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
final String funct = mFirebaseRemopteconfig.getString("functionn");
if (getPackageName().compareTo(funct) != 0) {
finish();
}
mFirebaseRemopteconfig.activateFetched();
}
}
});
Any idea how to solve this problem?
About setMinimumFetchIntervalInSeconds, it is officially said:
Keep in mind that this setting should be used for development only,
not for an app running in production. If you're just testing your app
with a small 10-person development team, you are unlikely to hit the
hourly service-side quota limits. But if you pushed your app out to
thousands of test users with a very low minimum fetch interval, your
app would probably hit this quota.
Although you can setMinimumFetchIntervalInSeconds other than the default value (= 12 hours), it's all up to you about whether it would hit the quota or not, and may lead to FirebaseRemoteConfigFetchThrottledException.
Now, the new API requires you to setMinimumFetchIntervalInSeconds for altering the interval. It is a method of FirebaseRemoteConfigSettings.Builder. So you must build a FirebaseRemoteConfigSettings object through the builder after setMinimumFetchIntervalInSeconds, and then setConfigSettingsAsync the built FirebaseRemoteConfigSettings to your FirebaseRemoteConfig.
Here is an example of my own implementation:
if (BuildConfig.DEBUG) {
cacheExpiration = 0;
} else {
cacheExpiration = 43200L; // 12 hours same as the default value
}
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings
.Builder()
.setMinimumFetchIntervalInSeconds(cacheExpiration)
.build();
config = FirebaseRemoteConfig.getInstance();
config.setConfigSettingsAsync(configSettings);
config.fetch(cacheExpiration).addOnCompleteListener(activity, onCompleteListener);
--------------------------- revised ---------------------------
For your porpose
checking if package name is the same
you don't need isDeveloperModeEnabled() or any interval settings. Just fetch() without any settings (but with default settings):
mFirebaseRemopteconfig = FirebaseRemoteConfig.getInstance();
mFirebaseRemopteconfig.fetch()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
final String funct = mFirebaseRemopteconfig.getString("functionn");
if (getPackageName().compareTo(funct) != 0) {
finish();
}
mFirebaseRemopteconfig.activateFetched();
}
}
});

Firebase remote Config server value are same as default?

We are using remote config in our application, and since yesterday our remote value are not reflecting on apps it was working before. Due to this some of over feature breaks and produce crash.
FirebaseRemoteConfig mFirebaseRemoteConfig;
FirebaseRemoteConfigSettings configSettings;
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
configSettings = new FirebaseRemoteConfigSettings.Builder()
.setDeveloperModeEnabled(BuildConfig.DEBUG)
.build();
mFirebaseRemoteConfig.setConfigSettings(configSettings);
mFirebaseRemoteConfig.setDefaults(R.xml.firebase_remote_config_defaults);
mFirebaseRemoteConfig.fetch(getCacheExpiration(mFirebaseRemoteConfig))
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
// If is successful, activated fetched
if (task.isSuccessful()) {
MyloLogger.e("FIREBASE_REMOTE_CONFIG", "CONFIG_FETCHED");
mFirebaseRemoteConfig.activateFetched();
setFirebaseConfigData(mFirebaseRemoteConfig, false);
} else {
MyloLogger.e("FIREBASE_REMOTE_CONFIG", "ERROR - KILLLLLL MMMMEEEE ");
}
}
});
setFirebaseConfigData(mFirebaseRemoteConfig, true);`
implementation 'com.google.firebase:firebase-config:16.1.3'
This code was working previously, and suddenly not responding.
This was solved, the problem with the A/B testing regex which is fail and not showing any error. I think Firebase should have some kind of process the errors over there.

Firebase Remote Config fetch doesn't update values from the Cloud

I'm trying to set up Firebase Remote Config for my project.
I added Firebase via the Assistant. I added values to the server values on Google Cloud Console:
I've created default values xml in res/xml
<defaultsMap>
<!-- Strings-->
<entry >
<key>textView_send_text</key>
<value >your phrase goes here.</value>
</entry>
</defaultsMap>
Thats my MainActivity:
final private FirebaseRemoteConfig mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
protected void onCreate(Bundle savedInstanceState) {
//..code..
//fetch from Firebase
fetchAll();
}
private void fetchAll(){
final FirebaseRemoteConfig mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setDeveloperModeEnabled(BuildConfig.DEBUG)
.build();
mFirebaseRemoteConfig.setConfigSettings(configSettings);
mFirebaseRemoteConfig.setDefaults(R.xml.defaults);
mFirebaseRemoteConfig.fetch()
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()){
Toast.makeText(MainActivity.this, "Fetch Succeeded",
Toast.LENGTH_SHORT).show();
mFirebaseRemoteConfig.activateFetched();
}else{
Toast.makeText(MainActivity.this, "Fetch Failed",
Toast.LENGTH_SHORT).show();
}
displayWelcomeMessage();
}
});
}
private void displayWelcomeMessage(){
String welcomeMessage = mFirebaseRemoteConfig.getString("textView_send_text");
Toast.makeText(this, welcomeMessage,
Toast.LENGTH_SHORT).show();
}
Toast output:
So Toast gets the value from xml/defaults not from the Cloud.
It'd be much appreciated if somebody found where I made a mistake.
For development testing, specify a cache expiration time of zero to force an immediate fetch:
mFirebaseRemoteConfig.fetch(0) // <- add the zero
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
...
});
Some tips the helped to me:
Don't forget to click "publish changes" in Firebase console after each value update
Uninstall and install the App before checking (Firebase may not fetch immediately)
Use mFirebaseRemoteConfig.fetch(0)
For what it worth I found that our firebase remote configs weren't downloading no matter what we tried - we are usually debugging while connected to a proxy (like Charles Proxy) and that was interrupting the firebase cloud update.
Once we connected to a non-proxied wifi connection we got the update.
You can also set your config to developer mode if running a debug build which will refresh values more often - but the proxy was our root problem.
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
.setDeveloperModeEnabled(BuildConfig.DEBUG)
.build();
In Flutter, I just changed the value of minimumFetchInterval to const Duration(hours: 0). I manually added an message to firebase and here I just get it. Here is my code;
await Firebase.initializeApp();
RemoteConfig remoteConfig = RemoteConfig.instance;
await remoteConfig.setConfigSettings(RemoteConfigSettings(
fetchTimeout: const Duration(seconds: 10),
minimumFetchInterval: const Duration(hours: 0),
));
RemoteConfigValue(null, ValueSource.valueStatic);
bool updated = await remoteConfig.fetchAndActivate();
if (updated) {
print("it is updated");
} else {
print("it is not updated");
}
print('my_message ${remoteConfig.getString('my_message')}');
Make sure your mFirebaseRemoteConfig.fetch() called only once. It gets throttled if you call it multiple times.
There is a default minimum time duration Intervals for firebase remote config fetching. According to the Firebase documentation, it is now 12 hours. During that default time interval gap, if you change the keys from Firebase remote config and if you don't uninstall the app, you don't get updated data. you will get updated data after passing default time intervals. If you need more frequent data changes, you can override fetch intervals from client side.

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

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:
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?
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);
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.
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.)
I also encountered this problem. Turns out I hadn't seen the 'Publish' button in the the Firebase console. :facepalm:
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.
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.
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!
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()
}
}
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")
}
})
Does Android Studio's Build Variant match your intended Firebase project?
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".
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

Categories

Resources