Skip to Content
Technical Articles
Author's profile photo Leonardo Gomez

How to integrate SAP Conversational AI web chat client with an MDK app using a custom control

Digital assistants play a crucial role in the UX of every application. They are everywhere! Is not that all applications should have one, just make sure they add its value to the whole. Their massive adoption is a clear sign of their importance in terms of UX. We are quite far from achieving a KITT, like in Knight Rider, but people are adopting them more and more.

KITT%3A%20%u201CMichael%20are%20you%20sure%20you%20want%20to%20do%20that%u201D

KITT: “Michael are you sure you want to do that?”

 

Personally, I use Alexa at home quite a lot, Google assistant sometimes, and the voice assistant in my car too, although rarely.

 

I’m sure you already know SAP Conversational AI, SAP’s offering to develop your own chatbots. It offers many standard channels to choose from, like the webchat, the SAP web client, Amazon Alexa, Facebook Messenger and Telegram, among others. A lot of options that can suite your needs. You can even, of course, implement one of your own. In this blog post I want to show you how you can integrate the web chat client into an MDK app. It’s clear that this functionality wont work offline, as an MDK app can, but is understandable and useful despite of that. Many popular assistants have that limitation too.

 

In this blog post I’m not going to go over the process of creating a chatbot and the basics of MDK. I intend this to be a short reading with the specific goal to integrate the two parts.

If you want to understand these topics better before you go on, you can go through these resources:

SAP Conversational AI Blogs

SAP Mobile Services, Mobile Development Kit

 

Specially this tutorial is key as I was based on it to write this post.

https://developers.sap.com/tutorials/cp-mobile-dev-kit-slider-extension.html

 

Prerequisites

  • You need a chatbot with the web chat channel implemented
  • A BTP (trial) account with mobile services and an MDK app created
  • The MDK SDK correctly installed

 

Overview

The idea is to create a custom control for the MDK app, using the metadata approach. This control will implement an embedded browser that will display a webpage with the web chat client in it. I have only did it for Android, using the WebView control, but it’s similarly achievable in iOS with the WKWebView. Hopefully I can soon update the post and include these devices too.

So, first of all, you need to build a web page and place the script that will include the web chat client. For example, this is the way I did it, just because I was reusing something I did previously. You can let go your imagination and make it the way you like it.

<!DOCTYPE html>
<html>

<head>
<style>
body {
    background-image: url(./assets/Athenas.jpeg);
    background-repeat: no-repeat;
    background-size: cover;  
}
</style>
</head>

<body background-image="./assets/Athenas.jpeg">
    <!-- // Pericles -->
<script src="https://cdn.cai.tools.sap/webchat/webchat.js" channelId="<channelId>" token="<token>" id="<id>"> </script>  
    <meta name="viewport" content="width=device-width">
</body>

</html>

And it looks like this:

Simple%20webpage

Simple webpage

Now you need to make your webpage accessible from the MDK app and I found 2 ways to do it. One alternative is to host it publicly and access it with the url. Or else you can include it and ship it as a resource in your app. For this, I couldn’t make it work using the metadata. Apparently, there is a folder in the metadata definitions to store resources, but not html files. If I’m wrong, I appreciate you let me know so I can fix it in here. But there is other way by building your own MDK client and placing your web page inside. So we are going to do that.

 

Steps to implement the metadata

  1. Open the Business Application Studio, create the Dev Space and a new project using the MDK template.
  2. Upload the image that will represent your custom control. In my case I’m using this one.

  3. Now register the extension control
  4. Select template New and Register Metadata Extension Control
  5. For the schema use this json
    {
    	"type": "object",
    	"BindType": "",
    	"properties": {
    	    "url": {
    	        "type": "string",
    	        "BindType": ""
    	    }
    	}
    }
    ​


  6. Now edit the Main.page to place your new custom control. Drag and drop it in the available area
    Set the Height to something like 580In the extension properties you can set the location of your webpage in the network

    url: https://etc..

  7. Fill the code in Extensions/chatClientModule/controls/chatClientExtension.ts
    import * as app from 'tns-core-modules/application';
    import { IControl } from 'mdk-core/controls/IControl';
    import { BaseObservable } from 'mdk-core/observables/BaseObservable';
    
    export class chatClientClass extends IControl {
        private _observable: BaseObservable;
        private _webView: any;
        private _url: string;
        
        public initialize(props: any): any {
            super.initialize(props);
    
            if (this.definition().data.ExtensionProperties.url) {
                this._url = this.definition().data.ExtensionProperties.url;
            } else {
                this._url = "file:///android_asset/webchat.html";
            }
    
            if (app.android) {
                this._webView = new android.webkit.WebView(this.androidContext());
                this._webView.getSettings().setJavaScriptEnabled(true);
                this._webView.getSettings().setAllowFileAccessFromFileURLs(true);
                this._webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
                this._webView.getSettings().setAllowFileAccess(true);
                this._webView.getSettings().setAllowContentAccess(true);
                this._webView.loadUrl(this._url);
    
                app.android.on(app.AndroidApplication.activityPausedEvent, this.onActivityPaused, this);
                app.android.on(app.AndroidApplication.activityResumedEvent, this.onActivityResumed, this);
                app.android.on(app.AndroidApplication.saveActivityStateEvent, this.onActivitySaveInstanceState, this);
                app.android.on(app.AndroidApplication.activityDestroyedEvent, this.onActivityDestroyed, this);
                var that = this;
            }
        }
    
        private onActivityPaused(args) {
            console.log("onActivityPaused()");
            if (!this._webView || this != args.activity) return;
            this._webView.onPause();
        }
    
        private onActivityResumed(args) {
            console.log("onActivityResumed()");
            if (!this._webView || this != args.activity) return;
            this._webView.onResume();
        }
    
        private onActivitySaveInstanceState(args) {
            console.log("onActivitySaveInstanceState()");
            if (!this._webView || this != args.activity) return;
            this._webView.onSaveInstanceState(args.bundle);
        }
    
        private onActivityDestroyed(args) {
            console.log("onActivityDestroyed()");
            if (!this._webView || this != args.activity) return;
            this._webView.onDestroy();
        }
    
        public view() {
    
            if (app.android) {
                return this._webView;
            }
        }
    
        public viewIsNative() {
            return true;
        }
    
        public observable() {
            if (!this._observable) {
                this._observable = new BaseObservable(this, this.definition(), this.page());
            }
            return this._observable;
        }
    
        public setContainer(container: IControl) {
            // do nothing
        }
    
        public setValue(value: any, notify: boolean, isTextValue?: boolean): Promise<any> {
            // do nothing
            return Promise.resolve();
        }    
    }​

    In your import function, if you see errors related to tns-core-modules or mdk-core, you can ignore them. There is currently no reference of such libraries in the MDK editor.

    The way it’s implemented, the web view is going to take the url from the extension properties if it’s set. If not it will use the one bundled with the client.

  8. Finally, deploy it to your app in mobile services.

Steps to build the MDK client

  1. I assume you already have your SDK installed, so look for the project template and paste your web page files in the respective resources folder.
  2. Set the respective values in the branding settings and build the client. If everything worked fine you will see your nice web page display in the phone.

Conclusion

I thought it was a nice trick and I hope you enjoy trying it on your own. So easily, you can extend the reach of the web chat client making it available to MDK apps.

Your feedback is highly appreciated!

 

 

 

Assigned tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Jean-Yves Guyomarc'h
      Jean-Yves Guyomarc'h

      Very nice one! Did you try it with the new SAP Conversational AI Web Client as well? As the new Web Client is meant to replace the WebChat in the future, I would be curious to see if it works as well.

      Author's profile photo Leonardo Gomez
      Leonardo Gomez
      Blog Post Author

      Sure does 🙂

      Author's profile photo Diego Rodriguez
      Diego Rodriguez

      Excellent Blog Leo!! Congrats

      Author's profile photo Emanuel Affatati
      Emanuel Affatati

      Excellent Leo! I really like the use case

      Author's profile photo Thomas Jung
      Thomas Jung

      Very nice. Bonus points for the Knight Rider reference.  I for one can't wait for the day when we have a real work companion like KITT.

      Author's profile photo Manjunath Gudisi
      Manjunath Gudisi

      Dear Leonardo Gomez  Did you already work on iOS app as well? Can you share the code if you had done it? Thanks, Manju