美文网首页android开发
Android 使用 Rhino JS 解析引擎执行JS代码

Android 使用 Rhino JS 解析引擎执行JS代码

作者: JzyCc | 来源:发表于2019-02-19 01:53 被阅读0次

Rhino 简介

官方示例

Android】不使用WebView来执行Javascript脚本(Rhino)

Rhino 是一个由 Java 实现的 JS 解析引擎,可以很容易的接入到 Java 项目中,对于现在的大前端的趋向中,可以利用 Rhino 来实现相关的跨平台渲染功能。

个人理解相比于现在更主流的 chrome v8 引擎,Rhino 的优势在于在 Java 项目容易使用,同时不需要去踩交叉编译的坑。但是缺点也在于只适用于 Java 项目,v8 在功能等方面应该是更胜一筹。

但是如果说只是自己或者小范围使用的话,rhino 可以做为一个很好的选择。

关于 JS 引擎的选择可以参考

在 Android 中使用 Rhino

首先要去下载一个 rhino 的包
下载链接

我下的是 1.7.9 版本的,将 rhino 的包放到如下位置。


image.png

同时在gradle文件中引用这个包。

    implementation files('libs/rhino-1.7.9.jar')

JS 代码运行时回调给 Java

接下来就可以开始使用 rhino 了,现写一个 JS 代码,做为测试可以将代码做为字符串传入,我这里贴出来方便查看。

//通过反射获取对应 Java类中名为 rhino_test(String) 的方法
var method_Api_rhino_test = ScriptAPI.getMethod("rhino_test",[java.lang.String])
function rhino_test() {
    var str = "jzy666";
    //执行反射获取的方法,并传入字符串参数
    method_Api_rhino_test .invoke(javaContext,str);
}
rhino_test();

创建一个 JsEngine 类

public class JsEngine{
    private Class clazz;
    private org.mozilla.javascript.Context rhino;
    private Scriptable scope;

    private String jsCode = "";
    private String testCode =
            "var method_Api_rhino_test = ScriptAPI.getMethod(\"rhino_test\",[java.lang.String])\n" +
            "function rhino_test() {\n" +
            "    var str = \"jzy666\";\n" +
            "    method_Api_rhino_test.invoke(javaContext,str);\n" +
            "}" +
            "rhino_test()";
    public JsEngine(){
        this.clazz = JsEngine.class;
        initJsEngine();
    }

    private void initJsEngine(){
        jsCode = "var ScriptAPI = java.lang.Class.forName(\"" + JsEngine.class.getName() + "\", true, javaLoader);\n"
                + testCode;
    }

    public void request(){
        rhino = org.mozilla.javascript.Context.enter();
        rhino.setOptimizationLevel(-1);
        try{
            scope = rhino.initStandardObjects();
            // 这两句是设置当前的类做为上下文以及获取当前的类加载器,以便于 rhino 通过反射获取档期类
            ScriptableObject.putProperty(scope,"javaContext", org.mozilla.javascript.Context.javaToJS(this,scope));
            ScriptableObject.putProperty(scope,"javaLoader", org.mozilla.javascript.Context.javaToJS(clazz.getClassLoader(),scope));
            //执行 js 代码
            Object x = rhino.evaluateString(scope, jsCode, clazz.getSimpleName(), 1, null);
        }finally {
            //退出
            org.mozilla.javascript.Context.exit();
        }
    }
    // 对应类中需要需要被调用的方法,可以做为 JS 代码执行时的回调
    public void rhino_test(String str){
        Log.i("jzy111","rhino_test: " + str);
    }
}

我们先执行一下,直接在 Activity 中使用。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        JsEngine jsEngine = new JsEngine();
        jsEngine.request();
    }
}  

运行程序后,可以在 logcat 中看到这样一条打印

2019-02-19 01:21:44.164 15751-15751/com.example.jzycc.rhino I/jzy111: rhino_test: jzy666

正是我们在上面 JsEngine 类中 rhino_test() 方法中写的打印语句打印的内容, 具体的内容就是 JS 代码执行时,通过反射调用 JsEngine 类中的 rhino_test() 并且传入需要的参数。

Java 调用 JS 代码

如果我们需要在 Java 中调用 JS 代码,则添加如下方法

    public void callFunction(String functionName,Object[] functionParams){
        Function function = (Function) scope.get(functionName,scope);
        function.call(rhino,scope,scope,functionParams);
    }

在使用这个方法前,我们先修改一下 JS 代码

//通过反射获取对应 Java类中名为 rhino_test(String) 的方法
var method_Api_rhino_test = ScriptAPI.getMethod("rhino_test",[java.lang.String])
// 这里设置了传入参数
function rhino_test(str) {
   //var str = "jzy666";
   //执行反射获取的方法,并传入字符串参数
   method_Api_rhino_test .invoke(javaContext,str);
}
//我们将执行方法的语句去掉
//rhino_test();

修改 request() 方法

    public void request(){
        rhino = org.mozilla.javascript.Context.enter();
        rhino.setOptimizationLevel(-1);
        try{
            scope = rhino.initStandardObjects();
            // 这两句是设置当前的类做为上下文以及获取当前的类加载器,以便于 rhino 通过反射获取档期类
            ScriptableObject.putProperty(scope,"javaContext", org.mozilla.javascript.Context.javaToJS(this,scope));
            ScriptableObject.putProperty(scope,"javaLoader", org.mozilla.javascript.Context.javaToJS(clazz.getClassLoader(),scope));
            //执行 js 代码
            Object x = rhino.evaluateString(scope, jsCode, clazz.getSimpleName(), 1, null);
            //js 代码执行后,我们来调用需要调用的方法
            callFunction("rhino_test",new Object[]{"我调用了方法"});
        }finally {
            //退出
            org.mozilla.javascript.Context.exit();
        }
    }

这里我们在 JS 代码执行后调用之前添加的 callFunction() 方法,再重新运行程序可以看到如下输出

2019-02-19 01:43:10.210 16761-16761/com.example.jzycc.rhino I/jzy111: rhino_test: 我调用了方法

JS 获取 Java 传入的值

如果说 JS 需要 我们本地计算好的值,可以这样使用。

还是先修改下 JS 代码。

  //  这里添加一个 getJavaValue() 方法, 同样需要在对应的 Java 类中添加一个方法
var method_Api_getJavaValue = ScriptAPI.getMethod("getJavaValue")
function getJavaValue(){
     return method_Api_getJavaValue.invoke(javaContext);
}

//通过反射获取对应 Java类中名为 rhino_test(String) 的方法
var method_Api_rhino_test = ScriptAPI.getMethod("rhino_test",[java.lang.String])
// 这里设置了传入参数
function rhino_test(str) {
    //var str = "jzy666";
    //执行反射获取的方法,并传入 getJavaValue() 的值
    method_Api_rhino_test .invoke(javaContext,getJavaValue());
}
//我们将执行方法的语句去掉
//rhino_test();

修改 JsEngine 代码,在其中加入如下方法。

    public String getJavaValue(){
        return "这里是 Java ~~~~";
    }

重新运行程序,打印如下

2019-02-19 01:51:12.279 17111-17111/com.example.jzycc.rhino I/jzy111: rhino_test: 这里是 Java ~~~~

最后

Rhino Js 引擎在 Android 中的基本用法就是这么简单,具体如何使用应该还是要根据使用场景来设计,我这里只是将最基本的 JS 与 JAVA 本地交互的方法做个展示。

相关文章

  • Android 使用 Rhino JS 解析引擎执行JS代码

    Rhino 简介 官方示例 Android】不使用WebView来执行Javascript脚本(Rhino) Rh...

  • js预解析(面试哦)

    js 代码通过 js 解释器(js 引擎) 来执行的 js 解释器 来执行js 代码分为两步: 首先预解析 再 ...

  • js变量提升 函数提升 作用域

    js代码解析原则 js引擎首先在读取js代码时默认执行2个步骤:1.解释(通篇扫描所有js代码,然后把所有声明(变...

  • 怎么来理解Js是单线程的这句话?

    Js是单线程指的是执行Js代码的只有Js引擎主线程。Js在js引擎中同步执行,永远都是运行执行栈最顶部的代码。那么...

  • 深入理解JavaScript之变量提升

    变量提升 原理:JS引擎的工作方式是先解析代码,获取所有被声明的变量;然后在运行。JS代码自上而下执行之前,浏览器...

  • java17使用graaljs引擎执行js代码

    java17使用graaljs引擎执行js代码 添加依赖 helloworld 运行,输出

  • 浏览器的运行机制

    浏览器的组成结构(1)呈现引擎:负责解析html/css内容,将解析内容呈现到屏幕上(2)js引擎:解析和执行js...

  • 学习笔记

    预解析1. js引擎在js代码正式执行之前会做一些预解析的操作2. 先找关键字var,function3. 找到v...

  • 声明提升

    js代码解析原则:首先js引擎在读取js代码时会进行两个步骤,第一个步骤是解释,第二个步骤是执行。所谓解释就是会先...

  • 变量提升

    js代码解析原则 首先js引擎在读取js代码时会进行两个步骤,第一个步骤是解释,第二个步骤是执行。所谓解释就是会先...

网友评论

    本文标题:Android 使用 Rhino JS 解析引擎执行JS代码

    本文链接:https://www.haomeiwen.com/subject/ggpweqtx.html