Skip to content

Web page integration for QR code scanner

Overview

The main purpose of this document is to describe the flow and working of a feature through which any Web Page opened in the Acrobits Application can ask application to launch the QR Code Scanner and after scanning can receive the Data from the scanned QR Code.

For any Web Page to initiate the QR Code Scanning process from the Native Application, we need to understand the flow of Messages & Information among both. There are three layers involved to complete the process:

  1. Javascript
  2. Web Page
  3. Native Application

Javascript

JavaScript layer is the key module that enables the communication between any Web Page and Native Application. This layer encapsulates all the communication logic and exposes the Interfaces that a Web Page needs to invoke to accomplish the communication. Acrobits has implemented this layer which exposes the Interface for Web Page such that any Web Page can initiate the QR Code Scanning Process.

var softphone = {};

softphone.openQrCodeScanner = function(callback) {
    softphone.qrCodeCallback = callback;

    const userAgent = navigator.userAgent;

    if(/iPad|iPhone|iPod/i.test(userAgent)) {
        window.webkit.messageHandlers.softphoneOpenQrScanner.postMessage("");
    }
    else if(/android/i.test(userAgent)) {
        softphoneJsInterface.openQrScanner();
    }
    else {
        alert('Platform not supported');
    }
};

softphone.onQrCode = function(content) {
    if(content != null) {
        if (softphone.qrCodeCallback) {
            softphone.qrCodeCallback(content);
        }
    }
}

The above JavaScript exposes two interface methods:

  1. softphone.openQrCodeScanner
  2. softphone.onQrCode

As their name suggests one represents the action to be taken and the latter being the result of an action. softphone.openQrCodeScanner is the method that would be invoked by any Web Page to initiate the QR Code scanning process. This method takes a parameter i.e. callback, this callback is a method that will be invoked later when application scans the QR Code and passes the scanned data back to Web Page. So make sure this callback method has a prototype that receives data as parameter.

softphone.onQrCode is another interface method that serves the communication from Native Application to JavaScript Layer. This method actually receives the information from the Native Application and passes it to the Web Page via callback that is received when Web Page initiated the QR Code scanning process via softphone.openQrCodeScanner.

The above script is part of the Native Application which gets injected in the Web Page being opened in the Web Browser Tab or anywhere within the Application.

Web page

For a Web Page it should have some default Interface to initiate the message calls that can be handled by the underlying application. As described in the above section i.e. JavaScript there are two Interface methods one being the initiator and second being the receiver. So following is an example of a simplest webpage which has a Text Field and a Button, Tapping on the Button will initiate the QR Code Scanning Request, which will be handled by the JavaScript Layer and based on the response received from the QR Code Scanning, the result will be displayed in the Text Field.

<!DOCTYPE html>
<html>
    <body>
        <script>
            function callbackFunc(qrValue)
            {
                document.getElementById("qr").value = qrValue;
            }
        </script>
        <input type="text" name="qrcode" id="qr" />
        <br />
        <button onclick="softphone.openQrCodeScanner(callbackFunc)">Click me</button>
    </body>
</html>

The above sample code declares the function named callbackFunc which actually has a parameter which will contain the QR Code Scanned Data which is being set in the text field named qr. The onclick listener for the button "Click me" is instantiating the QR Code Scanning Process via invoking the API Exposed by the JavaScript Layer described in the section JavaScript. I.e. softphone.openQrCodeScanner(callbackFunc), here its passing the method as parameter which will be invoked by the JavaScript layer to provide the Scanned QR Code Data.

Native application

The Native Application has three responsibilities here:

  1. Inject the JavaScript into the Web Page
  2. Receive & Process the Message from JavaScript
  3. Send Result Back to JavaScript

Note: Here we shall be giving the example of iOS Application using Objective-C Code.

Inject the JavaScript into the Web Page

This is the first step involved which enables the communication among the Web Page and Native Application. Following is the code snippet which loads the script file named softphone.js from the target and injects it in the Web Page being loaded.

WKWebViewConfiguration *webViewConfigurations = [[WKWebViewConfiguration alloc] init];
NSString *path = [[NSBundle mainBundle] pathForResource:@"softphone" ofType:@"js"];
if (path)
{
    NSError *error = nil;
    NSString *source = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
    if (!error)
    {
        WKUserContentController *userContentController = [[WKUserContentController alloc] init];
        webViewConfigurations.userContentController = userContentController;
        WKUserScript *userScript = [[WKUserScript alloc] initWithSource:source injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
        [userContentController addUserScript:userScript];
    }
}
[[WKWebView alloc] initWithFrame:CGRectZero configuration:webViewConfigurations];

The above code snippet creates the instance of WKWebViewConfiguration and WKUserContentController, then instantiates the WKUserScript using the JavaScript loaded from softphone.js and in the end instantiates the Instance of WKWebView using the WKWebViewConfiguration instance.

Receive & Process the Message from JavaScript

To receive the Message from JavaScript application needs to implement the message handler for this:

[userContentController addScriptMessageHandler:self name:@"softphoneOpenQrScanner"];

The above line will configure the WebBrowser class to receive the message calls initiated from the JavaScript i.e. softphoneOpenQrScanner

To process the message the WKScriptMessageHandler provides the delegate method:

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    if ([message.name isEqualToString:@"softphoneOpenQrScanner"])
    {
        // Process the message call here
    }
}

Send Result Back to JavaScript

To pass the result back to JavaScript Layer so that it can be passed back to the Web Page, application needs to invoke the Interface Method that is exposed in the Injected JavaScript described in the section above i.e. softphone.onQrCode. This method takes the parameter that would be the scanned QR Code data. On iOS WKWebView has a method evaluateJavaScript which can be invoked to initiate the Injected JavaScript Method Call:

NSString *value = @"Scanned QRCode Data";
NSString *function = [[NSString alloc] initWithFormat: @"softphone.onQrCode('%@')", value];
[_webView evaluateJavaScript:function completionHandler:nil];