Third party remote configuration provider integration is currently in private beta and will be available in the next major release of Appfigurate.
Check your third party remote configuration provider APIs for compatibility
The third party remote configuration providers' read-property function(s) must return a value synchronously (cached or default value):
✓ Pseudocode examples - ok
// ok - returns value immediately
var value = thirdPartyRemoteProvider.getBooleanValue("alwaysDarkMode");
// ok - returns value immediately
var value = thirdPartyRemoteProvider.getBooleanValue("alwaysDarkMode", false);
If your third party remote configuration provider's read-property function(s) are marked async, or take a callback/lambda/delegate, then it is incompatible with Appfigurate Library:
✗ Pseudocode examples - incompatible third party remote provider
// not compatible - asynchronous
var value = await thirdPartyRemoteProvider.getBooleanValue("alwaysDarkMode");
// not compatible - callback
thirdPartyRemoteProvider.getBooleanValue("alwaysDarkMode") { value in
...
};
Also check if your third party remote configuration provider has `snapshot` APIs, which should allow synchronous access to a 'snapshot in time' of remote properties (e.g. ConfigCat).
Once you've confirmed your third party remote provider has the required synchronous read-property function(s), you can start integration.
Integration of third party remote configuration providers
Using Appfigurate remote properties instead of your third party remote configuration provider APIs directly allows for the following:
locally change third party remote configuration provider properties without affecting your entire customer base.
compile time type safety - Appfigurate remote properties are typed, third party remote configuration provider properties are not.
avoids hardcoding duplicated property names throughout your app.
avoids hardcoding duplicated default values throughout your app.
deleting a property from your third party remote configuration provider Console won't affect existing apps, they'll continue to use the default value provided in the reset method.
We assume you already have Appfigurate Library and your third party remote provider integrated into your app with the following example remote properties created in the third party remote provider's Console:
Remote property key
Remote property type
alwaysDarkMode
boolean
appTitle
string
bookingDuration
integer
fontSize
double
Add remote properties into your Configuration subclass
Update your configuration subclass to include your remote configuration properties. Provide default values for the properties in the overridden reset method. See also Supported property types.
Swift Configuration example
import Foundation
import AppfigurateLibrary
@objcMembers class MyConfiguration: APLConfiguration {
...
@RemoteBoolProperty(remoteKey: "alwaysDarkMode", description: "Force dark mode to be always set")
var alwaysDarkMode: Bool
@RemoteStringPropertyEdit(remoteKey: "appTitle", description: "Title of application")
var appTitle: String
@RemoteIntPropertyEdit(remoteKey: "bookingDuration", description: "Duration (days) for reservation bookings")
var bookingDuration: Int
@RemoteDoublePropertyEdit(remoteKey: "fontSize", description: "Size of font throughout app")
var fontSize: Double
...
override func reset() {
alwaysDarkMode = false
appTitle = "Holiday finder"
bookingDuration = 30
fontSize = 13.0
}
...
}
#import "MyConfiguration.h"
@implementation MyConfiguration
...
REMOTE_BOOL_PROPERTY(alwaysDarkMode, @"alwaysDarkMode", @"Force dark mode to be always set");
REMOTE_STRING_PROPERTY_EDIT(appTitle, @"appTitle", @"Title of application");
REMOTE_INT_PROPERTY_EDIT(bookingDuration, @"bookingDuration", @"Duration (days) for reservation bookings");
REMOTE_DOUBLE_PROPERTY_EDIT(fontSize, @"fontSize", @"Size of font throughout app");
...
- (void) reset {
self.alwaysDarkMode = NO;
self.appTitle = @"Holiday finder";
self.bookingDuration = 30;
self.fontSize = 13.0;
}
...
@end
Kotlin Configuration example
package com.yourcompany.yourapp
import nz.co.electricbolt.appfiguratelibrary.annotations.RemoteBooleanProperty
import nz.co.electricbolt.appfiguratelibrary.annotations.RemoteDoublePropertyEdit
import nz.co.electricbolt.appfiguratelibrary.annotations.RemoteIntPropertyEdit
import nz.co.electricbolt.appfiguratelibrary.annotations.RemoteStringPropertyEdit
class MyConfiguration : nz.co.electricbolt.appfiguratelibrary.Configuration() {
...
@RemoteBooleanProperty(remoteKey = "alwaysDarkMode", description = "Force dark mode to be always set")
var alwaysDarkMode: Boolean = false
@RemoteStringPropertyEdit(remoteKey = "appTitle", description = "Title of application")
var appTitle: String? = null
@RemoteDoublePropertyEdit(remoteKey = "fontSize", description = "Size of font throughout app")
var fontSize: Double = 0.0
@RemoteIntPropertyEdit(remoteKey = "bookingDuration", description = "Duration (days) for reservation bookings")
var bookingDuration: Int = 0
...
override fun reset() {
alwaysDarkMode = false
appTitle = "Holiday finder"
bookingDuration = 30
fontSize = 13.0
}
}
Java Configuration example
package com.yourcompany.yourapp;
import nz.co.electricbolt.appfiguratelibrary.annotations.RemoteBooleanProperty;
import nz.co.electricbolt.appfiguratelibrary.annotations.RemoteDoublePropertyEdit;
import nz.co.electricbolt.appfiguratelibrary.annotations.RemoteIntPropertyEdit;
import nz.co.electricbolt.appfiguratelibrary.annotations.RemoteStringPropertyEdit;
public class MyConfiguration extends nz.co.electricbolt.appfiguratelibrary.Configuration {
...
@RemoteBooleanProperty(remoteKey = "alwaysDarkMode", description = "Force dark mode to be always set")
public boolean alwaysDarkMode;
@RemoteStringPropertyEdit(remoteKey = "appTitle", description = "Title of application")
public String appTitle;
@RemoteDoublePropertyEdit(remoteKey = "fontSize", description = "Size of font throughout app")
public double fontSize;
@RemoteIntPropertyEdit(remoteKey = "bookingDuration", description = "Duration (days) for reservation bookings")
public int bookingDuration;
...
@Override
public void reset() {
alwaysDarkMode = false;
appTitle = "Holiday finder";
bookingDuration = 30;
fontSize = 13.0;
}
...
}
Provide remote configuration values to Appfigurate Library when requested
Appfigurate Library needs to be able to read the current remote configuration values from your third party remote configuration provider.
If your third party remote configuration provider's read-property function(s) have a default value parameter, then Appfigurate Library passes across the correct default value of the remote property to the callback:
Pseudocode example
// add the following function call before initializing the third party remote provider.
APLFetchRemoteConfiguration { propertyKey, propertyType, defaultValue in
if (propertyType == RemotePropertyTypeBool) {
return this.thirdPartyRemoteProvider.getBooleanValue(propertyKey, defaultValue as Boolean);
} else if (propertyType == RemotePropertyTypeInt) {
return this.thirdPartyRemoteProvider.getIntegerValue(propertyKey, defaultValue as Int);
} else if (propertyType == RemotePropertyTypeDouble {
return this.thirdPartyRemoteProvider.getDoubleValue(propertyKey, defaultValue as Double);
} else // RemotePropertyTypeString {
return this.thirdPartyRemoteProvider.getStringValue(propertyKey, defaultValue as String);
}
};
...
// initialize the third party remote provider
this.thirdPartyRemoteProvider = ThirdPartyRemoteProvider.initAndConfigure("1fa0b704-8e22-4314");
If your third party remote configuration provider's read-property function(s) doesn't have a default value parameter, then it will likely require default values to be set at the start of your app. (e.g. Firebase does, Launch Darkly doesn't).
We recommend you use the default values set in the reset method of your configuration subclass. You can get the default values using the remoteDefaults method, which returns a Dictionary of property key/value pairs:
Pseudocode example
// add the following function call before initializing the third party remote provider.
APLFetchRemoteConfiguration { propertyKey, propertyType, defaultValue in
if (propertyType == RemotePropertyTypeBool) {
return this.thirdPartyRemoteProvider.getBooleanValue(propertyKey);
} else if (propertyType == RemotePropertyTypeInt) {
return this.thirdPartyRemoteProvider.getIntegerValue(propertyKey);
} else if (propertyType == RemotePropertyTypeDouble) {
return this.thirdPartyRemoteProvider.getDoubleValue(propertyKey);
} else { // RemotePropertyTypeString
return this.thirdPartyRemoteProvider.getStringValue(propertyKey);
}
};
...
// initialize third party remote provider
this.thirdPartyRemoteProvider = ThirdPartyRemoteProvider.initAndConfigure("1fa0b704-8e22-4314");
...
// initialize third party remote provider default values
var defaults = APLConfiguration.shared().remoteDefaults();
this.thirdPartyRemoteProvider.setDefaultBooleanValue(forKey: "alwaysDarkMode", value: defaults["alwaysDarkMode"]);
this.thirdPartyRemoteProvider.setDefaultIntegerValue(forKey: "bookingDuration", value: defaults["bookingDuration"]);
...
Notify Appfigurate Library when the third party remote configuration provider has received remote config
We need to tell Appfigurate Library that third party remote configuration provider has received remote configuration, so that it can keep your Configuration subclass remote properties in sync.
Pseudocode example
remoteProvider.setOnFetchCallback { status, error in
if (status == .receivedConfiguration) {
...
APLFlushRemoteConfiguration(); // add this line
}
}
Best practice and usage
Replace all calls to your third party remote configuration providers read-property function(s):
Pseudocode example
if (remoteProvider.getBooleanValue("alwaysDarkMode", defaultValue: false) {
...
with the following:
Pseudocode example
if (APLConfiguration.shared().alwaysDarkMode) {
...