Muhammad Saidur Rahman
Muhammad Saidur Rahman

Reputation: 548

javascript not working when webview loaded from internal html file in Android

The JavaScript is loaded properly when webview loaded using weblink like: example.com/test but JavaScript is not working when webview loaded from internal html file from assets folder.

Html file code:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>payment</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>


<!-- The Payment Form -->
<form id="iframes" action="" method="GET">
    <div class="form-group">
        <label for="iframesCardNumber">Card Number:</label>
        <div class="iframeholder" id="iframesCardNumber"></div>
    </div>
    <div class="form-group">
        <label for="iframesCardExpiration">Card Expiration:</label>
        <div class="iframeholder" id="iframesCardExpiration"></div>
    </div>
    <div class="form-group">
        <label for="iframesCardCvv">Card CVV:</label>
        <div class="iframeholder" id="iframesCardCvv"></div>
    </div>

    <input type="submit" class="btn btn-primary" value="Submit" />
</form>


<!-- The SecureSubmit Javascript Library -->
<script type="text/javascript" src="https://api2.heartlandportico.com/SecureSubmit.v1/token/2.1/securesubmit.js"></script>
<!-- The Integration Code -->
<script type="text/javascript">
  (function (document, Heartland) {
    // Create a new `HPS` object with the necessary configuration
    var hps = new Heartland.HPS({
      publicKey: '..............',
      type:      'iframe',
      // Configure the iframe fields to tell the library where
      // the iframe should be inserted into the DOM and some
      // basic options
      fields: {
        cardNumber: {
          target:      'iframesCardNumber',
          placeholder: '•••• •••• •••• ••••'
        },
        cardExpiration: {
          target:      'iframesCardExpiration',
          placeholder: 'MM / YYYY'
        },
        cardCvv: {
          target:      'iframesCardCvv',
          placeholder: 'CVV'
        }
      },
      // Collection of CSS to inject into the iframes.
      // These properties can match the site's styles
      // to create a seamless experience.
      style: {
        'input[type=text],input[type=tel]': {
            'box-sizing':'border-box',
           'display': 'block',
            'width': '100%',
            'height': '34px',
            'padding': '6px 12px',
            'font-size': '14px',
            'line-height': '1.42857143',
            'color': '#555',
            'background-color': '#fff',
            'background-image': 'none',
            'border': '1px solid #ccc',
            'border-radius': '4px',
            '-webkit-box-shadow': 'inset 0 1px 1px rgba(0,0,0,.075)',
            'box-shadow': 'inset 0 1px 1px rgba(0,0,0,.075)',
            '-webkit-transition': 'border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s',
            '-o-transition': 'border-color ease-in-out .15s,box-shadow ease-in-out .15s',
            'transition': 'border-color ease-in-out .15s,box-shadow ease-in-out .15s'
        },
        'input[type=text]:focus,input[type=tel]:focus': {
            'border-color': '#66afe9',
          'outline': '0',
          '-webkit-box-shadow': 'inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)',
          'box-shadow': 'inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)'
        },
        'input[type=submit]' : {
                    'box-sizing':'border-box',
                'display': 'inline-block',
              'padding': '6px 12px',
              'margin-bottom': '0',
              'font-size': '14px',
              'font-weight': '400',
              'line-height': '1.42857143',
              'text-align': 'center',
              'white-space': 'nowrap',
              'vertical-align': 'middle',
              '-ms-touch-action': 'manipulation',
              'touch-action': 'manipulation',
              'cursor': 'pointer',
              '-webkit-user-select': 'none',
              '-moz-user-select': 'none',
              '-ms-user-select': 'none',
              'user-select': 'none',
              'background-image': 'none',
              'border': '1px solid transparent',
              'border-radius': '4px',
              'color': '#fff',
              'background-color': '#337ab7',
              'border-color': '#2e6da4'
        },
        'input[type=submit]:hover':{
                'color': '#fff',
            'background-color': '#286090',
            'border-color': '#204d74'
        },
        'input[type=submit]:focus, input[type=submit].focus':{
            'color': '#fff',
            'background-color': '#286090',
            'border-color': '#122b40',
            'text-decoration': 'none',
            'outline': '5px auto -webkit-focus-ring-color',
                    'outline-offset': '-2px'
        }
      },
      // Callback when a token is received from the service
      onTokenSuccess: function (resp) {
        alert('Here is a single-use token: ' + resp.token_value);
      },
      // Callback when an error is received from the service
      onTokenError: function (resp) {
        alert('There was an error: ' + resp.error.message);
      }
    });

    // Attach a handler to interrupt the form submission
    Heartland.Events.addHandler(document.getElementById('iframes'), 'submit', function (e) {
      // Prevent the form from continuing to the `action` address
      e.preventDefault();
      // Tell the iframes to tokenize the data
      hps.Messages.post(
        {
          accumulateData: true,
          action: 'tokenize',
          message: '........'
        },
        'cardNumber'
      );
    });
  }(document, Heartland));
</script>
</body>
</html>

What I guess the css code inside the JavaScript does not load properly. But it works fine when loaded from sample website link like example.com/test

The relevant Java code is given below:

public static String wikiLink = "file:///android_asset/test.html"

..............
..............
.............
        WebSettings settings = webView.getSettings();

        //Using JavaScript in WebView, it will enable Javascript support for your website
        settings.setJavaScriptEnabled(true);

        //Zoom control
        settings.setBuiltInZoomControls(true);
        settings.setSupportZoom(true);
        settings.setDisplayZoomControls(false);

        //Handling Page Navigation
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                wikiLink = url;
                view.loadUrl(url);
                return true;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                webView.setVisibility(View.VISIBLE);
                layoutProgress.setVisibility(View.GONE);
                progressBar.setIndeterminate(false);
                super.onPageFinished(view, url);

            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                layoutProgress.setVisibility(View.VISIBLE);
                progressBar.setIndeterminate(true);
                super.onPageStarted(view, url, favicon);
            }
        });
        //End of Handling Page Navigation

        webView.setWebChromeClient(new WebChromeClient(){
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                Log.d("LogTag", message);
                result.confirm();
                return true;
            }
        });

        webView.getSettings().setUserAgentString("Test");
        webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        webView.getSettings().setDomStorageEnabled(true);
        webView.getSettings().setAllowUniversalAccessFromFileURLs(true);

        if(isOnline()) {
            if (webViewBundle == null) {
                webView.loadUrl(wikiLink);
            } else {
                webView.restoreState(webViewBundle);
            }
        } else {
            String summary = "<html><body><font color='red'>No Internet Connection</font></body></html>";
            webView.loadData(summary, "text/html", null);
            toast("No Internet Connection.");
        }

What can be done to resolve this issue?

Upvotes: 0

Views: 1222

Answers (3)

Shane L.
Shane L.

Reputation: 56

The Heartland JavaScript library needs to be loaded over the HTTP/HTTPS scheme, not file, as it uses the Window.postMessage API to communicate between the parent window (your WebView contents) and the child iframe windows. This is a restriction in place at the browser and Heartland library levels to help with security and cross-origin resource sharing (CORS).

The only way around this would be to use native inputs / controls within your Android application.

Upvotes: 0

Oliver
Oliver

Reputation: 11

i got the issue that the webview "loadData" did not display content after the first "#" in html source before updating Chrome browser everything was fine, sice update - i got the issue.

changing from loadData to loadDataWithBaseURL solved that problem for me

Upvotes: 1

user3339958
user3339958

Reputation:

Maybe the page wasn't properly loaded yet while I was already calling the javascript function.

I added a load listener on the WebView like this

  mWebView.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (url.equals("file:///android_asset/page.html")) {
                mWebView.loadUrl("javascript:plot();");
            }
        }
    });

Now it works properly on every call.

Thank you again for your attention!

Upvotes: 0

Related Questions