Start Flow¶
Before Starting a Predefined Flow¶
Before starting a predefined flow, there are two configurations to be completed.
ActivityLifecycleCallbacks
¶
For most of the features to be used in your mobile app, they will need to know the state of the app, for example whether the app is in the background or not. Therefore, registering an ActivityLifecycleCallbacks
to the application is a must.
//in onCreate of application
registerActivityLifecycleCallbacks(AppLifecycleCallbackHandler.getInstance())
//in onCreate of application
registerActivityLifecycleCallbacks(AppLifecycleCallbackHandler.getInstance());
DiscoveryServiceProvider
¶
In the app development stage you can set the Discovery Service URL for development into DiscoveryServiceProvider
when the application starts.
//in onCreate of application
DiscoveryServiceProvider.set("....")
//in onCreate of application
DiscoveryServiceProvider.set("....");
Then, when the onboard flow comes to the Discovery Service activation step, you only need to input the email domain to get the complete application information published to the Discovery Service.
Note
For detailed information about how to configure the Discovery Service, refer to the online help.
APIs to Start a Flow¶
There are two APIs to start a flow.
@JvmStatic
fun start(activity: Activity, flowContext: FlowContext) {
...
}
@JvmStatic
fun start(fragment: Fragment, flowContext: FlowContext) {
...
}
Some information will be needed when starting a flow: the application configuration information, customized flow options, etc. This information will be saved into the flowContext
.
data class FlowContext(
/** The application configuration*/
private var appConfig: AppConfig? = null
/** The predefined flow type*/
private var flowType: FlowType = FlowType.ONBOARDING
/** The flow state listener */
private var flowStateListener: FlowStateListener? = null
/** The screen settings */
private var screenSettings: MutableList<ScreenSettings> = mutableListOf()
/** The customized flow */
private var flow: Flow? = null
/** The flow action handler */
private var flowActionHandler: FlowActionHandler = FlowActionHandler()
/** The flow options to control how to show 'info' type message, which activation method to use*/
private var flowOptions: FlowOptions = FlowOptions()
/** Single/Multiple user mode switch */
private var multipleUserMode: Boolean = false
/**
* In the case that the client code wants to use a single activity to start different flows
* and be able to identify which flow finishes in 'onActivityResult', this variable can be
* specified.
*/
val flowRequestCode: Short = FlowConstants.FLOW_ACTIVITY_REQUEST_CODE,
/** The user ID of the user that forgot their passcode. */
val forgotPasscodeUserId: String? = null,
)
The parameters are:
Parameter | Description |
---|---|
appConfig |
The application information that the mobile app uses to talk to mobile services. This is mandatory for onboarding. AppConfig.Builder is provided to build an instance easily. |
enabledServices |
Specify which features the client application wants to use. |
screenSettings |
Customize the screens inside the flow. |
flowStateListener |
Provide customized logic and insert it into the flow execution process at certain points. |
flowActionHandler |
Provide customized logic for certain cases, such as the customize passcode validation logic for example. |
flowOptions |
Pass in options, such as specifying which activation method to use, how to show information message from the flows component, either with a dialog or a toast message. See Flow configuration for details. |
multipleUserMode |
Boolean value to indicate single user or multiple user mode |
flowType |
Predefined flow type, onboarding, reset, etc. |
flow |
Customized flow instance. If this property is provided, flowType will be ignored by the flows component |
flowRequestCode |
The request code that the client code wants to monitor. If the client code wants to start different flows in one activity, this property can be provided. |
forgotPasscodeUserId |
When executing the 'Forgot Passcode' flow, this property must be provided in FlowContext , otherwise, a runtime exception will be reported. |
Sample client code:
val flowContext = FlowContext(
flowType = FlowType.ONBOARDING,
appConfig = AppConfig.Builder().applicationId("myapp").build(),
flowStateListener = WizardFlowStateListener())
Flow.start(activity, flowContext)
FlowContext flowContext = new FlowContextBuilder()
.setApplication(prepareAppConfig())
.setFlowStateListener(new WizardFlowStateListener())
.build();
Flow.start(activity, flowContext);
After starting a flow, the flowContext
will be saved into a FlowContextRegistry
. The client code can then get flowContext
from FlowContextRegistry
at a later time in order to update some of the properties and start another flow. For example:
val flowContext = FlowContextRegistry.flowContext.copy(flowType = FlowType.RESTORE)
Flow.start(activity, flowContext)
FlowContext flowContext = new FlowContextBuilder(FlowContextRegistry.getFlowContext())
.setFlowType(FlowType.CHANGEPASSCODE)
.build();
Flow.start(this, flowContext);
Note
Since Java does not have the 'copy' function on FlowContext
, unlike Kotlin, we can get the FlowContext
instance
from FlowContextRegistry
, then pass it to FlowContextBuilder
to copy the instance and modify the property as needed.
Since SAP BTP SDK for Android 3.3, two new APIs have been added into FlowContext
to retrieve the current user id and the offline encryption key.
fun getCurrentUserId(): String?
fun getOfflineEncryptionKey(): String?
The two APIs can only be called after the onboarding or restore flow, otherwise null
will be returned. getOfflineEncryptionKey
will only retrieve the key saved in the user passcode protected secure store during the onboarding flow.
To get the flow execution status, which is either done
or canceled,
the client activity needs to override the onActivityResult
function:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == FlowConstants.FLOW_ACTIVITY_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
//start your main business activity.
startActivity(Intent(this, MainActivity::class.java))
} else {
Snackbar.make(fab, "Flow cancelled.", Snackbar.LENGTH_LONG).show()
}
} else if( requestCode == 100 ) {
//If flowRequestCode is provided in flow context, client code can check the request code here.
}
}
For more information about enabledServices
and screenSettings
in FlowContext
, see Flow Configuration and flowStateListener
and flowActionHandler
in Extension Points.