Android-specific Mobile Widget

Generate widget config

Read more about widget config

  1. Need to get otp
  2. Prepare link to css file
  3. Create config object with specific configuration
  4. Get base64 string from config object
private void generateWidgetConfig() {
    Map<String, Object> config = new HashMap<>();
    config.put("token", mOtp);
    config.put("cardId", mCardId);
    config.put("styleUrl", mStyleUrl);
    config.put("cssClass", mCssClass);

    Map<String, Object> cardholderName = new HashMap<>();
    cardholderName.put("display", false);
    config.put("cardholderName", cardholderName);

    try {
        byte[] jsonData = new ObjectMapper().writeValueAsBytes(config);
        String widgetConfig = Base64.getEncoder().encodeToString(jsonData);
    } catch (IOException e) {
        Log.e("Error", e.getMessage());
    }
}

Generate HTML for WebView

This is an example of a function to get a string with html. For apiHostPci check this link. traceId should be the same as for OTP generation request.

private String getHtml() {
    String iframeUrl = apiHostPci + "/card-details/widget?traceId=" + traceId + "&params=" + widgetConfig;

    return "<!DOCTYPE html>\n" +
            "<html>\n" +
            "  <script>\n" +
            "    window.addEventListener('message', function(event) {\n" +
            "      window.Android.handleMessage(JSON.stringify(event.data));\n" +
            "    });\n" +
            "  </script>\n" +
            "  <head>\n" +
            "    <meta charset=\"utf-8\">\n" +
            "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" + // Add initial-scale to viewport meta tag
            "    <title>Card</title>\n" +
            "    <style>\n" +
            "      body, html {\n" +
            "        margin: 0;\n" +
            "        padding: 0;\n" +
            "        width: 100vw;\n" +
            "        height: 100vh;\n" +
            "        background-color: transparent;\n" +
            "      }\n" +
            "      iframe {\n" +
            "        width: 100%;\n" +
            "        height: 100%;\n" +
            "        background-color: transparent;\n" +
            "      }\n" +
            "    </style>\n" +
            "  </head>\n" +
            "  <body>\n" +
            "    <iframe\n" +
            "      src=\"" + iframeUrl + "\"\n" +
            "      title=\"Card Details\"\n" +
            "      width=\"100%\"\n" +
            "      height=\"100%\"\n" +
            "      frameBorder=\"0\"\n" +
            "      id=\"card-details-widget-frame\"\n" +
            "      allow=\"clipboard-read; clipboard-write\"\n" +
            "    />\n" +
            "  </body>\n" +
            "</html>";
}

Take a look on this code. It will allow you to receive messages from iframe with some events

window.addEventListener('message', (event) => {
  window.Android.handleMessage(JSON.stringify(event.data));
});

Configure WebView

Example:

WebView wvContent = this.findViewById(R.id.pci_widget_web_view);
wvContent.setBackgroundColor(Color.TRANSPARENT);
wvContent.getSettings().setJavaScriptEnabled(true);

URL baseUrl = new URL("https://localhost");

wvContent.loadDataWithBaseURL(
    baseUrl.toString(),
    getHtml(),
    "text/html",
    "UTF-8",
    null
);

Keep in mind, you:

  • need to enable setJavaScriptEnabled
  • need to specify baseUrl: 'https://localhost'

iFrame Events

You may receive messages from iframe with events. Example of handleMessage callback:

// Define JavaScript interface object
JavaScriptInterface jsInterface = new JavaScriptInterface();

// Add JavaScript interface object to WebView
webView.addJavascriptInterface(jsInterface, "Android");

// Define Java object to serve as JavaScript interface
public class JavaScriptInterface {
    @android.webkit.JavascriptInterface
    public void handleMessage(String message) {
        // Handle message received from JavaScript
        System.out.println("Message received from JavaScript: " + message);
    }
}