Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running JavaScript within a Service in Android

I have business logic that is written in JavaScript, this code is shared with other non-android apps.

What is the best way to use the functions in this piece of JavaScript from within a Service in Android.

AFAIK, there are 2 options?

  • V8 that is built into the standard WebView and superfast, no extra apk bloat.
  • Rhino, which is tricky to get going on Android?

Focusing on V8/Webview, when I attempt to access the WebView, with any function, I get;

All WebView methods must be called on the UI thread. Future versions of WebView may not support use on other threads.

The warning being noted, it doesn't even work now. When I set the webviewclient up, I get nothing after loading an URL.

My question is in 3 parts;

1) Has anyone had any success with running javascript in a webview without a UI thread?

2) How do I get results from the functions inside the javascript, does the webview interface "addJavascriptInterface " support loading a parameter and sending it back to the java?

3) If either of the above are impossible.. I guess I'll go get Rhino, any tips would be appreciated, I've only seen a few blogs complaining of issues with regards to getting it going on Android and wondering if there is a "go to" version for android maintained somewhere.

like image 305
Pork 'n' Bunny Avatar asked May 08 '13 13:05

Pork 'n' Bunny


1 Answers

Couldn't find anything with regards to V8 from deep down in a service.

Ended up using Rhino, however a word of warning to anyone following down my footsteps, it's incredibly slow.

Just grab the jar from the official latest distribution of Rhino from https://developer.mozilla.org/en-US/docs/Rhino/Download_Rhino?redirectlocale=en-US&redirectslug=RhinoDownload

js.jar is what you need in the zip. js-14 is a bigger java 1.4 compatible version you don't need.

Integration was a snap just chuck the jar into your libs folder.

Below is me scraping a webpage using javascript (turning the data into better formatted json). With the parse.js script I made coming from the assets folder.

Rhino doesn't come with DOM, and env.js crashes out with stackoverflow errors. Overall, I'd say this solution is slow and not well supported...

public static void sync(Context context, ){
    String url = BASE_URL;

    String html = Utils.inputStreamToString(Utils.getHTTPStream(url));

    timeList.add(System.currentTimeMillis());

    if(html == null){
        Utils.logw("Could not get board list.");
        return;
    }

    String parsingCode = null;
    try {
        parsingCode = Utils.inputStreamToString(context.getAssets().open("parse.js"));
    } catch (IOException e) {
        Utils.logw("Could not get board parser js");
        return;
    }

    // Create an execution environment.
    org.mozilla.javascript.Context cx = org.mozilla.javascript.Context.enter();

    // Turn compilation off.
    cx.setOptimizationLevel(-1);

    try {
        // Initialize a variable scope with bindnings for
        // standard objects (Object, Function, etc.)
        Scriptable scope = cx.initStandardObjects();

        ScriptableObject.putProperty(
                scope, "html", org.mozilla.javascript.Context.javaToJS(html, scope));

        //load up the function
        cx.evaluateString(scope, parsingCode,"parseFunction", 1 , null);

        // Evaluate the script.
        Object result = cx.evaluateString(scope, "myFunction()", "doit:", 1, null);

        JSONArray jsonArray = new JSONArray(result.toString());
like image 99
Pork 'n' Bunny Avatar answered Oct 05 '22 15:10

Pork 'n' Bunny