The new Firebase has been released during the Google I/O 2016, and one of the key features is called Firebase Remote Config. It allows you to experiment within your app and to ship faster with less risk. It can be used as an asynchronous remote control in your apps. And we’ve open-sourced our Firely Facade to make using it easier.
The Remote Config is a key-value pair configuration store that can be synced with the devices. And you can apply conditions on those configurations to distribute different values depending on many criteria: countries, languages, package names, audiences, random percentage of users…
Remote Config is great for :
This is really easy and not the scope of this blog post, but you can find complete tutorials and sample app walkthrough on Firebase Remote Config Android Sample App Walkthrough
At Busbud, we use Firebase Remote Config a lot and especially for A/B testing. We initially integrated Remote Config very simply in the application but after a few months of use, we saw patterns emerge from using Firebase Remote Config: the footprint in the code was not that light. And it was definitely not DRY.
Let’s imagine that we want to integrate a feature flag (on/off) using Firebase Remote Config, from scratch.
Configuring Firebase Remote Config is quite simple:
In fact, you end up with quite a bit more code than you had bargained for, when all you really wanted to write was:
if (FirebaseRemoteConfig.isMyFeatureFlagOn(MyFeatureFlag)) { // Let's do that } else { // Let's do this }
After few iterations, we wanted something that:
We ended-up with a small and light library called Firely.
Nothing revolutionary here, but just a nicer Facade, our comfy version of Firebase Remote Config.
This library, integrated in your gradle project, only requires:
firely-config.json
file that will contains the type of items, the keys, and the default valueFirely.setup(Context context)
from the Application.onCreate()
methodfirely-config.json
file is organized in 3 main sections (for us, but it can have the “names” you want):
Here is an example of firely-config.json
:
{
"config": [
{
"key": "android_version_code_min",
"default": 0
}
],
"feature_flag": [
{
"key": "refer_a_friend",
"default": true
},
{
"key": "promotion_url",
"default": ""
}
],
"experiment": [
{
"key": "xp_button_pay",
"default": "control"
}
]
}
Firely is an Android library that come with a gradle plugin, firely-plugin
. It will generate a FirelyConfig.java
file based on the firely-config.json
, like the R.java
android creates. The FirelyConfig.java
will contain Enums that match the configuration. You can then use these enums on Firely to get LiveVariable
, CodeBlock
, OrderedArrayBlock
.
Let’s imagine I am using Remote Config to restrict my user to a minimum Android version on which they can run (otherwise they have to update the app). With Firely, I can instantiate a LiveVariable that will use this setting:
LiveVariable<Integer> minAndroidRemoteVersion = Firely.integerVariable(FirelyConfig.Config.ANDROID_VERSION_CODE_MIN);
FirelyConfig.Config.ANDROID_VERSION_CODE_MIN
is generated by the plugin and the default value is 0.
Now, anytime I need to get the last version that has been fetched, I just call:
Integer lastVersion = minAndroidRemoteVersion.get();
Here is another example with a feature flag:
if (Firely.booleanVariable(FirelyConfig.FeatureFlag.REFER_A_FRIEND).get()) { // Add the view }
Now I need to build out an XP that will change the text of a button.
Firely.codeBlock(Remote.Experiment.XP_BUTTON)
.withVariant("billed_currency", "no_price")
.execute(
() -> advance.setText(getString(R.string.bb_payment_cta)), // control
() -> advance.setText(.getString(R.string.bb_payment_cta_2)), // billed_currency
() -> advance.setText(getString(R.string.bb_payment_cta_3))); // no_price
NOTE: we are always using “control” as the default value and as the control group for A/B Tests.
In the Busbud Android App, we use a lot of blocks and lists. Let’s imagine you have N blocks of data in a page.
You want to A/B test which one should go first and the order for all the others.
A basic approach could be to have N! variants.
If we have three items: 1-2-3, 2-1-3, 2-3-1, 1-3-2, 3-2-1, 3-1-2
And while using CodeBlocks:
Firely.codeBlock(Remote.Experiment.XP_BUTTON)
.withVariant("2-1-3", "2-3-1", "1-3-2", "3-2-1", "3-1-2")
.execute(
() -> {
addOne();
addTwo();
addThree();
}, // control
() -> {
addTwo();
addOne();
addThree();
},
... etc
Really inefficient.
Another approach is to use OrderedArrayBlock. You will use one Firebase entry:
{
...
"experiment": [
{
"key": "xp_mypage_order",
"default": "one,two,three"
}
]
}
OrderedArrayBlock mCheckoutXp =
Firely.orderedArrayBlock(FirelyConfig.Experiment.XP_CHECKOUT_ORDER)
.addStep("one", () -> addOne())
.addStep("two", () -> addTwo())
.addStep("three", () -> addThree());
And you can control your A/B Tests from the Firebase Remote Config dashboard by changing the xp_mypage_order
key.
three,one,two
will then call addThree()
, addOne()
, addTwo()
. You can use this to remotely control the order of lists.
One of the highlights of Firebase is that everything is working together. In the documentation, Firebase proposes putting the values, manually, as a User Property:
String experiment1_variant = FirebaseRemoteConfig.getInstance().getString("experiment1");
AppMeasurement.getInstance(context).setUserProperty("MyExperiment",experiment1_variant);
That’s nice, but it does not fit our needs. Putting the property at the user level means it will be erased over time and we will lose the information. Instead, we prefer to tag all the events with all the experiments that have been applied at the time the event is triggered.
We added a method on Firely to help with this:
Firely.getAllPropsWithCurrentValue()
And this method is called each time we send an event and merged into the property list.
Therefore we can track the configuration changes over time.
Firely is really simple and contains:
One of the key issues we currently have is determining the best time to FirebaseRemoteConfig.fetch()
and follow with FirebaseRemoteConfig.activateFetched()
on the local Firebase Remote Config. And also decide on the cacheExpiration
.
For your convenience, here’s the way Firebase Remote Config works:
Firely is very simple. It’s plugged into the registerActivityLifecycleCallbacks
and will only fetch the configuration while your user is using the app actively (i.e. opening / closing screens – if you have an app that have no Activity component, we’re accepting contributions 😉 ).
FirebaseRemoteConfig.fetch()
is called in onResume()
and, in the case of production, the cache expiration is set at 0 until we actually get a configuration and then it’s set to 1 hour. For the record, Firebase allow you to make 5 requests per hour for a given app. The INITIAL_CHECK
with the cache expiration at 0 is reset anytime your app is updated, to force the last config to be used as fast as possible.
FirebaseRemoteConfig.activateFetched()
is a bit more complex because we wanted to misrepresent for analytics (you don’t want to send properties that do not reflect what is used in the app) and that make sense as a user. You don’t want your users to navigate forward through your app and then discover as they try to go back that they’re now in another variant of the screen they were expecting to find. To provide a more stable experience for users, we decided to FirebaseRemoteConfig.activateFetched()
once the root task is destroyed, so the config will be applied next launch. The reason why is that our app is based on a single Task of Activities. This may not fit all projects.
But when developing, you want the fetch to be activated as soon as possible. In debugMode, the FirebaseRemoteConfig.activateFetched()
is called in onPause()
.
And that’s pretty much it!
This is a very first rough cut, and the idea behind the Firely library is to keep it light and open.
Some ideas here:
FirebaseRemoteConfig.activateFetched()
and the way the consistency can be guaranteed between the variable you access and what is sent to the Analytics APIs.It took roughly 2 or 3 days of dev work to end up with a solution that better fits our needs.
There are a lot of complex solutions that exist on the market, but Firebase Remote Config is one that is almost free.
And while Firebase Remote Config is nice, you may need something comfier and DRYer for your daya to day work. There is nothing wrong in making your life easier, so give Firely a try.
You can find the open-source code on github.
Source: Busbud engineering
There’s never been a better time to explore Canada’s stunning landscapes, vibrant cities, and cultural…
Love a good scenic ride? No matter what you're into—history, art, food, or just incredible…
When it comes to traveling in Mexico, most people assume flying is the fastest way…
Argentina is a vast and diverse country, with thousands of kilometers of roads connecting unique…
Traveling offers a world of experiences, but the costs can quickly add up, turning planning…
As the warm weather approaches, it's time to start planning your summer getaway. Whether you're…
View Comments
The article in this forum is very good, glad to read your article. If you can, take a moment to play games a and b one of the hottest games
The quality and quantity of work produced in here is absolute informative.
How long does it take you to write an essay of this caliber? Finding material of this caliber is difficult.
Additionally, this method is used to add properties to the property list each time an event is sent.
This game Donkey Kong will last forever. No matter how much I play, it never bores me. still attracts my attention.
Best games free online!
Legaliteit
Over de legaliteit van online casino's in Nederland is lang gedebatteerd. Begin 2021 voerde het land echter eindelijk een wettelijk vergunningensysteem in voor de online goksector. Hierdoor voldoet het land aan de regelgeving van de Europese Unie.
De Nederlandse overheid heeft een strikte doorlichtingsprocedure ingesteld voor elke website die Nederlandse gokkers wil toelaten. Een vergunning van de Kansspelautoriteit is noodzakelijk voor een online casino om legaal in het land te opereren.
De regels voor online gokken zijn verdeeld in twee categorieën. De eerste heeft betrekking op sportweddenschappen, bingo en andere vormen van gokken. Deze worden aangeboden op basis van een semi-permanente exclusieve licentie. De tweede categorie omvat spellen als gokkasten, blackjack, baccarat en roulette.
Remote Config allows developers to define variables and values that can be changed on the fly, and then have those values fetched by the app at runtime.
I'm just like you, I've basically searched on google forever but still can't kind of find any information, does anyone for all intents and purposes know information that you can share with us, which mostly is fairly significant. thank yo, or so they mostly thought.
Actually this configuration is quite easy to adopt. We sometimes over-complicate things.