Android - How to load external javascript files wi

2019-06-14 10:53发布

问题:

I have a WebView containing HTML data. The data is generated at runtime. A main feature of my app is highlighting certain parts of this HTML data. I tried this by using javascript.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_reader_page, container, false);

    webview = (WebView) rootView.findViewById(R.id.resultText);
    webview.getSettings().setJavaScriptEnabled(true);

    String page = makeHTML();
    webview.loadUrl("file:///android_asset/jquery-1.8.2.js");
    webview.loadUrl("file:///android_asset/src_javascript.js");
    webview.loadData(page, "text/html", "UTF-8");

    return rootView;
}

private String makeHTML() {
    StringBuilder sb = new StringBuilder();

    sb.append("<!DOCTYPE html>\n");
    sb.append("<html>\n");
    sb.append("<head>\n");
    sb.append("</head>\n");
    sb.append("<body>\n");
    sb.append(tokenizedText + "\n");
    sb.append("</body>\n");
    sb.append("</html>\n");

    return sb.toString();
}

tokenizedText is my at runtime generated data with this format:

<YT_SEN id="_YT_SEN_0">This is my first sentence.</YT_SEN>
<YT_SEN id="_YT_SEN_1">This is my second sentence.</YT_SEN>
...

When my data is loaded in the WebView, the user can highlight a particular sentence by giving its number. This method then calls the corresponding javascript function:

public void highlightSentence(int sent_id) {
    if (android.os.Build.VERSION.SDK_INT < 19) {
        webview.loadUrl("javascript:highlightSentence('_YT_SEN_" +sent_id+ "', " +color+ ")");
    } else {
        webview.evaluateJavascript("javascript:highlightSentence('_YT_SEN_" +sent_id+ "', " +color+ ")", null);
    }
}

The javascript function for highlighting (defined inside file:///android_asset/src_javascript.js):

function highlightSentence(object,color)
{
    document.getElementById(object).style.backgroundColor = color;
}

The output of Logcat when I execute the highlightSentence method:

I/chromium﹕ [INFO:CONSOLE(1)] "Uncaught ReferenceError: highlightSentence is not defined", source:  (1)

Somehow the WebView can't find the highlightSentence function. I think it's because of the way I load the Javascript and JQuery files. Yet I don't know (and can't find) the proper way to load external js-files within at runtime generated HTML data.

Note: I use the WebView solely for offline use, I have no need for any internet communication whatsoever. WebView seemed like the easiest way to enable dynamic highlighting.

回答1:

It seems the Javascript same origin policy is the root of the problem. The WebView will only load javascript files which are from the same origin as the html. Since no origin for the html was given, the data scheme is used as default. If, however, the data is loaded with the same base url as the javascript files, no problem arises.

Load the html data (with file:///android_asset/javascript/ being the directory of the javascript files):

webview.loadDataWithBaseURL("file:///android_asset/javascript/", page, "text/html", "UTF-8", null);

Then reference the javascript files like this inside the html:

<script src='jquery-1.8.2.js' type='text/javascript'></script>
<script src='src_javascript.js' type='text/javascript'></script>


回答2:

Assuming your javascript is in the assets directory point to it with a file url

 file://android_asset/<some java script file in assets>

file://android_asset/ points to the assets directory in your apk. So you can reference the script in your html when you build it for the webview.

 <script  charset='utf-8' type='text/javascript' 
          src='file://android_asset/myjavascript.js'></script>