运用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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值