如何在Android上执行JavaScript?

50

我有一段使用 ScriptEngineManager 和 ScriptEngine 类在Java中执行JavaScript代码的代码。但是它能够在Java SE中正常工作,但在Android环境下无法正常工作 - SDK显示缺少类的错误。是否可能在Android中执行JS代码?谢谢。


1
如果搜索引擎出现问题,我相信谷歌会在这里找到一些重复的内容。右侧的“相关”区块至少列出了其中一个。 - Fredrik
可能是重复问题:https://dev59.com/5msz5IYBdhLWcg3w9ssQ和https://dev59.com/nFrUa4cB1Zd3GeqPhjVl - Alex K
10个回答

22

AndroidJSCore 是一个非常好的库。这里还有另一个我写的用于评估 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)
  }
});

它在幕后创建一个WebView。适用于Android 3及以上版本。


我该如何在Java中调用Cryptojs文件的加密方法来加密参数?我有点困惑,请帮忙。 - Animesh Jena
4
更新2018年: AndroidJSCore已被 LiquidCore取代,它基于V8。它不仅包含了V8引擎,还可以使用所有Node.js的功能。 - Eric Lange
@Evgenii 不错的个人头像。Beluga是革命 :) - Temüjin

13
你可以使用继承自View类的Webview。创建一个XML标记并使用findViewById()函数在活动中使用。但是要使用JavaScript,您可以创建一个包含JavaScript代码的HTML文件。下面的示例可能会有所帮助。
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

请记住,JS代码将在WebView中运行而不是本地环境中运行,因此您可能会在模拟器中遇到延迟或FPS缓慢的情况。但是,在实际手机上使用时,代码可能会快速运行,这取决于手机的速度。


9

你的链接已经失效了,能否修复一下呢? - Jonas Czech
虽然方式不太好(因为这不是我的博客),但archive.org保存了一份副本:https://web.archive.org/web/20100201235324/http://divineprogrammer.blogspot.com/2009/11/javascript-rhino-on-android.html - Fredrik

9
2018年更新: AndroidJSCore已经被LiquidCore取代,它基于V8。不仅包含了V8引擎,还提供了所有Node.js功能。

原始回答:AndroidJSCore是Webkit的JavaScriptCore C库的Android Java JNI封装。它受到iOS 7中原生包含的Objective-C JavaScriptCore框架的启发。在应用程序中本地使用JavaScript而无需使用注入到庞大、缓慢、受安全限制的WebView中的JavaScript是非常有用的,这对于许多类型的应用程序(如游戏或支持插件的平台)非常有用。然而,它的使用受到人为限制,因为该框架仅受到iOS的支持。大多数开发者希望使用能够跨越主要移动操作系统的技术。AndroidJSCore旨在支持此要求。

例如,您可以共享Java对象并进行异步调用:

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

第一个链接坏了,有人修复一下吗? - pavi2410
@Pavitra 已修复。 - Eric Lange

7
javax.script包不是Android SDK的一部分。您可以在WebView中执行JavaScript,如此处所述。您可以尝试使用Rhino,如此处所述。您还可以查看Scripting Layer for Android项目。请注意保留HTML标记。

sl4a 是一个过时的库。 - Vlad

7
我也在寻找在Android上运行javascript的方法,并发现了j2v8库。这是针对Google的v8引擎的Java包装器。
要使用它,请添加依赖项:
compile 'com.eclipsesource.j2v8:j2v8_android:3.0.5@aar'

它有相当简单的API,但我除了maven repository中的javadoc之外,在网上没有找到任何文档。他们博客上的文章也很有用。

这篇文章中的代码示例:

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

最新版本显示为4.5.0。如何在“compile 'com.eclipsesource.j2v8:j2v8_android:3.0.5@aar'”中替换它。用4.5.0替换3.0.5不起作用。 - AndroidGuy
2
@AndroidGuy 最新的 Android 版本是 3.0.5,请查看 https://mvnrepository.com/artifact/com.eclipsesource.j2v8/j2v8_android - Keammoort
不要忘记导入:import com.eclipsesource.v8.V8; - ybdesire

6
您可以使用Rhino库在没有WebView的情况下执行JavaScript代码。
首先下载Rhino,解压缩后将js.jar文件放置在libs文件夹中。它非常小,因此您不必担心由于这个外部jar文件而使您的apk文件变得非常大。
以下是一些简单的代码,用于执行JavaScript代码。
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();
}

您可以在我的文章中查看更多详细信息。

1
我刚发现了应用程序“JavaScript for Android”,它是Java的Rhino JavaScript引擎。它可以使用所有Java类,因此具有很大的潜力。问题是它可能会变慢,因为它不是真正优化的(CPU负载很重)。还有另一个名为Nashorn的JavaScript引擎,但不幸的是它不能在Google的DalvikVM Java引擎上运行(不支持Oracle Java引擎的优化)。我希望Google能够跟上这个进展,那就太好了!

1
鉴于 ScriptEngineManagerScriptEngineJDK 的一部分,而 Android SDK 不同于 JDK,因此我认为您不能使用这些类来处理 Android 下的 JavaScript。
您可以查看 Android SDK 的 参考文档/软件包索引,了解其中包含哪些类(即可开箱即用的内容)以及缺少哪些类。

0
如果您想在Chrome浏览器上执行一些JavaScript代码,请按照问题中的说明复制此代码并将其粘贴到地址栏中:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接