运用Rhino,在Android上运行js代码

简单记录如何运用Rhino

在这里不过多赘述rhino,百度以及官网到处都是介绍,本文只提供我自己封装的工具类,用于处理运行js代码(字符串形式),返回js对象或者String。支持es5语法,支持部分es6语法,js代码中包含console.log,会报错,移除即可,因为工作原因没有继续深入了解。

下载并依赖rhino的jar包

github链接: rhino.

自行选择下载并添加依赖,我选择的是目前最新的版本1.7.11,旧版本未曾用过。
编译未通过可在app/build.gradle中添加如下代码:

android{
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
}

工具类代码如下:


import android.text.TextUtils;

import org.mozilla.javascript.ArrowFunction;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeJSON;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

/**
 * Android端运行js,基于Rhino进行封装
 */
public class AndroidRunJs {

    private static AndroidRunJs androidRunJs;

    private AndroidRunJs() {
    }

    public synchronized static AndroidRunJs getInstance() {
        if (androidRunJs == null) {
            androidRunJs = new AndroidRunJs();
        }
        return androidRunJs;
    }

    /**
     * 加载JS代码
     *
     * @param js             js代码
     * @param functionName   js方法名称
     * @param functionParams js方法参数
     * @return js对象
     */
    public ScriptableObject runScript(String js, String functionName, Object... functionParams) {
        Context rhino = Context.enter();
        rhino.setOptimizationLevel(-1);
        try {
            Scriptable scope = rhino.initStandardObjects();
            rhino.evaluateString(scope, js, null, 1, null);

            Function function = (Function) scope.get(functionName, scope);
            ScriptableObject jsContextObject = (ScriptableObject) function.call(rhino, scope, scope, functionParams);
            return jsContextObject;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            Context.exit();
        }
    }

    /**
     * 从js对象中获取js对象
     *
     * @param jsObject
     * @param varName  对象对应的key名称
     * @return js对象
     */
    public ScriptableObject getJsObj(ScriptableObject jsObject, String varName) {
        if (jsObject == null) {
            return null;
        }
        Context rhino = Context.enter();
        rhino.setOptimizationLevel(-1);
        try {
            Scriptable scope = rhino.initStandardObjects();
            ScriptableObject so = (ScriptableObject) jsObject.get(varName);
            return so;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            Context.exit();
        }
    }

    /**
     * 执行js对象中的函数,并获取返回的js对象
     *
     * @param jsObject
     * @param functionVarName js函数对应的key名
     * @param functionParams  js函数所需参数
     * @return js对象
     */
    public ScriptableObject getJsObjByFunction(ScriptableObject jsObject, String functionVarName, Object... functionParams) {
        if (jsObject == null) {
            return null;
        }
        Object[] funcParam = new Object[]{};
        if (functionParams != null) {
            funcParam = functionParams;
        }
        Context rhino = Context.enter();
        rhino.setOptimizationLevel(-1);
        try {
            Scriptable scope = rhino.initStandardObjects();
            Object fuc = jsObject.get(functionVarName);
            ScriptableObject so = null;
            if (fuc instanceof ArrowFunction) {
                ArrowFunction fuc1 = (ArrowFunction) fuc;
                if (fuc != null) {
                    so = (ScriptableObject) fuc1.call(rhino, scope, scope, funcParam);
                }
            } else if (fuc instanceof Function) {
                Function fuc1 = (Function) fuc;
                if (fuc != null) {
                    so = (ScriptableObject) fuc1.call(rhino, scope, scope, funcParam);
                }
            } else {
                return null;
            }
            return so;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            Context.exit();
        }
    }

    /**
     * 从js对象中获取字符串值
     *
     * @param jsObject
     * @param varName  值对应的key名
     * @return 字符串值
     */
    public String getJsRes(ScriptableObject jsObject, String varName) {
        if (jsObject == null) {
            return null;
        }
        Context rhino = Context.enter();
        rhino.setOptimizationLevel(-1);
        try {
            Scriptable scope = rhino.initStandardObjects();
            Object var = jsObject.get(varName);
            return var == null ? null : rhino.toString(var);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            Context.exit();
        }
    }

    /**
     * 执行js对象中的函数,获取返回的字符串值
     *
     * @param jsObject
     * @param functionVarName js函数对应的key名
     * @param functionParams  js函数所需参数
     * @return 字符串返回值
     */
    public String getJsResByFunction(ScriptableObject jsObject, String functionVarName, Object... functionParams) {
        if (jsObject == null) {
            return null;
        }
        Object[] funcParam = new Object[]{};
        if (functionParams != null) {
            funcParam = functionParams;
        }
        Context rhino = Context.enter();
        rhino.setOptimizationLevel(-1);
        try {
            Scriptable scope = rhino.initStandardObjects();
            Object fuc = jsObject.get(functionVarName);
            Object so = null;
            if (fuc instanceof ArrowFunction) {
                ArrowFunction fuc1 = (ArrowFunction) fuc;
                if (fuc != null) {
                    so = fuc1.call(rhino, scope, scope, funcParam);
                }
            } else if (fuc instanceof Function) {
                Function fuc1 = (Function) fuc;
                if (fuc != null) {
                    so = fuc1.call(rhino, scope, scope, funcParam);
                }
            } else {
                return null;
            }
            return so == null ? null : rhino.toString(so);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            Context.exit();
        }
    }

    /**
     * 获取js代码可识别的对象
     * @param jsonString json格式的字符串
     * @return
     */
    public Object getJSJsonObject(String jsonString) {
        if (TextUtils.isEmpty(jsonString)) {
            return null;
        }
        Context rhino = Context.enter();
        rhino.setOptimizationLevel(-1);
        try {
            Scriptable scope = rhino.initStandardObjects();
            Object result = NativeJSON.parse(rhino, scope, jsonString, new NullCallable());
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            Context.exit();
        }
    }

}
其中getJSJsonObject函数需要用到自定义NullCallable类,代码如下:
import org.mozilla.javascript.Callable;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;

public class NullCallable implements Callable {
    @Override
    public Object call(Context context, Scriptable scope, Scriptable holdable, Object[] objects) {
        return objects[1];
    }
}

getJSJsonObject函数是为了js代码中函数接收的参数类型为对象,此函数可将json格式字符串转为js代码可直接识别js对象

最后,希望本文能够给同行一点帮助,网上的资料零零散散真的很难寻到有用的东西。

参考资料:
[1]: https://github.com/mozilla/rhino
[2]: https://developer.mozilla.org/zh-CN/docs/Mozilla/Projects/Rhino/Documentation
[3]: https://stackoverflow.com/questions/10856154/rhino-return-json-from-within-java

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以的,Android平台可以使用Rhino引擎来执行JavaScript代码。你可以将JavaScript代码保存在一个.js文件中,在Android应用中使用Rhino引擎加载并执行该文件。通过Rhino的API,你可以实现常驻监听的功能。 首先,在你的Android项目中引入Rhino库依赖。然后,创建一个JavaScript上下文对象,并将你的.js文件加载到该上下文中。接下来,你可以调用上下文对象的方法来执行你的JavaScript代码。 下面是一个简单的示例代码,演示了如何在Android应用中使用Rhino引擎执行一个常驻监听的JavaScript代码: ```java import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; public class RhinoExample { public static void main(String[] args) { // 创建一个JavaScript上下文对象 Context rhino = Context.enter(); rhino.setOptimizationLevel(-1); // 关闭Rhino的优化,加速加载 try { // 创建一个全局作用域对象 Scriptable scope = rhino.initStandardObjects(); // 加载你的.js文件 String jsCode = "var counter = 0;\n" + "while (true) {\n" + " counter++;\n" + " print('Counter: ' + counter);\n" + " java.lang.Thread.sleep(1000); // 休眠1秒\n" + "}"; rhino.evaluateString(scope, jsCode, "MyScript", 1, null); } catch (Exception e) { e.printStackTrace(); } finally { // 退出Rhino上下文 Context.exit(); } } } ``` 这段JavaScript代码会在一个无限循环中输出计数器的值,并休眠1秒。你可以根据自己的需求修改代码实现常驻监听的功能。 注意,Rhino引擎是一个轻量级的JavaScript引擎,对于一些复杂的JavaScript代码可能会有性能方面的限制。如果你需要处理更复杂的逻辑,可以考虑使用更强大的JavaScript引擎,如V8引擎或J2V8库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值