Skip to main content

SDK Remote Config for Unreal Engine (version 1.0.0)

SDK Remote Config is a cloud-based service that lets you change application behaviour and appearance without requiring users to download an application update. The plugin encapsulates configuration request from server, caching, background update. It also offers easy-to-use APIs for data retrieval.

Implementation example

Take a look at example app to learn how to implement SDK Remote Config.

Key features

Connecting to project

  1. Copy the plugin project from the official RuStore repository on GitFlic;

  2. Open the Android project from the unreal_plugin_libraries folder in your IDE.

  3. Use the gradle assemble command to assemble the project.

If the build is successful, files will be created in unreal_example/plugins/RuStoreRemoteConfig/source/RuStoreRemoteConfig/thirdparty/Android/libs and unreal_example/plugins/RuStoreCore/source/RuStoreCore/thirdparty/Android/libs directories:

  • RuStoreUnityRemoteConfigClient.aar;
  • RuStoreUnityCore.aar.
  1. Save the contents of unreal_example /Plugins folder to the Plugins folder inside your project. Restart Unreal Engine.

  2. In the list of plugins (Edit - Plugins - Project - Mobile) tick the plugins "RuStoreRemoteConfig" and "RuStoreCore".

  3. Connect RuStoreCore and RuStoreRemoteConfig modules in the YourProject.Build.cs file in the PublicDependencyModuleNames list.

  4. In the project settings (Edit → Project Settings → Android) set:

    • Minimum SDK Version24 or later.
    • Target SDK Version31 or later.

Initialization

RemoteConfigClient creation

RemoteConfigClient initialization must be done during Application.onCreate() as by the background sync start the SDK must be already initialized.

To initialise RemoteConfigClient, perform an extension to the GameApplication class and add the following code to onCreate:

Инициализация в Application
package com.example.RuStoreRemoteConfigApp;

import android.content.Context;
import com.epicgames.ue4.GameApplication;
import ru.rustore.unitysdk.remoteconfigclient.model.UnityUpdateBehaviour;
import ru.rustore.unitysdk.remoteconfigclient.RuStoreUnityRemoteConfigClient;

public class RuStoreRemoteConfigApplication extends GameApplication {

public final String APP_ID = "a83c91d3-21b4-4891-841e-0ed0fc39a562";
public final int UPDATE_TIME = 15;
public final String UPDATE_BEHAVIOUR = "Actual";

@Override
public void onCreate() {
super.onCreate();

RuStoreUnityRemoteConfigClient.INSTANCE.init(APP_ID, UPDATE_TIME, UPDATE_BEHAVIOUR, null, null, getApplicationContext());
}
}

To replace the GameApplication class with RuStoreRemoteConfigApplication in your project's manifest file, use the Unreal Plugin Language functionality.

Пример UPL.xml
<prebuildCopies>
<copyDir src="$S(PluginDir)/Java" dst="$S(BuildDir)/src/com/example/RuStoreRemoteConfigApp" />
</prebuildCopies>

<androidManifestUpdates>
<addAttribute tag="application" name="android:name" value="com.example.RuStoreRemoteConfigApp.RuStoreRemoteConfigApplication" />
</androidManifestUpdates>

UpdateBehaviour

UpdateBehaviour— this parameter defines SDK behavior. The default value of the RemoteConfigClientBuilder instance upon creation is UpdateBehaviour.Defaultwith a 15 minute sync interval.

Differences in the values of UpdateBehaviour

UpdateBehaviourDescription

Actual

With this type of initialization, **every ** configuration request is made by a request to the server.

The ** Actualupdate type ensures the configuration is up to date, however, the speed of the configuration retrieval will depend on the network speed.**

This type of initialization cancels the background update.

Default

With this type of initialization, the configuration request is made from the local store that is updated at specified intervals.

If it is the first initialization (the local store is empty), a request to the server is made. Theduration of this request depends on the network speed. Configuration access will wait for the initialization to complete.

The Default configuration does not guarantee that during the process lifetime configuration retrieval will return the same result, as there can be configuration sync in the background.

This initialization type starts background update.

Snapshot

With this type of initialization, the configuration request is made from the local inMemory storage. inMemory-storage will receive the result of the request from the permanent store and save it until the end of the process lifetime.

If it is the first initialization (the local store is empty), a request to the server is made. Theduration of this request depends on the network speed. Configuration access will wait for the initialization to complete.

The Snapshotconfiguration ensures that during the process lifetime configuration retrieval will return the same result.

This initialization type starts background update.

Initialization in C++ and Blueprint

To access SDK methods from C++ and Blueprint, initialise the plugin using the Init method.

Вызов метода Init
URuStoreRemoteConfigClient::Instance()->Init();

All operations with URuStorePushClient are also accessible from Blueprints. Initialization example:

img

Deinitialization

The object is bound to the scene root by calling the Init method for URuStoreRemoteConfigClient. If no further work with the objects is needed, run the Dispose method to free memory. Dispose method call unties the objects from root and securely complete all sent requests.

Вызов метода Dispose
URuStoreRemoteConfigClient::Instance()->Dispose();
img

Optional initialization parameters

You can set optional initialisation parameters via the RemoteConfigClientParameters interface.

Интерфейс RemoteConfigClientParameters
public interface RemoteConfigClientParameters {
String getAppBuild();
String getAppVersion();
String getDeviceId();
String getDeviceModel();
String getEnvironment();
String getOsVersion();
}

Via the setAccount and setLanguage methods, you may set additional parameters that can be used to obtain a specific configuration.

The setAccount and setLanguage methods can be called at any time.

Инициализация с опциональными параметрами
public final String APP_ID = "a83c91d3-21b4-4891-841e-0ed0fc39a562";
public final int UPDATE_TIME = 15;
public final String UPDATE_BEHAVIOUR = "Actual";
public final String ACCOUNT = "MyAccount";
public final String LANGUAGE = "ru";

RemoteConfigClientParametersImpl parameters;

/* Your initialisation parameters */

RuStoreUnityRemoteConfigClient.INSTANCE.setAccount(ACCOUNT);
RuStoreUnityRemoteConfigClient.INSTANCE.setLanguage(LANGUAGE);
RuStoreUnityRemoteConfigClient.INSTANCE.init(APP_ID, UPDATE_TIME, UPDATE_BEHAVIOUR, parameters, null, getApplicationContext());
ParametersDescription
OsVersionCondition in the configuration tool: Os Version
Allows to compare OsVersion against the value set in the interface. By default OsVersion is not passed, in this case the default configuration will be returned.
DeviceModelCondition in the configuration tool: Device Model
Allows to compare DeviceModel against the value set in the interface. By default DeviceModel is not passed, in this case the default configuration will be returned.
LanguageCondition in the configuration tool: Language
Allows to compare Language against the value set in the interface. By default Language is not passed, In this case the default configuration will be returned.

To pass Language, implement ConfigRequestParameterProvider.
AccountCondition in the configuration tool: Account
Allows to compare account against the value set in the interface.
**
Condition in the configuration tool: Account Percentile**
Allows to broadcast the configuration to a specified percent of users based on the account value.

Condition in the configuration tool: Interval Account Percentile
Allows to broadcast the configuration to a specified percent of users on a specified day based on the account value.

To pass Account, implement ConfigRequestParameterProvider.
DeviceIdCondition in the configuration tool: DeviceID
Allows to compare DeviceId againste the value set in the interface.
**
Condition in the configuration tool: DeviceID Percentile**
Allows to broadcast the configuration to a specified percent of devices based on a on the DeviceId value.
**
Condition in the configuration tool: Interval DeviceID Percentile**
Allows to broadcast the configuration to a specified percent of devices on a specified day based on the DeviceId value.
AppVersionCondition in the configuration tool: App Version
Allows to compare AppVersion against the value set in the interface.
EnvironmentCondition in the configuration tool: App Environment
Allows to compare Environment with the value set in the interface
Environment can take the following values: Alpha, Beta, Release.
It is a convenient parameter for testing of the configuration on different app builds.
AppBuildCondition in the configuration tool: App Build
Allows to compare AppBuild against the value set in the interface.

ConfigRequestParameterProvider

ConfigRequestParameterProvider implementation allows to dynamically pass parameters to the server for configuration sync.

Supported parameters: Language and Account.

Initialization

To access the ConfigRequestRequestParameterProvider methods from C++ and Blueprint, initialise the URuStoreConfigRequestParameterProvider using the Init method.

URuStoreConfigRequestParameterProvider::Instance()->Init();
img

Deinitialization

Calling the Init method for URuStoreConfigRequestParameterProvider binds the object to the scene root. If no further work with the objects is needed, run the Dispose method to free memory. Dispose method call unties the objects from root and securely complete all sent requests.

URuStoreConfigRequestParameterProvider::Instance()->Dispose();
img

Passed parameters

You can dynamically set ConfigRequestParameterProvider parameters via SetAccount and SetLanguage methods:

Вызов методов SetAccount и SetLanguage
URuStoreConfigRequestParameterProvider::Instance()->SetAccount("MyAccount");
URuStoreConfigRequestParameterProvider::Instance()->SetLanguage("ru");
img img

Get the current ConfigRequestParameterProvider parameters using GetAccount and GetLanguage methods:

FString account = URuStoreConfigRequestParameterProvider::Instance()->GetAccount();
FString language = URuStoreConfigRequestParameterProvider::Instance()->GetLanguage();
img img

RemoteConfigClientEventListener

RemoteConfigClientEventListener implementation allows to receive callbacks on SDK performance, such as end of initialization and permanent storage updates..

Initialization

To access the RemoteConfigClientEventListener methods from C++ and Blueprint, initialise the URuStoreConfigRequestParameterProvider using the Init method.

URuStoreRemoteConfigClientEventListener::Instance()->Init();

All operations on URuStoreRemoteConfigClientEventListener object are also available from Blueprints. Initialization example:

img

Deinitialization

Calling the Init method for URuStoreRemoteConfigClientEventListener binds the object to the scene root. When you are finished working with the object, call the Dispose method to release the memory. Dispose method call unties the objects from root and securely complete all sent requests.

URuStoreRemoteConfigClientEventListener::Instance()->Dispose();
img

Callbacks

Callback list (callbacks):

Subscribing to the following URuStoreRemoteConfigClientEventListener events gives you the ability to receive callbacks about SDK activity, such as completing initialisation and updating persistent storage, etc:

  • OnBackgroundJobErrors — returns a background operation error.
  • OnFirstLoadComplete — called once the first load is complete.
  • OnInitComplete — called when initialisation is complete.
  • OnMemoryCacheUpdated — called when memory cache is changed.
  • OnPersistentStorageUpdated — called when on-going storage is changed.
  • OnRemoteConfigNetworkRequestFailure — called when a Remote Config network request fails.
События URuStoreRemoteConfigClientEventListener
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRemoteConfigClientEventBackgroundJobErrorsDelegate, int64, requestId, FString, exception);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRemoteConfigClientEventFirstLoadCompleteDelegate, int64, requestId);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRemoteConfigClientEventInitCompleteDelegate, int64, requestId);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRemoteConfigClientEventMemoryCacheUpdatedDelegate, int64, requestId);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRemoteConfigClientEventPersistentStorageUpdatedDelegate, int64, requestId);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FRemoteConfigClientEventRemoteConfigNetworkRequestFailureDelegate, int64, requestId, FString, throwable);

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventBackgroundJobErrorsDelegate OnBackgroundJobErrors;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventFirstLoadCompleteDelegate OnFirstLoadComplete;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventInitCompleteDelegate OnInitComplete;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventMemoryCacheUpdatedDelegate OnMemoryCacheUpdated;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventPersistentStorageUpdatedDelegate OnPersistentStorageUpdated;

UPROPERTY(BlueprintAssignable, Category = "RuStore RemoteConfigClientEvent Listener")
FRemoteConfigClientEventRemoteConfigNetworkRequestFailureDelegate OnRemoteConfigNetworkRequestFailure;
Подписка на событие слушателя
FScriptDelegate OnBackgroundJobErrorsDelegate;
FScriptDelegate OnFirstLoadCompleteDelegate;
FScriptDelegate OnInitCompleteDelegate;
FScriptDelegate OnMemoryCacheUpdatedDelegate;
FScriptDelegate OnPersistentStorageUpdatedDelegate;
FScriptDelegate OnRemoteConfigNetworkRequestFailureDelegate;

Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnBackgroundJobErrorsCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnFirstLoadCompleteCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnInitCompleteCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnMemoryCacheUpdatedCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnPersistentStorageUpdatedCallback"));
Delegate.BindUFunction(YourHandlerUObjectPtr, FName("OnRemoteConfigNetworkRequestFailureCallback"));

URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnBackgroundJobErrorsCallbackDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnFirstLoadCompleteDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnInitCompleteDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnMemoryCacheUpdatedDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnPersistentStorageUpdatedDelegate);
URuStoreRemoteConfigClientEventListener::Instance()->OnBackgroundJobErrors.Add(OnRemoteConfigNetworkRequestFailureDelegate);
Методы обработчика обратных вызовов
UFUNCTION()
void OnBackgroundJobErrorsCallback(int64 requestId, FString exception) {
// Process callback
}

UFUNCTION()
void OnFirstLoadCompleteCallback(int64 requestId) {
// Process callback
}

UFUNCTION()
void OnInitCompleteCallback(int64 requestId) {
// Process callback
}

UFUNCTION()
void OnMemoryCacheUpdatedCallback(int64 requestId) {
// Process callback
}

UFUNCTION()
void OnPersistentStorageUpdatedCallback(int64 requestId) {
// Process callback
}

UFUNCTION()
void OnRemoteConfigNetworkRequestFailureCallback(int64 requestId, FString throwable) {
// Process callback
}
img

Getting configuration

Call to GetRemoteConfig to obtain configuration.


Each GetRemoteConfig request returns requestId that is unique within a single application run. Each event returns the requestId of the request that triggered the event.

Вызов метода GetRemoteConfig
long requestId = URuStoreRemoteConfigClient::Instance()->GetRemoteConfig(
[](long requestId, TSharedPtr<FURuStoreRemoteConfig, ESPMode::ThreadSafe> response)
// Process success
},
[](long requestId, TSharedPtr<FURuStoreError, ESPMode::ThreadSafe> error) {
// Process error
}
);
img
  • The Success callback returns a FURuStoreRemoteConfig structure with information about the current dataset in Response parameter.

  • The Failure callback returns a FURuStoreError structure with error information in Error. All errors are described in Error Handling.

FURuStoreRemoteConfig structure

The FURuStoreRemoteConfig instance is the current set of all data received depending on the update policy selected at initialisation. The instance has the full set of keys transferred from the server. This depends on the parameters specified at initialisation.

Структура FURuStoreRemoteConfig
USTRUCT(BlueprintType)
struct RUSTOREREMOTECONFIG_API FURuStoreRemoteConfig
{
GENERATED_USTRUCT_BODY()

public:
UPROPERTY(BlueprintReadOnly)
TMap<FString, FString> data;
};

Possible errors

It is not recommended to display the error to the user if you get Failure in response. Showing an error can negatively impact the user experience.

Структура FURuStoreError
USTRUCT(BlueprintType)
struct RUSTORECORE_API FURuStoreError
{
GENERATED_USTRUCT_BODY()

FURuStoreError()
{
name = "";
description = "";
}

UPROPERTY(BlueprintReadOnly)
FString name;

UPROPERTY(BlueprintReadOnly)
FString description;
};
  • name — error name. Contains simpleName of the error class.
  • description — error message.
ErrorDescription
BackgroundConfigUpdateErrorDisplayed if an error occurs during background synchronisation.
FailedToReceiveRemoteConfigDisplayed in case of an error when calling the get configuration method.
RemoteConfigCastExceptionDisplayed if the key data from the RemoteConfig class was retrieved incorrectly. The error may be caused by an impossible type conversion or null key value.
RemoteConfigClientAlreadyExistDisplayed if RemoteConfigClient is recreated within the life of the process.
RemoteConfigClientNotCreatedDisplayed if RemoteConfigClient is accessed via the instance static field before RemoteConfigClient is created.
RemoteConfigCommonExceptionGeneral unexpected error
RemoteConfigNetworkExceptionDisplayed in case of a network error.