Integrating with a web app

Setup

To embed the Web Discover SDK natively within the app, place the Web SDK folder inside the /src/main/assets/ directory in your project. It’s advisable to embed the webpage inside your application directly as opposed to hosting on a secondary server as you’ll need to put some Android specific callbacks within the HTML document to take full advantage of the framework. If hosting on a server is preferable and necessary, POST messages will need to be implemented to manage data and control interactions.

Create your embedded page

A basic HTML page will be needed to display the Web Discover and Preview screens natively - it is similar both in structure and functionality to what would be used in an embedded web application, with the only difference being how the vouchrApp object is created. An example of the VouchrApp object that will be included in the embedded webpage is shown below.

var vouchrApp = new window.VouchrApp({
        vouchrConfig,
        idToken,
        active: function() {
            //Screen Active
            Android.active()
            console.log("ACTIVE");
        },
        summary: function() {
            //Summary Showing
            Android.summary()
        },
        complete: function(voucherId) {
            //Complete button clicked
            // The voucherId parameter is used for the finalization of the voucher
            if(voucherId !== undefined) {
              var body = {
                type: "CASHLESS",
                approved: true
              };

              vouchrApp.finalizeVoucher(voucherId, body).then(function(response) {
                Android.complete(response.data.url);
              });
            }
        },
        error: function() {
            //Error occurred
            Android.error()
        },
        cancel: function() {
            //Voucher deleted
            Android.cancel()
        }
      });

As you can see the main difference, besides the comments, are that there are many references to an Android object and its functions. This will be covered in more detail in the next section, but this allows us to control native Android functionality by calling native Android code from within our webpage. In this example the finalizeVouchr function is called as soon as the confirm callback is issued, but that is not necessary for every implementation.

Setting up the native view

Loading the page into the webview

In order to load your modified webpage into your WebView and maintain proper functionality, some setup is required. Use the following template to ensure everything works as intended.

webView.loadUrl("file:///android_asset/vouchr-web-sdk/web_discover.html");
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
webView.addJavascriptInterface(WebAppInterface(getContext()), "Android");
webView.setVisibility(View.VISIBLE);
webView.loadUrl("file:///android_asset/vouchr-web-sdk/web_discover.html")
webView.settings.javaScriptEnabled = true
webView.webChromeClient = WebChromeClient()
webView.addJavascriptInterface(WebAppInterface(context!!), "Android")
webView.visibility = View.VISIBLE

The three most important steps are the middle 3 -0 setting javaScriptEnabled to true allows the page to run external javaScript, setting a WebChromeClient allows our page to show alerts (needed to confirm various functionalities), and adding a JavaScriptInterface allows us to add our native code as an external javaScript file to our webpage.

Setting up the JavaScriptInterface

The JavaScriptInterface is the most important part of this task - it allows the webpage to seamlessly call our native methods without having to deal with POST methods or any other forms of HTTP requests. An example with names corresponding to those used in the above embedded page can be found below.

class WebAppInterface {
    public WebAppInterface (){
        //Constructor if needed
    }

    @JavascriptInterface
    @UiThread
    public void active() {
        //Control what happens when the Web SDK Discover or Preview screens are on screen
    }

    @JavascriptInterface
    @UiThread
    public void summary() {
        //Control what happens when the summary screen is showing
    }

    @JavascriptInterface
    @UiThread
    public void complete(String vouchrId) {
        //Control what happens when the voucher is sent
    }

    @JavascriptInterface
    @UiThread
    public void error() {
        //Handle an error occuring
    }

    @JavascriptInterface
    @UiThread
    public void cancel() {
        //Voucher creation has been cancelled
    }
}
inner class WebAppInterface(private val mContext: Context) {
    @JavascriptInterface
    @UiThread
    fun active() {
        //Control what happens when the Web SDK Discover or Preview screens are on screen
    }

    @JavascriptInterface
    @UiThread
    fun summary() {
        //Control what happens when the summary screen is showing
    }

    @JavascriptInterface
    @UiThread
    fun complete(vouchrId: String?) {
        //Control what happens when the voucher is sent
    }

    @JavascriptInterface
    fun error() {
        //Handle an error occuring
    }

    @JavascriptInterface
    @UiThread
    fun cancel() {
        //Voucher creation has been cancelled
    }
}

As can be seen above the actual interface class is quite simple, with only a one noticable difference - the annotations above each method. The @JavascriptInterface annotation in tandem with the addJavascriptInterface property in our WebView allows Android to compile our methods into javaScript and send it as an external script for our webpage to make use of.

The second annotation - @UiThread - is used along with the runOnUiThread() method to ensure that we can modify UI elements from within our callbacks. Keep note that if your callback class is within a fragment your fragment context will have to be cast to your parent activity to ensure availability of this method.

Flow

In terms of flow and usage, the implementation is totally up to the developer. Lifecycle-wise the embedded Web app will function exactly the same as the standard Web app, just encased within the mobile framework.