Skip to main content

Android project requirements

System requirements:
  • minSdk = 26 (Android 8.0)
  • compileSdk = 37
The SDK library was built using: Your project must build with at least:
  • Android Gradle Plugin 9.1.0, with built-in Kotlin (no org.jetbrains.kotlin.android plugin)
  • Gradle 9.3.1 (the minimum depends on your Android Gradle Plugin version)
  • Kotlin 2.4
  • JDK 17

Installing the library

  1. Add the maven repository in your project’s settings.gradle.kts file:
  1. Add the library as a dependency in your app/build.gradle.kts file:
Replace <version> with the correct version corresponding to your platform version.
To find the right version, navigate to:

Release Notes → Choose your platform version → Deployment guidelines → Component versions

  1. Enable core library desugaring in your app/build.gradle.kts file, as the SDK requires it:

Library dependencies

Impactful dependencies:
The SDK depends on OkHttp 5 and Retrofit 3. Gradle resolves your app to these versions even if you declare older ones, so any code in your app that uses OkHttp or Retrofit must be compatible with them.

Public API

The SDK library is managed through the Flowx singleton instance, which exposes the following methods:

Configuring the library

To configure the SDK, there are two things needed in the project’s application class:
  1. first, make it implement the FlowxOwner interface:
  1. then, call the init method inside the onCreate() method:

Parameters

• The 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.
• Collecting log 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

The configuration properties that should be passed as Config data for the config parameter above are:

Where to find these values

The mandatory configuration values are properties of your FlowX deployment, not of the SDK. Your DevOps team holds them, in the same configuration the FlowX Designer web app connects through:

Custom validators

The custom 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 render processes, UI Flows and the chat for an authenticated user, set the user’s access token before calling any other method on the singleton instance:
Whenever the access token changes based on your own authentication logic (e.g. it is refreshed), update it in the renderer by calling the setAccessToken method again. Refreshing the token of the same user while a process, a UI Flow or the chat is running is supported.
  • The token can’t be cleared once set. When another user logs in, call setAccessToken with that user’s token, between runs (not while a process, a UI Flow or the chat is running).
  • Do not pass an empty string (""). The SDK sends it as is and the backend rejects the requests.
The SDK performs no authentication of its own: an authentication base URL or a Keycloak client ID are not SDK configuration parameters. Your container application runs its own OIDC flow against Keycloak and passes the resulting token through setAccessToken. If you are starting from the FlowX TemplateApp, the authentication values it sets belong to the application, not to the SDK.

Anonymous mode

If the access token is never set, the SDK runs in anonymous mode: it sends no Authorization header and uses an anonymous session provided by the backend.
Use it to render processes and UI Flows that are exposed to unauthenticated users. For the platform setup, see Anonymous runtime access.
Setting an access token switches the SDK to authenticated mode and discards the anonymous session. Switching back to anonymous mode is not available.

Theming

Prior setting up the theme, make sure the access token was set.
Check the authentication section for details.
To be able to use styled components while rendering a process, a UI Flow or the chat, the theming mechanism must be invoked by calling the setupTheme(...) method over the singleton instance of the SDK:

Parameters

If the fallbackThemeJsonFileAssetsPath parameter value is null, there will be no fallback mechanism set in place, meaning if fetching the theme fails, the rendered process will have no style applied over its 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.
Do not start or resume a process before the completion of the theme setup mechanism.

Changing current locale settings

The current locale and language can be also changed after the initial setup, by calling the changeLocaleSettings function:

Parameters

Do not change the locale or the language while a process is rendered.
The change is successful only if made before starting or resuming a process.

Sample

The 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
After performing all the above steps and all the prerequisites are fulfilled, a new instance of a FlowX process can be started, by using the startProcess function:

Parameters

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 @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
To resume an existing instance of a FlowX process, after fulfilling all the prerequisites, use the continueProcess function:

Parameters

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 @Composable returned from the SDK (i.e. it occupies the whole activity screen space).

Sample

onDismissRequested parameter

The onDismissRequested parameter is a function defined within the ProjectScope context. This gives the ability to query for substitution tags, media library items or enumerations to use them when handling this callback (i.e. showing a snackbar or an alert).
ProjectScope is also the base of the CustomComponentScope and CustomLoaderScope contexts, so the same methods are available in custom components and custom loaders.

Get a substitution tag value by key

All substitution tags will be retrieved by the SDK before starting the process and will be stored in memory. Whenever the container app needs a substitution tag value, it can request it through the ProjectScope 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

All media items will be retrieved by the SDK before starting the process and will be stored in memory. Whenever the container app needs a media item url, it can request it through the ProjectScope 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

Whenever the container app needs enumeration data, it can request it through the ProjectScope context, using the method above, by providing the name (and the parentName, if the requested enumeration is a child of another one). It returns the enumeration data, as an FxEnumeration object, or null, if not found.

Sample

Start an UI Flow

Prior starting an UI Flow, make sure the authentication and theming were correctly set up
After performing all the above steps and all the prerequisites are fulfilled, an UI Flow can be started, by using the startUiFlow function:

Parameters

The onDismissRequested lambda runs in the ProjectScope context, the same as for processes. See the onDismissRequested parameter section.
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 @Composable returned from the SDK (i.e. it occupies the whole activity screen space).

Sample

Display the standalone chat

Prior displaying the chat, make sure the authentication and theming were correctly set up
The chat component can be used on its own, outside of any process or UI Flow. It is connected to an AI conversational workflow and can be displayed by using the chatView function:

Parameters

The ChatConfig properties are:
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 @Composable returned from the SDK (i.e. it occupies the whole activity screen space).

Sample

Custom components

The container application should decide which custom component view to provide using the componentIdentifier 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 the CustomComponent 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
The appropriate way to check and cast the data accordingly to the needs must belong to the implementation details of the custom component.
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

The composable property of the CustomComponent is a @Composable function which may be defined and run only within the context of a CustomComponentScope receiver.
Besides the methods for running actions, it inherits the ProjectScope methods (getSubstitutionTagContent, getMediaItemUrl and getEnumerationItems). This allows calling predefined SDK methods for running actions, querying for substitution tags, media item URLs or obtaining enumerations data, directly from the custom component through the scope itself.

Run 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.

To run an action (e.g., on a click of a button in the custom component) you need to call the runAction method, through the CustomComponentScope context:
Parameters

Run upload action

A specific use case for running actions from custom components involves uploading files into the FlowX platform.

To run an upload action (e.g., on a click of a button in the custom component) you need to call the runUploadAction method, through the CustomComponentScope context:
Parameters
It is recommended that a value for the mimeType parameter is always provided.
When missing, the SDK tries computing it internally.
Sample
In order for the upload behave correctly, it’s highly IMPORTANT to disable the SDK internal update mechanism while selecting a file.

Get a substitution tag value by key

All substitution tags will be retrieved by the SDK before starting the process and will be stored in memory. Whenever the container app needs a substitution tag value for populating the UI of the custom components, it can request the substitution tag, through the 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

All media items will be retrieved by the SDK before starting the process and will be stored in memory. Whenever the container app needs a media item url for populating the UI of the custom components, it can request the url, through the 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

Whenever the container app needs enumeration data for populating the UI of the custom components, it can request it through the CustomComponentScope context, using the method above, by providing the name (and the parentName, if the requested enumeration is a child of another one). 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
  • runs an action, through the CustomComponentScope context, to skip setting the age

Custom header view for the STEPPER component

The container app can opt for providing a custom view to use 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 the CustomStepperHeader interface:

Sample

Custom loaders

The container application can decide to provide custom loaders to be displayed at certain moments based on a given predefined actionName.
To provide custom loaders, an implementation of the CustomLoaderProvider interface should be passed as a parameter when initializing the SDK:
where the CustomLoaderProvider.LoaderType is defined like this:
The available types for the loaderType parameter are:
  • LoaderType.StartProcess - received for overriding the loader displayed when starting a new process
  • LoaderType.ReloadProcess - received for overriding the loader displayed when resuming an existing process
  • LoaderType.Action - received for overriding the loader displayed while the action having the name name is executed
  • LoaderType.Upload - received for overriding the loader displayed while the upload action having the name name is executed
The name property received for the LoaderType.Action and LoaderType.Upload types represents the name of an action, as defined at process definition time, received for being able to override the loader displayed while that action is executed.
Returning an implementation of a 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 the CustomLoader interface:

CustomLoaderScope

The composable property of the CustomLoader is a @Composable function which may be defined and run only within the context of a CustomLoaderScope receiver.
It provides the ProjectScope methods (getSubstitutionTagContent, getMediaItemUrl and getEnumerationItems). This allows calling predefined SDK methods for querying for substitution tags, media item URLs or obtaining enumerations data directly from the custom loader through the scope itself.

Sample

Collecting log events

To be able to collect log events from the SDK, an implementation for the LogSink.Collector functional interface may be provided when initializing the SDK:
The Event is structured like this:

Sample

The implementation can be passed as a lambda, like:
The payload inside the LogSink.Event contains raw data specific to the event type.

Collecting analytics events

To be able to collect analytics events from the SDK, an implementation for the AnalyticsCollector functional interface may be provided when initializing the SDK:
There are two types of events, 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 action
  • label - 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
The 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 type START_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 by processInstanceUuid (received in the broadcast intent).

ProGuard / R8

The SDK ships with its own consumer-rules.pro file containing the required keep rules for correct functionality.
These rules are automatically merged into the container app’s ProGuard/R8 configuration and applied during code shrinking and obfuscation.
The container app may add additional rules if its specific logic requires them.

Known issues

Last modified on October 30, 2026