Android project requirements
System requirements:- minSdk = 26 (Android 8.0)
- compileSdk = 35
- Android Gradle Plugin 8.11.0
- Gradle 8.14.2
- Kotlin 2.2.0
Installing the library
- Add the maven repository in your project’s
settings.gradle.kts
file:
- Add the library as a dependency in your
app/build.gradle.kts
file:
Library dependencies
Impactful dependencies:- Android Core KTX 1.16.0
- Android Activity Compose 1.10.1
- Compose BOM 2025.06.01
- Accompanist Permissions 0.37.3
- Kotlin Coroutines 1.10.2
- Compose Navigation 2.9.1
- Android Lifecycle 2.9.1
- Android Core Library Desugaring 2.1.5
- OkHttp BOM 4.12.0
- Retrofit 2.12.0
- Moshi 1.15.2
- Coil BOM 3.2.0
Public API
The SDK library is managed through theFlowx
singleton instance, which exposes the following methods:
Name | Description | Definition |
---|---|---|
init | Initializes the FlowX SDK. Must be called in your application’s onCreate() | fun init(context: Context, config: Config, customComponentsProvider: CustomComponentsProvider? = null, customStepperHeaderProvider: CustomStepperHeaderProvider? = null, customLoaderProvider: CustomLoaderProvider? = null, analyticsCollector: AnalyticsCollector? = null, onNewProcessStarted: NewProcessStartedHandler.Delegate? = null) |
setAccessToken | Updates the access token | fun setAccessToken(accessToken: String?) |
setupTheme | Sets up the theme to be used when rendering a process | fun setupTheme(workspaceUuid: String, appearance: ThemeAppearance = ThemeAppearance.LIGHT, themeUuid: String, fallbackThemeJsonFileAssetsPath: String? = null, @MainThread onCompletion: () -> Unit) |
changeLocaleSettings | Changes the current locale settings (i.e. locale and language) | fun changeLocaleSettings(locale: Locale, language: String) |
startProcess | Starts a FlowX process instance, by returning a @Composable function where the process is rendered. | fun startProcess(workspaceId: String, projectId: String, processName: String, params: JSONObject = JSONObject(), isModal: Boolean = false, onProcessEnded: (() -> Unit)? = null, closeModalFunc: (CloseModalProcessScope.(processName: String) -> Unit)? = null): @Composable () -> Unit |
continueProcess | Continues an existing FlowX process instance, by returning a @Composable function where the process is rendered. | fun continueProcess(processUuid: String, isModal: Boolean = false, onProcessEnded: (() -> Unit)? = null, closeModalFunc: (CloseModalProcessScope.(processName: String) -> Unit)? = null): @Composable () -> Unit |
Configuring the library
To configure the SDK, there are two things needed in the project’s application class:- first, make it implement the
FlowxOwner
interface:
- then, call the
init
method inside theonCreate()
method:
Parameters
Name | Description | Type | Requirement |
---|---|---|---|
context | Android application Context | Context | Mandatory |
config | SDK configuration parameters | ai.flowx.android.sdk.api.Config | Mandatory |
customComponentsProvider | Provider for the @Composable custom components | ai.flowx.android.sdk.api.custom.components.CustomComponentsProvider? | Optional. Defaults to null . |
customStepperHeaderProvider | Provider for the @Composable custom stepper header view | ai.flowx.android.sdk.api.custom.stepper.CustomStepperHeaderProvider? | Optional. Defaults to null . |
customLoaderProvider | Provider for the @Composable custom loader view | ai.flowx.android.sdk.api.custom.loader.CustomLoaderProvider? | Optional. Defaults to null . |
analyticsCollector | Collector interface for SDK analytics events | ai.flowx.android.sdk.api.analytics.AnalyticsCollector | Optional. Defaults to null . |
onNewProcessStarted | Callback for when a new process was started as a consequence for executing a START_PROJECT action | ai.flowx.android.sdk.api.NewProcessStartedHandler.Delegate | Optional. Defaults to null . |
custom components
implementation is explained in its own section.• The implementation for providing a
custom view for the header
of the Stepper component is detailed in its own section.• The implementation for providing a
custom loader
is explained in its own section.• Collecting analytics events from the SDK is explained in its own section.
• Handling the start of a new process while in a running process is explained in its own section.
Sample
Config
data for the config
parameter above are:
Name | Description | Type | Requirement |
---|---|---|---|
baseUrl | URL to connect to the FlowX back-end environment | String | Mandatory |
imageBaseUrl | URL to connect to the FlowX Media Library module of the CMS | String | Mandatory |
enginePath | URL path segment used to identify the process engine service | String | Mandatory |
language | The language used for retrieving enumerations and substitution tags | String | Optional. Defaults to en . |
locale | The locale used for date, number and currency formatting | java.util.Locale | Optional. Defaults to Locale.getDefault() |
validators | Custom validators for form elements | Map<String, (String) -> Boolean>? | Optional. |
logEnabled | Flag indicating if logs should be printed | Boolean | Optional. Defaults to false |
Custom validators
Thecustom validators
map is a collection of lambda functions, referenced by name (i.e. the value of the key
in this map), each returning a Boolean
based on the String
which needs to be validated.
For a custom validator to be evaluated for a form field, its name must be specified in the form field process definition.
By looking at the example from above:if a form element should be validated using this lambda function, a custom validator named
"exact_25_in_length"
should be specified in the process definition.Using the library
Authentication
To be able to use the SDK, authentication is required. Therefore, before calling any other method on the singleton instance, make sure that the access token is set by calling:Whenever the access token changes based on your own authentication logic, it must be updated in the renderer by calling the
setAccessToken
method again.Passing
null
or empty string (""
) as an argument to the setAccessToken
method clears the tokenTheming
Prior setting up the theme, make sure the
Check the authentication section for details.
access token
was set.Check the authentication section for details.
suspend
-ing setupTheme(...)
method over the singleton instance of the SDK:
Parameters
Name | Description | Type | Requirement |
---|---|---|---|
workspaceUuid | UUID string identifier of the workspace that contains the theme to be loaded | String | Mandatory. Should not be empty |
themeUuid | UUID string of the theme configured in FlowX Designer | String | Mandatory. Can be empty |
fallbackThemeJsonFileAssetsPath | Android asset relative path to the corresponding JSON file to be used as fallback, in case fetching the theme fails and there is no cached version available | String? | Optional. Defaults to null |
appearance | Indicator for the appearance of the theme (LIGHT, DARK) | Flowx.ThemeAppearance | Options. Defaults to Flowx.ThemeAppearance.LIGHT |
onCompletion | @MainThread invoked closure, called when setting up the theme completes | () -> Unit | Mandatory |
If the
If the
themeUuid
parameter value is empty (""
), no theme will be fetched, and the mechanism will rely only on the fallback file, if set.If the
fallbackThemeJsonFileAssetsPath
parameter value is null
, there will be no fallback mechanism set in place, meaning if fetching the theme fails, the redered process will have no style applied over it’s displayed components.The SDK caches the fetched themes, so if a theme fetch fails, a cached version will be used, if available. Otherwise, it will use the file given as fallback.
Sample
The
fallbackThemeJsonFileAssetsPath
always search for files under your project’s assets/
directory, meaning the example parameter value is translated to file://android_asset/theme/a_fallback_theme.json
before being evaluated.Changing current locale settings
The currentlocale
and language
can be also changed after the initial setup, by calling the changeLocaleSettings
function:
Parameters
Name | Description | Type | Requirement |
---|---|---|---|
locale | The new locale | java.util.Locale | Mandatory |
language | The code for the new language | String | Mandatory |
Sample
The
More information regarding the standard can be found by reading RFC 4647 “Matching of Language Tags” and RFC 5646 “Tags for Identifying Languages”.
An example of BCP 47 is
Locale
satisfies the IETF BCP 47 standard for representing language and country/region codes.More information regarding the standard can be found by reading RFC 4647 “Matching of Language Tags” and RFC 5646 “Tags for Identifying Languages”.
An example of BCP 47 is
en-US
(language code en
and country US
).Start a FlowX process
Prior starting a process, make sure the authentication and theming were correctly set up
startProcess
function:
Parameters
Name | Description | Type | Requirement |
---|---|---|---|
workspaceId | The id of the workspace that contains the project and process to be started | String | Mandatory |
projectId | The id of the project containing the process to be started | String | Mandatory |
processName | The name of the process | String | Mandatory |
params | The starting params for the process, if any | JSONObject | Optional. If omitted, if defaults to JSONObject() |
isModal | Flag indicating whether the process can be closed at anytime by tapping the top-right close button | Boolean | Optional. It defaults to false . |
onProcessEnded | Lambda function where you can do additional processing when the started process ends | (() -> Unit)? | Optional. It defaults to null . |
closeModalFunc | Lambda function where you should handle closing the process when isModal flag is true | (CloseModalProcessScope.(processName: String) -> Unit)? | Optional. It defaults to null . |
The returned @Composable function must be included in its own Activity, which is part of (controlled and maintained by) the container application.
This wrapper activity must display only the
This wrapper activity must display only the
@Composable
returned from the SDK (i.e. it occupies the whole activity screen space).Sample
Resume a FlowX process
Prior resuming process, make sure the authentication and theming were correctly set up
continueProcess
function:
Parameters
Name | Description | Type | Requirement |
---|---|---|---|
processUuid | The UUID string of the process | String | Mandatory |
isModal | Flag indicating whether the process can be closed at anytime by tapping the top-right close button | Boolean | Optional. It defaults to false . |
onProcessEnded | Lambda function where you can do additional processing when the continued process ends | (() -> Unit)? | Optional. It defaults to null . |
closeModalFunc | Lambda function where you should handle closing the process when isModal flag is true | (CloseModalProcessScope.(processName: String) -> Unit)? | Optional. It defaults to null . |
The returned @Composable function must be included in its own Activity, which is part of (controlled and maintained by) the container application.
This wrapper activity must display only the
This wrapper activity must display only the
@Composable
returned from the SDK (i.e. it occupies the whole activity screen space).Sample
closeModalFunc
parameter
The closeModalFunc
parameter is a function defined within the CloseModalProcessScope
context.
This gives the ability to query for substitution tags or media library items in order to use them when handling this callback (i.e. showing an snackbar or an alert).
Get a substitution tag value by key
CustomComponentScope
context, using the method above, by providing the key
.
It returns:
- the key’s counterpart, if the
key
is valid and found - the empty string, if the
key
is valid, but not found - the unaltered string, if the key has the wrong format (i.e. not starting with
@@
)
Get a media item url by key
CustomComponentScope
context, using the method above, by providing the key
.
It returns the URL
string of the media resource, or null
, if not found.
Sample
Custom components
The container application should decide which custom component view to provide using thecomponentIdentifier
configured in the UI designer.
A custom component receives data
to populate the view and actions
available to execute, as described below.It can also be validated and provide data back into the process when executing an action. To handle custom components, an implementation of the
CustomComponentsProvider
interface should be passed as a parameter when initializing the SDK:
Sample
CustomComponent
The implementation for providing a custom component is based on creating and binding a user defined @Composable function, through theCustomComponent
interface:
The value for the
data
parameter received in the populateUi(data: Any?)
could be:Boolean
String
java.lang.Number
org.json.JSONObject
org.json.JSONArray
Both validation and providing data back into process are optional, and, based on the needs, it may be included in the implementation or not.
CustomComponentScope
Thecomposable
property of the CustomComponent is a @Composable function which may be defined and run only within the context of a CustomComponentScope
receiver.
Execute action
The custom components which the container app provides may contain FlowX actions available for execution.These actions are received through the
actions
parameter of the populateUi(actions: Map<String, CustomComponentAction>)
method.In order to run an action (i.e. on a click of a button in the custom component) you need to call the
executeAction
method, through the CustomComponentScope
context:
Parameters
Name | Description | Type | Requirement |
---|---|---|---|
action | Action object extracted from the actions received in the custom component | ai.flowx.android.sdk.api.custom.components.CustomComponentAction | Mandatory |
params | Parameters needed to execute the action | JSONObject? | Optional. It defaults to null |
Get a substitution tag value by key
CustomComponentScope
context, using the method above, by providing the key
.
It returns:
- the key’s counterpart, if the
key
is valid and found - the empty string, if the
key
is valid, but not found - the unaltered string, if the key has the wrong format (i.e. not starting with
@@
)
Get a media item url by key
CustomComponentScope
context, using the method above, by providing the key
.
It returns the URL
string of the media resource, or null
, if not found.
Obtain enumeration data
CustomComponentScope
context, using the method above, by providing the name
(and the parentName
, if there’s a hierarchy defined and the desired enumeration data (name
is child of parentName
).
It returns the enumeration data, as an FxEnumeration
object, or null
, if not found.
Sample
Among multiple existing custom components, there may be one that:- allows the input of a value representing an
age
- the value should be validated (e.g. to be at least 35 years old)
- the value will be passed back into the process
- execute an action, through the
CustomComponentScope
context, to skip setting the age
Custom header view for the STEPPER component
The container application can opt for providing a custom view in order to be used, for all the Stepper components, as a replacement for the built-in header.The custom view receives
data
to populate its UI, as described below.
To provide a custom header for the Stepper, an implementation of the CustomStepperHeaderProvider
interface should be passed as a parameter when initializing the SDK:
Sample
CustomStepperHeader
To provide the custom header view as a @Composable function, you have to implement theCustomStepperHeader
interface:
Sample
Custom loaders
The container application can decide to provide custom loaders to be displayed at certain moments based on a given predefinedactionName
.To provide custom loaders, an implementation of the
CustomLoaderProvider
interface should be passed as a parameter when initializing the SDK:
The possible values for the
Returning null keeps the built-in platform loader for the specified use cases.
actionName
parameter are:startProcess
- received for overriding the loader displayed when starting a new processreloadProcess
- received for overriding the loader displayed when resuming an existing processwhatever string value representing the name of an action as defined at process definition time
- received for overriding the loader displayed while that action is executed
CustomLoader
replaces the built-in platform loader with the provided one for the specified use cases.Returning null keeps the built-in platform loader for the specified use cases.
CustomLoader
The implementation for providing a custom loader is based on creating and binding a user defined @Composable function, through theCustomLoader
interface:
CustomLoaderScope
Thecomposable
property of the CustomLoader is a @Composable function which may be defined and run only within the context of a CustomLoaderScope
receiver.
Sample
Collecting analytics events
To be able to collect analytics events from the SDK, an implementation for theAnalyticsCollector
functional interface may be provided when initializing the SDK:
Screen
and Action
, both of them containing some Data
and an optional CustomPayload
, as defined at process definition time.
The Event
is structured like this:
Sample
The implementation can be passed as a lambda, like:The
value
property represents the identifier set in the process definition.For action type events there are some additional properties provided:component
- The type of component triggering the actionlabel
- The label of the component, if available. (E.g. title of a button or label of a form element)screen
- The identifier of the screen containing the component, if set
customPayload
is defined at process definition time, and then processed inside the platform before sending it to being collected.Handling “Start of a new process”
When an action of typeSTART_PROJECT
is executed, the onNewProcessStarted
lambda provided in the Flowx.getInstance().init(...)
function is invoked.
This callback provides the UUID of the newly started process, which can be used to resume the process by calling the Flowx.getInstance().continueProcess(...)
method.
It is the responsibility of the container application’s developer to implement the necessary logic for displaying the appropriate UI for the newly started process.
Sample
One way to handle this is to send a broadcast message to notify the Activity currently displaying the running process. The Activity should handle the broadcast to reload and display the newly started process identified byprocessInstanceUuid
(received in the broadcast intent).
Known issues
- shadows are rendered only on Android >= 28 having hardware acceleration enabled