Subaio Fintech Bridge for Android

This document provides informations of how to use the Subaio Fintech Bridge in your projects. There exists 3 Fintech Bridge libraries;

  • Fintech Bridge for iOS
  • Fintech Bridge for Android
  • Fintech Bridge for Web.

The libraries provides user interfaces, API integrations and other functionality related to Subaio. The purpose of the libraries is to reduce the implementation and maintenance cost the host applications, while enabling the Subaio application to evolve parallel with the host application. While there are slight differences between them because of differences in syntax and convention, the general structure is the same.

Architecture

The fintech bridge is intended for embedding small, widget-like applications inside a larger app. The application is structured in the following parts:

  • Host application: The iOS, Android, or web application that hosts the Subaio components. This might be a mobile bank application or web home banking solution.
  • Bridge: The bridge library is used by the host application to grant easy control over the embedded app as well as a standardized event system. It consists primarily of two components:
    • BridgeManager: A singleton-like class for global configuration of all views, authentication mangagement, as well as communication between views.
    • BridgeView: A wrapper around a single embedded application.
  • Embedded application: The web application running inside of a webview/iframe.

Including embedded applications thus requires including the bridge library, configuring the BridgeManager and instantiating a BridgeView.

Each bridge project includes an example project demonstrating how to use the manager and the views.

To better facilitate native transitions between pages, the subaio app is separated in pages that can be placed in separate view controllers and pushed separately to the nagivation stack.

Each instance of an embedded view can be set to show a specific Page, defined by a name and optionally a set of parameters, e.g. new Page("OVERVIEW", null) or new Page("SUBSCRIPTION", new JSONObject(new HashMap() {{ put("subscriptionId", "..."); }})). The exact pages will depend on the application. For simple integrations where the views are simply started as new activities, the host application only need knowledge of the initial overview page, available as Page.overview() for convenience.

Views will push new pages using the onViewNavigated event.

Notifications for the embedded app should generally be implemented to pass name and params provided by subaio on to the host application to easily handle navigation. See the Push Notifications section for details.

Authentication

The subaio views use JSON web tokens for authentication. All views use a shared token, administred by the BridgeManager. The tokens generally expire after one hour, so the BridgeManager has internal logic to automatically refresh the token when necessary.

The preferred method of obtaining a subaio token is to let the host application make an authenticated request to its own backend, which will then request a token from the subaio backend.

The host application is responsible for providing a callback for obtaining a token to the BridgeManager. This callback will be passed a handler class, where exactly one of the following methods should be called:

  • success: called when a token is received
  • unauthenticated: called if the user is not authenticated
  • unavailable: called when a network outage or similar prevents getting a token

Example implementation:

new BridgeManager.TokenHandler() {
    @Override
    public void onTokenRequired(String language, BridgeManager.TokenResultHandler resultHandler) {
        if (/* User is unauthenticated */) {
            resultHandler.unauthenticated();
        }
        try {
            String token = /* Fetch token from backend */;
            resulthandler.success(token);
        } catch (Exception e) {
            resultHandler.unavailable();
        }
    }
}

Besides providing the callback, the host application should invoke BridgeManager.getInstance().refreshToken() whenever the user is logged out or a new user is logged in.

See BridgeManager.TokenHandler.onTokenRequired.

Getting a BridgeManager

A singleton BridgeManager is automatically available as BridgeManager.getInstance(). Alternatively, they can be instantiated manually. If the shared instance is not used, the manager should be passed to the BridgeView constructor as the last argument.

Configuring the BridgeManager

The following options need to be provided to the BridgeManager before any views can be instantiated:

  • baseUrl: The URL where the embedded app is hosted.
  • language: A BCP-47 language tag. The language can be changed on the fly.
  • onTokenRequired: Callback to request a new token. See Authentication section and platform-specific documentation for details. The callback will be called whenever the BridgeManager needs new token information (including if the user is logged out). See BridgeManager.TokenHandler.onTokenRequired and the Authentication section.
  • requestHandler: Handler for request authentication, such as SSL pinning. If native pinning or no pinning is sufficient, use NativeRequestHandler. Otherwise, see the section on SSL pinning.

Optionally, the following may be set:

  • customConfig: A Map<String, String> lookup of custom values sent to all views. Keys and possible values should be agreed upon between the embedded and host apps. Possible uses are custom theming, dark/light mode and injecting user info.
  • allowExternalUrls: (default false) Allow the embedded app to open arbitrary URLs on the phone. This is primarily used to help navigate the user to iTunes/Google Play subscription pages. This needs to be enabled for the embedded app to be fully functional.
  • allowShare: (default false) Allow the embedded app to request a share dialog to share a message. This is primarily used to help the user help others to find their iTunes subscription page. This needs to be enabled for the app to be fully functional.

These can be set through a fluent interface by calling startConfiguration and ending with apply.

Example configuration (see app/src/main/java/com/subaio/example/LoadingActivity.java):

BridgeManager.getInstance()
    .startConfiguration()
    .setBaseUrl(baseUrl)
    .setLanguage(language)
    .setCustomConfig(customConfig)
    .setAllowExternalUrls(true)
    .setAllowShare(true)
    .setRequestHandler(new NativeRequestHandler())
    .setTokenHandler(...)
    .apply()

Instantiating a BridgeView

The BridgeView is a UIView that can be inserted in a controller. An example of a controller wrapping a navigation bar and a BridgeView can be found in <

Changelog

3.1.1

Improve documentation for custom actions

BridgeView's sendCustomAction previously allowed any Object as argument. If was anything but a JSONObject, JSONArray or a valid primitive, the result was simply stringified instead of serialized.

To alleviate this, a type check has been added to the existing call for sendCustomAction, and the call has been deprecated. In addition, two new overloads have been added, one accepting a JSONObject and one accepting a JSON string, allowing easy usage with other JSON libraries.

3.1.0

Add support for custom dialogs

Views can now request a native AlertDialog be shown. This must be enabled when configuring BridgeManager, with the optional allowDialogs setting.

3.0.2

Fix crash when fetching templates

If the connection for fetching template data was interrupted at the wrong time, it could result in an unhandled exception.

3.0.1

Initialization timeout is now configurable

Whenever a view is created, a timeout is used to detect and stop hanging views. Previously, this timeout was set to 10 seconds. Now, this timeout can be changed to a more tailored user experience when configuring the manager, by calling setInitializationTimeoutMillis. The default remains 10 seconds.

3.0.0

Remove trustkit example (breaking)

The previous example implementation of RequestHandler as TrustKitRequestHandler has been removed, since TrustKit is not the most common solution for SSL pinning, and TrustKit sometimes caused installation problems. TrustKitRequestHandler can still be found in the readme, which also makes it clearer that any pinning solution will do, not just TrustKit.

Upgrade from android.support.* to androidx.* (breaking)

This should enable consumers to disable jettifier if nothing else uses android.support.*.

2.0.4

Fix crash when fetching templates (backported from 3.0.2)

If the connection for fetching template data was interrupted at the wrong time, it could result in an unhandled exception.

2.0.3

Avoid flash of white

A quick flash of white could be seen for apps not using placeholder-content. This was caused by the uninitialized webview being visible, and should now no longer happen.

2.0.2

Minor improvements

  • All logging is now consistently tagged with FintechBridge

Bugs

  • Fixed an issue that could cause a crash if the application opened views with more than 12 hours delay without restarting

2.0.1

Bugs

  • Fixed an issue that caused other webviews to malfunction when closing a view

2.0.0

Naming (breaking)

The framework as well as a number of classes have been renamed. The initial implementation had the package called com.subaio.subaio and many classes prefixed with Subaio. The package has been renamed to com.subaio.fintechbridge. The following classes have been renamed:

  • SubaioManager -> BridgeManager
  • SubaioView -> BridgeView
  • SubaioViewListener -> BridgeViewListener
  • SubaioViewError -> ViewError

Share and open URL events removed (breaking)

Events onViewDidShare and onViewDidOpenUrl from BridgeViewListener have been moved to internal handling. Since both can already be disabled during configuration, it seems unnecessary to require an implementation from library consumers, and it is unlikely that custom logic will be needed.

Configuration (breaking)

The SubaioConfiguration class has been removed entirely. The options normally passed to the SubaioConfiguration constructor can now be passed directly into the .configure call. No overloads exist for optional properties. To ease configuration, a fluent interface has been added, and it is recommended that this is used instead of directly calling .configure. To use it, start by calling startConfiguration and end by calling apply. Configuration must include calls to

  • setBaseUrl
  • setLanguage
  • setTokenHandler
  • setRequestHandler (see section on SSL pinning)

Optionally, you can also call

  • setAllowExternalUrls
  • setAllowShare
  • setCustomConfig

Synchronicity

Previously, the configure-call was asynchronous. During the configuration, base-HTML and placeholder images were fetched, and an initial token was requested.

All this initialization has been moved to the creation of the first view. Calling configure is now entirely passive and synchronous, and can thus be done whenever convenient, as long as it is before the first view is created.

SSL pinning

To allow the usage of other libraries for authentication, TrustKit has been moved to the class TrustKitRequestHandler, which should be imported and passed to setRequestHandler during configuration. network_security_config.xml is still used to define the expected pins.

If another library than TrustKit is used for SSL pinning or to otherwise validate connections, the RequestHandler abstract class should be used.

If built-in handling of SSL is sufficient, NativeRequestHandler can be used. It has to be passed manually to ensure SSl pinning is not accidentally omitted.

Example of new configuration

BridgeManager.getInstance()
    .startConfiguration()
    .setBaseUrl(baseUrl)
    .setLanguage(language)
    .setCustomConfig(customConfig)
    .setAllowExternalUrls(true)
    .setAllowShare(true)
    .setRequestHandler(new TrustKitRequestHandler(this /* Android context */))
    .setTokenHandler(...)
    .apply()

Token management (breaking)

The signature of TokenHandler.onTokenRequired has been updated to better guide the implementation. Previously, the library consumer was responsible for setting the token to a value or null at the appropriate times. Now, a handler class makes handling specific cases more explicit. The new handler has three methods, exactly one of which should be called every time the function is invoked:

  • success: called when a token is received
  • unauthenticated: called if the user is not authenticated
  • unavailable: called when a network outage or similar prevents getting a token

Example implementation:

new BridgeManager.TokenHandler() {
    @Override
    public void onTokenRequired(String language, BridgeManager.TokenResultHandler resultHandler) {
        if (/* User is unauthenticated */) {
            resultHandler.unauthenticated();
        }
        try {
            String token = /* Fetch token from backend */;
            resulthandler.success(

Package com.subaio.fintechbridge


package com.subaio.fintechbridge