2

I am trying to render a chart in an Android WebView using HighCharts.

What my app does should be simple : - Load the HTML page and external (but local) css and js files - Load data from the Java part of the app - Call a javascript function with the previously-loaded data as a parameter

I setup my webview by activating Javascript :

mWebView.getSettings().setJavaScriptEnabled(true);

And also by setting a WebClient to catch javascript's console messages :

mWebView.setWebChromeClient(new WebChromeClient() {
        public boolean onConsoleMessage(ConsoleMessage cm) {
            Log.d(TAG, cm.message() + " -- From line "
                    + cm.lineNumber() + " of "
                    + cm.sourceId() );
            return true;
        }

    });

This is my HTML page :

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="stylesheet" type="text/css" href="style.css" />
    <title>Chart</title>
    <script src="jquery.js"></script>
</head>

<body>
    <script src="highstock.js"></script>
    <script src="exporting.js"></script>
    <script language="javascript">
        function plot() {
            console.log("Hello !");
        }
    </script>
    <div id="container" style="height: 100%; width: 100%"></div>
</body>
</html>

I load this page from the app's assets by calling

mWebView.loadUrl("file:///android_asset/page.html");

My external CSS file seems to be read and I suppose the external JS files are also correctly loaded

I read everywhere that I can call my javascript method anytime by calling

mWebView.loadUrl("javascript:plot()");

However, I always get the error

Uncaught ReferenceError: plot is not defined -- From line 1 of null

Is there anything I might have forgotten ? Note that I load my page and call the javascript method right after the loadUrl call.

Thanks !

2 Answers 2

4

Ok, I'm sorry for your time loss. I was looking for an answer for hours, and then within 15 minutes of posting the question I found the solution.

The problem seemed to be the two consecutive calls to loadUrl. 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();");
            }
        }
    });

so that I call the javascript method only when the page is completely loaded. Now it works properly on every call.

Thank you again for your attention !

Sign up to request clarification or add additional context in comments.

1 Comment

The consecutive calls to loadUrl cause a race condition. The problem is that loadUrl("file://..") doesn't complete immediately and so when you call loadUrl("javascript:..") it will sometimes execute before the page has loaded (so it will effectively execute in "about:blank" context) causing errors.
2

Try this:

<body>
    <script src="highstock.js"></script>
    <script src="exporting.js"></script>
    <script language="javascript">
        function plot() {
            console.log("Hello !");
        }

      plot(); //Note the calling of the function within the HTML file once loaded into webView
    </script>
    <div id="container" style="height: 100%; width: 100%"></div>
</body>

And remove the line:

mWebView.loadUrl("javascript:plot()");

If you want to pass data to your javascript function, hen send your data through the URL like this:

mWebView.loadUrl("file:///android_asset/page.html?data=something");

and use:

var param1var = getQueryVariable("data");
function getQueryVariable(variable) {
  var query = window.location.search.substring(1);
  var vars = query.split("&");
  for (var i=0;i<vars.length;i++) {
    var pair = vars[i].split("=");
    if (pair[0] == variable) {
      return pair[1];
    }
  } 
  alert('Query Variable ' + variable + ' not found');
}

in your JavaScript like what is done here. You can also check out this example.

2 Comments

This does indeed work. However, I am going to add parameters to my plot() call, and those parameters will come from my Java code, so I would rather keep my loadUrl() call. Or is there another way ?
This should actually work but it would reload the page everytime I refresh the data. I am planning to use a quite heavy chart library, so I would rather avoid reloading it every time I add a single data to plot. Still, thank you for this method, it might help me later on another page.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.