Skip to toolbar
Home » Software » 2015/04/05/Execute-JavaScript-in-Android-without-WebView/

2015/04/05/Execute-JavaScript-in-Android-without-WebView/

Spread the love

The reasons I need do some Javascript code in Andriod based project was because of me running the background thread (in doinbackground part in an Asynctask), I want want to use Webview

Why not WebView

The first problem here is that Webview is heavy which then makes it run slow overall which is bigger problem when you are doing large kind of proejct and you need to add as well a lot of webview related setting which slows things done further when you want to do things like code snippet so my thoughts it’s not worth doing it because of these sort of problems overall.

Second main points I want to make which is UI related webview should be created in a UI thread which will then load Javascript code in the background of the thread then pass the results bac kto the UI it’s workable overall but it’s not safe in my thoughts.

If you can call methods on webview from any other thread than your app UI thread it can cause unexpected results. https://developer.android.com/guide/webapps/migrating#Threads

Last but not final Webview is fragmented after Android 4.4 or level 19 is using Webview based on Chromium style and even oo this is a good thing my mindset is 4.3 so a older version which could give you problems. You should try and code two versions of Webview in related code to just try and make it work

A lot of code should be re-wrote.

Luckily, the good people in Mozilla make a project called Rhino. It is typically embedded into Java applications to provide scripting to end users.

How to use Rhino?

Rhino is a open source project, you can get the source code using this command:

git clone https://github.com/mozilla/rhino.git

Of course, you don’t have to get the source code. If you want to use it in your Android project. Download Rhino first, unzip it, put the js.jar file under libs folder. It is very small, so you don’t need to worry your apk file will be ridiculously large because of this one external jar.

Here is some simple code to execute JavaScript code.

Object[] params = new Object[] { "javaScriptParam" };

// Every Rhino VM begins with the enter()
// This Context is not Android's Context
Context rhino = Context.enter();

// Turn off optimization to make Rhino Android compatible
rhino.setOptimizationLevel(-1);
try {
    Scriptable scope = rhino.initStandardObjects();

    // Note the forth argument is 1, which means the JavaScript source has
    // been compressed to only one line using something like YUI
    rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);

    // Get the functionName defined in JavaScriptCode
    Object obj = scope.get(functionNameInJavaScriptCode, scope);

    if (obj instanceof Function) {
        Function jsFunction = (Function) obj;

        // Call the function with params
        Object jsResult = jsFunction.call(rhino, scope, scope, params);
        // Parse the jsResult object to a String
        String result = Context.toString(jsResult);
    }
} finally {
    Context.exit();
}

As you can see, it is quite easy. You can dig up more in Rhino document.

Proguard & Obfuscation

You can set up Rhino’s proguard setting by adding this following line into your proguard-android.txt file.

-keep class org.mozilla.javascript.** { *; }

When you run the assembleRelease task, with minifyEnabled true of course, you still can see a lot of warning like these:

Warning: org.mozilla.javascript.tools.shell.JSConsole: can't find referenced class javax.swing.JMenu
Warning: org.mozilla.javascript.tools.shell.JSConsole: can't find referenced class javax.swing.JMenu
Warning: org.mozilla.javascript.tools.shell.JSConsole: can't find referenced class javax.swing.JMenu
Warning: org.mozilla.javascript.tools.shell.JSConsole: can't find referenced class javax.swing.ButtonGroup
Warning: org.mozilla.javascript.tools.shell.JSConsole: can't find referenced class javax.swing.JScrollPane
Warning: org.mozilla.javascript.tools.shell.JSConsole: can't find referenced class java.awt.event.ActionEvent
Warning: org.mozilla.javascript.tools.shell.JSConsole: can't find referenced class java.awt.event.ActionEvent
Warning: org.mozilla.javascript.tools.shell.JSConsole$1: can't find referenced class javax.swing.filechooser.FileFilter
Warning: org.mozilla.javascript.tools.shell.JSConsole$2: can't find referenced class java.awt.event.WindowAdapter
Warning: org.mozilla.javascript.tools.shell.JSConsole$2: can't find referenced class java.awt.event.WindowEvent
Warning: org.mozilla.javascript.tools.shell.JSConsole$2: can't find referenced class java.awt.event.WindowEvent
Warning: org.mozilla.javascript.xml.impl.xmlbeans.LogicalEquality: can't find referenced class org.apache.xmlbeans.XmlCursor
Warning: org.mozilla.javascript.xml.impl.xmlbeans.LogicalEquality: can't find referenced class org.apache.xmlbeans.XmlCursor
Warning: org.mozilla.javascript.xml.impl.xmlbeans.LogicalEquality: can't find referenced class org.apache.xmlbeans.XmlCursor

Luckily, evan with these warnings, the app runs fine. You can ignore them(that’s what I do), or adding this line inot your proguard-android.txt file.

-dontwarn org.mozilla.javascript.**
, , , , , , , , , , , , , , , , , , , , , , , , , , , , ,

About

Leave a Reply