简单记录如何运用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