Timeout Flow in SAP BTP SDK for Android

If you’re developing a mobile app with SAP BTP SDK, you may already be familiar with the passcode policy concept and how to integrate this feature into your app. If you need more detail information, here is the document about passcode policy

Above is the screenshot from the mobile service cockpit to configure the passcode policy for an application.

If you’re developing your Android mobile app with SAP BTP SDK for Android, most of the settings in the above screenshot are handled inside SDK, but ‘Lock Timeout’ may need something in your code based on your use cases.

In this article, we will focus on the ‘Lock Timeout’ property, and discuss different use cases around this property and how the client code need do to make it work seamlessly with your app.

Timeout flow is one of the predefined flows inside the ‘Flows’ component of SAP BTP SDK for Android, it provides the support for the ‘Lock Timeout’ passcode policy. The basic logic of this flow is that if the mobile app is put into background for a period of time which is longer than the ‘Lock Timeout’ setting, then when bring the app back to the foreground, the ‘Timeout’ flow will kick in automatically, asking the user to input his passcode to unlock the app before proceeding with other operations.

For example, with the setting in the above screenshot, if the app is put into background over 5 seconds, then bring it back again into foreground will need the passcode to unlock the app.

You code does not need to trigger this flow explicitly, it will be triggered automatically by SDK at the right time on top of the activity when the app was put into the background.

You may already get the sense that the ‘Timeout’ will depend on the status whether the app is in the foreground or background, then SDK must have logic to detect this status change.

Before SAP BTP SDK for Android 4.0.1, we used ActivityLifecycleCallbacks to detect the status change, but it had a problem to handle the following use case:

Set ‘Lock Timeout’ as ‘0’, then rotate the device, the ‘Timeout’ flow kicks in.

To address this problem, from SDK version 4.0.1, we switched to ProcessLifecycleOwner to detect the status, and from the coming version 4.0.2, we’re now using Android ‘startup’ library version 1.1.1 to initialize the SDK components. So in your AndroidManifest.xml, the ‘androidx.startup.InitializationProvider’ provider should never be marked as ‘tools:node = “remove”‘, as documented in google’s Android document.

<!-- DO NOT DO THIS -->
<provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" tools:node="remove"> </provider>

Instead, if you have your own ‘startup’ initializer, or just want to remove one specific meta-data, the ‘tools:node’ must be set to ‘merge’, like this:

<!-- DO THIS --> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <!-- If you are using androidx.startup to initialize other components --> <meta-data android:name="androidx.work.WorkManagerInitializer" android:value="androidx.startup" tools:node="remove" /> </provider>

If you don’t use the ‘startup’ Android library, you can also totally remove this provider from your AndroidManifest.xml.

In the coming SAP BTP SDK for Android version 4.0.2, we made several enhancements around this ‘Timeout’ flow to support more use cases and make SDK more flexible.

Chrome Custom Tabs

In SAP BTP SDK for Android version 4.0, we added the support to authenticate the user with Chrome Custom Tabs, so after authentication, the sessions inside the browser can be shared to the client code if it wants to bring up Javascript app inside the native app.

But because when launching a Chrome Custom Tabs, the mobile will be put into the background, the ‘Timeout’ flow might kick in depending on your ‘Lock Timeout’ settings. After you close the browser and go back to app, you may see the sign in screen asking for passcode to unlock the app.

To make the launched Chrome Custom Tabs be treated as in the same process of your app, we exposed an API for the client code to launch a Chrome Custom Tabs instead of using the Custom Tabs APIs directly.

 //SDKCustomTabsLauncher.kt fun launchCustomTabs( context: Context, url: String, builder: ((CustomTabsIntent.Builder) -> Unit)? = null ) { ... } fun customTabsSupported(context: Context): Boolean { ... }

Here is the sample code to use the above API:

 SDKCustomTabsLauncher.launchCustomTabs( context, "http://androidsdkqiangz.web.app/test" ) { builder -> builder.setShowTitle(true) }

SDK will connect to the Custom Tabs service, do the ‘warmup’, create a session, then pass back the ‘CustomTabsIntent.Builder’ back to the client code, so you can still customize the Custom Tabs. Internally, SDK will fill the gap between the app going into background and Custom Tabs being shown.

Widget Configuration Activity and Launcher Activity

Since the ‘Timeout’ may kick in when the app is brought up to the foreground, it may not ideal for some cases.

For example, we received the requirement that when a widget configuration activity is showing, the activity does not want the ‘Timeout’ flow kicking in automatically but would start the ‘Restore’ flow explicitly depending on its needs.

Another example is the launcher activity, it may also be able to trigger the ‘Timeout’ flow in some cases which is not intended either.

To support the above use cases, one more API is exposed inside ‘FlowActionHandler’ in SAP BTP SDK for Android version 4.0.2.

open fun shouldStartTimeoutFlow(activity: Activity): Boolean = true

SDK will ask the client code with the topmost activity when being brought up to the foreground, so the client code can decide whether the ‘Timeout’ flow needs kick in or not. The sample code looks like this:

override fun shouldStartTimeoutFlow(activity: Activity): Boolean = when (activity) { is WelcomeActivity -> false //Launcher activity is ODataWidgetConfigurationActivity -> false //the widget configuration activity else -> super.shouldStartTimeoutFlow(activity) }

With this, it’s also possible that your code can decide whether to start the ‘Timeout’ flow based on a ‘state’ inside your activity.

Other Cases

If the above approaches still cannot meet your requirement, we also exposed 2 APIs to let the client code to pause and resume the ‘TimeoutService’.

//TimeoutLockService.kt
/** Pauses the timeout service, return 'true' if it was started before, 'false' otherwise.*/
@JvmStatic
fun pause(): Boolean { ... } fun resume() { ... }

Note: Please be careful when using these 2 APIs. Once you forget to ‘resume’ or the ‘resume’ is not triggered for some reasons, the ‘Timeout’ flow will NOT work until the user signs in again with the ‘Restore’ flow.

Basically, ‘Timeout’ flow is the same as ‘Restore’ flow in terms of feature and the callbacks to ‘FlowStateListener’, but there are differences that may need attention.

‘Timeout’ flow will be called inside SDK, so the client code cannot install callbacks in ‘Flow.start’ API. After ‘Timeout’ flow, SDK will notify the client code with ‘

  • onFlowFinished’ callback with the flow name as ‘Timeout’, then return to the activity which was left on topmost when putting into the background. For other flows, since the client code can install callback when calling ‘Flow.start’, ‘onFlowFinished’ will not be called.
  • From SDK version 4.0.2, we added a ‘Reset Client’ button on the sign in screen for the single user mode apps. But because of the above difference, the button will be hidden for ‘Timeout’ flow, because SDK will not be able to know where to go after resetting the client.

Thanks for reading and looking forward to your feedback. If you have any questions, please leave them here:  https://answers.sap.com/tags/73555000100800001281