Use the Javascript-Widget within a web-view in your mobile app.
You can also integrate our Javascript-Widget solution inside a web-view in your mobile App(s).
The integration follows almost the same procedure as described in our description for Javascript-Widget.
Some special steps have to be taken when integrating the JS-Widget in a web-view, which will be described below in the examples.
Implementation Steps for the Hosted Page Implementing the JS-Widget
You will need a HTML page that implements the JS-Widget, just like described in Javascript-Widget. In addition, the following changes are recommended:
HTML
<!-- in the <head> -->
<!-- Scale settings so the page does not zoom/move-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, maximum-scale=1.0, user-scalable=no">
CSS
#XS2A-Form input:not([type='checkbox']):not([type='radio']), #XS2A-Form select {
/* Increase the font size for input elements, 16px minimum is recommended */
font-size: 16px !important;
}
JS-to-Native Callbacks
The most important steps to be taken are about handling the callbacks the JS-Widget does in your mobile app. For example, when the user finishes the process, you probably want to close the web-view and show the user a specific screen. The same needs to be done when the user aborts.
This can be accomplished with registering callbacks, that notify the host app (your app) from within the Javascript on the hosted page. You might already have callbacks defined such as xs2a.finish() or xs2a.abort() , for which you will need to add some more functionality:
xs2a.finish(function () {
if (window.App) {
// Callback to native Android App
App.finishTransaction();
} else if (window.webkit) {
// Callback to native iOS App
webkit.messageHandlers.callback.postMessage("finished");
}
});
xs2a.abort(function () {
if (window.App) {
// Callback to native Android App
App.abortTransaction();
} else if (window.webkit) {
// Callback to native iOS App
webkit.messageHandlers.callback.postMessage("aborted");
}
});
xs2a.configure({
// ESSENTIAL!
// this needs to be set so that in-app webviews handle redirects properly
'reuse-tab-on-redirect': true
});
Implementation Steps for the Native Apps
In the app, we need some functionality to show the web-view and to deal with the callbacks defined above.
iOS
The following is an example class showing an integration with WKWebView and how the JS-to-Native callbacks are defined and configured:
import UIKit
import WebKit
class WebViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler, UIAdaptivePresentationControllerDelegate {
var webView: WKWebView!
var urlToLoad: URL!
/* Capture Javascript Messages */
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let response = message.body as? String else { return }
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var screenToPresent: UIViewController?
if response == "finished" {
/* The user finished the session */
screenToPresent = storyboard.instantiateViewController(withIdentifier: "successView") as UIViewController
} else if response == "aborted" {
/* User pressed abort button */
screenToPresent = storyboard.instantiateViewController(withIdentifier: "abortedView") as UIViewController
}
if let screenToPresent = screenToPresent {
present(screenToPresent, animated: true, completion: nil)
}
}
override func loadView() {
let contentController = WKUserContentController()
/* Register javascript-to-native callbacks */
/* This lets us use "webkit.messageHandlers.callback.postMessage" in the JS */
contentController.add(self, name: "callback")
let config = WKWebViewConfiguration()
config.userContentController = contentController
let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
webView = WKWebView(frame: frame, configuration: config)
webView.navigationDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
self.presentationController?.delegate = self
webView.load(URLRequest(url: urlToLoad!))
webView.allowsBackForwardNavigationGestures = false
}
init(url: URL) {
self.urlToLoad = url
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
webView.removeFromSuperview()
view = nil
}
}
You can present this web-view like this:
let vc = WebViewController(url: <URL_TO_HOSTED_PAGE>)
self.present(vc, animated: true, completion: nil)
Android
Register the JS-to-Native callbacks:
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.widget.Toast;
import androidx.navigation.fragment.NavHostFragment;
public class WebViewJSInterface {
private static final String TAG = "WebViewJSInterface";
SecondFragment fragment;
public WebViewJSInterface(SecondFragment fragment) {
this.fragment = fragment;
}
@JavascriptInterface
public void finishTransaction() {
Log.d(TAG, "finishTransaction: Finish Transaction on Android");
// navigate to success screen
}
@JavascriptInterface
public void abortTransaction() {
Log.d(TAG, "finishTransaction: Abort Transaction on Android");
// navigate to e.g. abort screen
}
}
Configure and present the web-view:
private void loadXS2AIntoWebView(@NonNull View view, String wizardSessionKey) {
WebView webView = view.findViewById(R.id.main_web_view);
webView.getSettings().setJavaScriptEnabled(true);
// This lets use use window.App in the JS
webView.addJavascriptInterface(new WebViewJSInterface(this), "App");
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
webView.loadUrl(<URL_TO_HOSTED_PAGE>);
}