Firebase Remote Config | What is it?
Change the behavior and appearance of your app without publishing an app update.
Feature:
It’s a cloud service
A simple key-value store
Customize your app for segments of your user base (ex: A/B tests)
Docs: https://firebase.google.com/docs/remote-config/ (+ 3min video)
4. Firebase Remote Config | What is it?
Change the behavior and appearance of your app without publishing an app
update.
Feature:
● It’s a cloud service
● A simple key-value store
● Customize your app for segments of your user base (ex: A/B tests)
Docs: https://firebase.google.com/docs/remote-config/ (+ 3min video)
5. Firebase Remote Config | How it works?
● Open Firebase console https://console.firebase.google.com
● Choose or create a new project
● Select “Remote Config”
● Add/change/remove parameter
● Publish!
6. Firebase Remote Config | API architecture
● Singleton exposed to your app
● Default Config bundled with your
app
● Active Config for keep
consistency
● Fetched Config synced with FRC
console values
8. Firebase Remote Config | Configure project | 1/3
1) Add Firebase to your app
Add the dependency for Remote Config to your app-level build.gradle file as part of this step:
compile 'com.google.firebase:firebase-config:11.4.0'
2) Get the Remote Config singleton object
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance()
3) Set in-app default parameter values
using a Map object or an XML resource file stored in your app's res/xml folder
mFirebaseRemoteConfig.setDefaults(R.xml.remote_config_defaults);
9. Firebase Remote Config | Configure project | 2/3
Example of Default Config XML
<?xml version="1.0" encoding="utf-8"?>
<defaultsMap>
<entry>
<key>loading_phrase</key>
<value>Fetching config…</value>
</entry>
<entry>
<key>secretFeature1_enabled</key>
<value>false</value>
</entry>
</defaultsMap>
10. Firebase Remote Config | Configure project | 3/3
4) Get parameter values to use in your app
getBoolean(key) , getByteArray(key), getDouble(key), getLong(key), getString(key)
mFirebaseRemoteConfig.getBoolean("secretFeature1_enabled");
5) Fetch and activate values from the service (as needed)
● To fetch parameter values from the Remote Config service, call the fetch() method. Any values that you set in the
Remote Config service are fetched and cached in the Remote Config object.
● To make fetched parameter values available to your app, call the activateFetched() method.
12. Kotlin: Properties
Declaring Properties
val secretFeature1_enabled: Boolean = false
Properties: Getters and Setters
val secretFeature1_enabled: Boolean
get() = FirebaseRemoteConfig.getInstance().getBoolean("secretFeature1_enabled")
From code
if (secretFeature1_enabled) {
// do something …
}
13. Kotlin: Delegated Properties | 1/3
There are certain common kinds of properties, that, though we can implement
them manually every time we need them, would be very nice to implement once
and for all, and put into a library.
class Example {
val myProperty: String by MyDelegate()
}
14. Kotlin: Delegated Properties | 2/3
Define getValue() in your MyDelegate class.
class Example {
val myProperty: String by MyDelegate()
}
class MyDelegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
}
15. Kotlin: Delegated Properties | 3/3
Providing a delegate (since Koltin 1.1)
class Example {
val myProperty: String by MyDelegate()
}
class MyDelegate {
operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): ReadOnlyProperty<Any?, T> {
// init: check and create delegate
}
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
}
17. The Goal
Define a class with only properties and defaults
object FRC {
val signup_useHint by boolean(true)
val secretFeature1_enabled by boolean(false)
val logMaxLines by int(10)
}
18. The Goal | Singleton
Define a class with only properties and defaults
object FRC { // it’s a singleton!
val signup_useHint by boolean(true)
val secretFeature1_enabled by boolean(false)
val logMaxLines by int(10)
}
19. The Goal | Declare config name once
Define a class with only properties and defaults
object FRC {
val signup_useHint by boolean(true) // no need to declare string name!
val secretFeature1_enabled by boolean(false)
val logMaxLines by int(10)
}
20. The Goal | Static type-safe
Define a class with only properties and defaults
object FRC {
val signup_useHint by boolean(true) // it’s a type-safe!
val secretFeature1_enabled by boolean(false)
val logMaxLines by int(10)
}
21. The Goal | Declare default
Define a class with only properties and defaults
object FRC {
val signup_useHint by boolean(true) // has default!
val secretFeature1_enabled by boolean(false)
val logMaxLines by int(10)
}
22. The Goal | Easy to use
Define a class with only properties and defaults
object FRC {
val signup_useHint by boolean(true)
val secretFeature1_enabled by boolean(false)
val logMaxLines by int(10)
}
Easy to use in our code (with static type-safe)
if (FRC.secretFeature1_enabled) {
// do something ...
}
24. Build EasyFRC | Defaults for initialization
abstract class EasyFRC {
val _defaults = HashMap<String, Any?>()
}
25. Build EasyFRC | Auto setup for Firebase Remote Config
abstract class EasyFRC {
val _defaults = HashMap<String, Any?>()
val frc by lazy {
FirebaseRemoteConfig.getInstance().apply {
setDefaults(_defaults)
activateFetched()
fetch()
}
}
}
26. Build EasyFRC | Our Delegate Class
abstract class EasyFRC {
val _defaults = HashMap<String, Any?>()
val frc by lazy {
FirebaseRemoteConfig.getInstance().apply {
setDefaults(_defaults)
activateFetched()
fetch()
}
}
class FRCDelegate<T>(val defaultValue: T, val getMethod: (String) -> T) {
override fun getValue(thisRef: EasyFRC, property: KProperty<*>) = getMethod(property.name)
}
}
27. Build EasyFRC | Method for build Delegates | 1/2
abstract class EasyFRC {
val _defaults = HashMap<String, Any?>()
val frc by lazy {
FirebaseRemoteConfig.getInstance().apply {
setDefaults(_defaults)
activateFetched()
fetch()
}
}
fun string(defaultValue: String? = null) = FRCDelegate(defaultValue) { frc.getString(it) }
class FRCDelegate<T>(val defaultValue: T, val getMethod: (String) -> T) {
override fun getValue(thisRef: EasyFRC, property: KProperty<*>) = getMethod(property.name)
}
}
28. Build EasyFRC | Method for build Delegates | 2/2
abstract class EasyFRC {
// ...
fun string(defaultValue: String? = null) = FRCDelegate(defaultValue) { frc.getString(it) }
fun boolean(defaultValue: Boolean = false) = FRCDelegate(defaultValue) { frc.getBoolean(it) }
// ...
class FRCDelegate<T>(val defaultValue: T, val getMethod: (String) -> T) {
override fun getValue(thisRef: EasyFRC, property: KProperty<*>) = getMethod(property.name)
}
}
29. Build EasyFRC | provideDelegate() with Kotlin 1.1
abstract class EasyFRC {
// ...
fun string(defaultValue: String? = null) = FRCDelegate(defaultValue) { frc.getString(it) }
fun boolean(defaultValue: Boolean = false) = FRCDelegate(defaultValue) { frc.getBoolean(it) }
// ...
class FRCDelegate<T>(val defaultValue: T, val getMethod: (String) -> T) {
override fun getValue(thisRef: EasyFRC, property: KProperty<*>) = getMethod(property.name)
operator fun provideDelegate(thisRef: EasyFRC, property: KProperty<*>): FRCDelegate<T> {
thisRef._defaults.put(property.name, defaultValue)
return this
}
}
}
30. Build EasyFRC | The result!
object FRC : EasyFRC() {
// Basic example
val myBoolean by boolean(false)
val myInt by int(1337)
val myLong by long(134567890123456789)
val myDouble by double(0.0)
val myString by string("Ciao")
val myByteArray by byteArray(ByteArray(0))
// Real world examples
val signup_useHint by boolean(true)
val secretFeature1_enabled by boolean(false)
val secretFeature2_enabled by boolean(true)
val cache_expireMax by long(TimeUnit.DAYS.toSeconds(7))
val logMaxLines by int(10)
val logLevel by int(Log.INFO)
}
32. More complex example ...
Added support for: devMode, custom keys, fetch() and fetchAndActivate()
Full example: https://github.com/jacklt/jutils
Import as dependency (with JitPack)!
Gradle (v4 or later):
implementation 'com.github.jacklt.jutils:easyfrc:1.0.1'
or Gradle (before v4):
compile 'com.github.jacklt.jutils:easyfrc:1.0.1'