46

I have code which uses ScriptEngineManager, ScriptEngine class for executing JavaScript code using Java. But it works fine in Java SE, and doesn't work in Android - SDK show error of missing classes. Is it possible to execute JS code in Android? Thank you.

user1078760
  • 709
  • 2
  • 10
  • 17
  • 1
    FYI, if the search engine is broken I am sure google will find a couple of the duplicates in here. The "related" block to the right lists at least one of them. – Fredrik Dec 04 '11 at 07:57
  • Possible duplicate: http://stackoverflow.com/questions/7544671/how-to-call-javascript-from-android & http://stackoverflow.com/questions/7042710/android-is-there-a-way-to-execute-javascript-from-my-app – Alex K Dec 04 '11 at 10:38

10 Answers10

20

AndroidJSCore is a great one. And here is another little library I wrote for evaluating JavaScript:

https://github.com/evgenyneu/js-evaluator-for-android

jsEvaluator.evaluate("function hello(){ return 'Hello world!'; } hello();", new JsCallback() {
  @Override
  public void onResult(final String result) {
    // get result here (optional)
  }
});

It creates a WebView behind the scenes. Works on Android version 3 and newer.

Evgenii
  • 33,381
  • 26
  • 125
  • 160
  • How can I call the encrypt method of Cryptojs file to encrypt the parameters in java? Got a little confusion over here. Please help. – Animesh Jena Mar 21 '18 at 20:59
  • 4
    **UPDATE 2018:** AndroidJSCore has been superseded by [LiquidCore](https://github/LiquidPlayer/LiquidCore), which is based on V8. Not only does it include the V8 engine, but all of Node.js is available as well. – Eric Lange Sep 24 '18 at 08:40
12

You can use Webview which inherits View class. Make an XML tag and use findViewById() function to use in the activity. But to use the JavaScript, you can make a HTML file containing the JavaScript code. The example blelow might help.

Webview browser=(Webview) findViewById(R.main.browser); //if you gave the id as browser
browser.getSettings().setJavaScriptEnabled(true); //Yes you have to do it
browser.loadUrl("file:///android_asset/JsPage.html"); //If you put the HTML file in asset folder of android

Remember that the JS will run on WebView, not in native environment, thus you might experience a lag or slow FPS in emulator. However when using on an actual phone, the code may run fast, depending on how fast is your phone.

axel22
  • 31,198
  • 9
  • 120
  • 134
noob
  • 17,131
  • 18
  • 103
  • 168
8

UPDATE 2018: AndroidJSCore has been superseded by LiquidCore, which is based on V8. Not only does it include the V8 engine, but all of Node.js is available as well.

Original answer: AndroidJSCore is an Android Java JNI wrapper around Webkit's JavaScriptCore C library. It is inspired by the Objective-C JavaScriptCore Framework included natively in iOS 7. Being able to natively use JavaScript in an app without requiring the use of JavaScript injection on a bloated, slow, security-constrained WebView is very useful for many types of apps, such as games or platforms that support plugins. However, its use is artificially limited because the framework is only supported on iOS. Most developers want to use technologies that will scale across both major mobile operating systems. AndroidJSCore was designed to support that requirement.

For example, you can share Java objects and make async calls:

public interface IAsyncObj {
    public void callMeMaybe(Integer ms, JSValue callback) throws JSException;
}
public class AsyncObj extends JSObject implements IAsyncObj {
    public AsyncObj(JSContext ctx) throws JSException { super(ctx,IAsyncObj.class); }
    @Override
    public void callMeMaybe(Integer ms, JSValue callback) throws JSException {
        new CallMeLater(ms).execute(callback.toObject());
    }

    private class CallMeLater extends AsyncTask<JSObject, Void, JSObject> {
        public CallMeLater(Integer ms) {
            this.ms = ms;
        }
        private final Integer ms;
        @Override
        protected JSObject doInBackground(JSObject... params) {
            try {
                Thread.sleep(ms);
            } catch (InterruptedException e) {
                Thread.interrupted();
        }
            return params[0];
        }

        @Override
        protected void onPostExecute(JSObject callback) {
            JSValue args [] = { new JSValue(context,
                    "This is a delayed message from Java!") };
             try {
                 callback.callAsFunction(null, args);
             } catch (JSException e) {
                 System.out.println(e);
             }
        }
    }
}

public void run() throws JSException {
    AsyncObj async = new AsyncObj(context);
    context.property("async",async);
    context.evaluateScript(
        "log('Please call me back in 5 seconds');\n" +
        "async.callMeMaybe(5000, function(msg) {\n" +
        "    alert(msg);\n" +
        "    log('Whoomp. There it is.');\n" +
        "});\n" +
        "log('async.callMeMaybe() has returned, but wait for it ...');\n"
    );
}
Eric Lange
  • 1,535
  • 2
  • 17
  • 22
8

http://divineprogrammer.blogspot.com/2009/11/javascript-rhino-on-android.html will get you started. ScriptEngine is a java thing. Android doesn't have a JVM but a DalvikVM which is not identical but similar.

Fredrik
  • 5,649
  • 2
  • 23
  • 31
  • Your link is broken. Could you fix it ? – JonasCz Jan 13 '16 at 15:31
  • Not in a very good way (as it is not my blog) but archive.org has a saved copy: https://web.archive.org/web/20100201235324/http://divineprogrammer.blogspot.com/2009/11/javascript-rhino-on-android.html – Fredrik Jan 13 '16 at 23:36
7

I was also looking for a way to run javascript on Android and came across j2v8 library. This is a java wrapper for Google's v8 engine.

To use it add a dependency:

compile 'com.eclipsesource.j2v8:j2v8_android:3.0.5@aar'

It has pretty simple api, but I haven't found any docs online apart from javadoc in maven repository. The articles on their blog are also useful.

Code sample from this article:

public static void main(String[] args) {
    V8 runtime = V8.createV8Runtime();

    int result = runtime.executeIntegerScript(""
        + "var hello = 'hello, ';\n"
        + "var world = 'world!';\n"
        + "hello.concat(world).length;\n");

    System.out.println(result);

    runtime.release();
}
Keammoort
  • 3,035
  • 15
  • 20
  • The latest version shows 4.5.0. How to replace it in "compile 'com.eclipsesource.j2v8:j2v8_android:3.0.5@aar'". Replacing 3.0.5 with 4.5.0 does not work. – AndroidGuy Jan 12 '17 at 09:37
  • 2
    @AndroidGuy latest version for Android is 3.0.5, see https://mvnrepository.com/artifact/com.eclipsesource.j2v8/j2v8_android – Keammoort Jan 12 '17 at 11:26
  • Do not forget the import: `import com.eclipsesource.v8.V8;` – ybdesire Aug 17 '18 at 06:42
7

The javax.script package is not part of the Android SDK. You can execute JavaScript in a WebView, as described here. You perhaps can use Rhino, as described here. You might also take a look at the Scripting Layer for Android project.

Ted Hopp
  • 222,293
  • 47
  • 371
  • 489
6

You can use Rhino library to execute JavaScript without WebView.

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();
}

You can see more details at my post.

Wesley
  • 3,949
  • 6
  • 35
  • 58
1

I just found the App JavaScript for Android, which is the Rhino JavaScript engine for Java. It can use all Java-classes, so it has BIG potential. The problem is it might be slow, since it is not really optimized (heavy CPU load). There is another JavaScript engine named Nashorn, but that unfortunately doesn't works on Google's DalvikVM Java engine (does not support the optimizations of Oracle Java engine). I hope Google keeps up with that, I would just love it!

kungfooman
  • 3,696
  • 1
  • 32
  • 25
1

Given that ScriptEngineManager and ScriptEngine are part of the JDK and Android SDK is not the same thing as the JDK I would say that you can't use these classes to work with JavaScript under Android.

You can check the Android SDK's reference documentation/package index to see what classes are included (what can you work on Android out of the box) and which of them are missing.

Kohányi Róbert
  • 8,681
  • 3
  • 46
  • 74
0

If you want to run some javascript code on chrome browser as per the question copy this code and paste it into address bar:

data:text/html, <html contenteditable> <title> Notepad </title> <script> alert('Abhasker Alert Test on Mobile'); </script> </html>

AbhiNickz
  • 937
  • 2
  • 15
  • 25