如何从Android调用javascript?
我们如何从Android调用javascript?我有一个我想使用的javascript库,我想调用javascript函数并将结果值传递给android java代码。从现在起我还没有找到答案。我设法从javascript调用android代码,但我想换一种方式。有一个黑客:如何从Android调用javascript?,java,javascript,android,return,Java,Javascript,Android,Return,我们如何从Android调用javascript?我有一个我想使用的javascript库,我想调用javascript函数并将结果值传递给android java代码。从现在起我还没有找到答案。我设法从javascript调用android代码,但我想换一种方式。有一个黑客: 绑定一些Java对象,以便可以使用WebView从Javascript调用它: addJavascriptInterface(javaObjectCallback, "JavaCallback") 通过强制在现有页面
addJavascriptInterface(javaObjectCallback, "JavaCallback")
WebView.loadUrl("javascript: var result = window.YourJSLibrary.callSomeFunction();
window.JavaCallback.returnResult(result)");
JavaObjectCallback
应该有一个方法returnResult(..)
)
注意:这是一个安全风险-此网页中的任何JS代码都可以访问/调用绑定的Java对象。最好将一些一次性cookie传递给loadUrl(),并将它们传回您的Java对象,以检查调用的是您的代码。为了匹配iOS WebviewJavascriptBridge()的方法调用,我为
register\u handle
和call\u handle
的调用制作了一些代理。请注意,我不是Javascript大师,因此可能有更好的解决方案
javascriptBridge = (function() {
var handlers = {};
return {
init: function () {
},
getHandlers : function() {
return handlers;
},
callHandler : function(name, param) {
if(param !== null && param !== undefined) {
JSInterface[name](param);
} else {
JSInterface[name]();
}
},
registerHandler : function(name, method) {
if(handlers === undefined) {
handlers = {};
}
if(handlers[name] === undefined) {
handlers[name] = method;
}
}
};
}());
通过这种方式,您可以从Javascript向Java发送具有字符串参数的调用
javascriptBridge.callHandler("login", JSON.stringify(jsonObj));
号召
@JavascriptInterface
public void login(String credentialsJSON)
{
Log.d(getClass().getName(), "Login: " + credentialsJSON);
new Thread(new Runnable() {
public void run() {
Gson gson = new Gson();
LoginObject credentials = gson.fromJson(credentialsJSON, LoginObject.class);
SingletonBus.INSTANCE.getBus().post(new Events.Login.LoginEvent(credentials));
}
}).start();
}
您可以使用
javascriptBridge.registerHandler('successfullAuthentication', function () {
alert('hello');
})
及
如果需要传递参数,请序列化为JSON字符串,然后调用StringEscapeUtils.escapeEcmaScript(JSON)
,否则会得到意外标识符:source(1)
错误
有点俗气,但它能用。您只需删除以下内容
connectWebViewJavascriptBridge(function(bridge) {
}
编辑:
为了将全局变量更改为实际属性,我将上述代码更改为:
(function(root) {
root.bridge = (function() {
var handlers = {};
return {
init: function () {
},
getHandlers : function() {
return handlers;
},
callHandler : function(name, param) {
if(param !== null && param !== undefined) {
Android[name](param);
} else {
Android[name]();
}
},
registerHandler : function(name, method) {
if(handlers === undefined) {
handlers = {};
}
if(handlers[name] === undefined) {
handlers[name] = method;
}
}
};
}());
})(this);
我的想法来自。您可以使用
Rhino
库在没有WebView的情况下执行JavaScript
首先,解压缩它,将js.jar文件放在libs文件夹下。它非常小,所以您不必担心apk文件会因为这个外部jar而大得离谱
下面是一些执行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();
}
您可以在上查看更多详细信息。有关不需要使用慢速WebView的JavaScript的完整实现,请参阅,这是Webkit的JavaScriptCore For Android的完整端口 2018年更新:AndroidJSCore已弃用。但是,它的继任者具有所有相同的功能和更多功能。 从Android调用函数非常简单:
JSContext context = new JSContext();
String script =
"function factorial(x) { var f = 1; for(; x > 1; x--) f *= x; return f; }\n" +
"var fact_a = factorial(a);\n";
context.evaluateScript("var a = 10;");
context.evaluateScript(script);
JSValue fact_a = context.property("fact_a");
System.out.println(df.format(fact_a.toNumber())); // 3628800.0
只需查看code.google.com上的一个问题,目前的解决方案是加载一个JavaScript URL,例如:webview.loadUrl(“JavaScript:(function(){“+”document.getElementsByTagName('body')[0]。style.color='red';“+”})();在某些方面,一旦您看到它,它看起来非常优雅和明显,但它仍然没有直接执行JavaScript的方法那么优雅。然而,这确实证明了实现这种方法是很容易的。Android开发者的页面也谈到了这种安全风险如果
JavascriptInterface
只包含可以从JavaScript访问的方法,我认为没有风险,这就是为什么在JellyBean(api 17)中引入@JavascriptInterface注释的原因@peter knego我应该为returnResult(…)
中的参数使用什么类型?例如,我想返回类型为HTMLCollection的document.getElementsByCassName('someclass')
,但Java中没有这种类型?如果我只使用字符串或对象作为参数类型,它将返回null和“undefined”。我不知道这对我来说是否太过分了。我只想在我的网站上解析一个HTML表。我仍在寻找这样做的方法。我有一个javascript函数,可以将表转换为json,我只需要一种在java.Hi-Eric中获取它的方法。你还忘了提到它现在被弃用,取而代之的是LiquidCore。
JSContext context = new JSContext();
String script =
"function factorial(x) { var f = 1; for(; x > 1; x--) f *= x; return f; }\n" +
"var fact_a = factorial(a);\n";
context.evaluateScript("var a = 10;");
context.evaluateScript(script);
JSValue fact_a = context.property("fact_a");
System.out.println(df.format(fact_a.toNumber())); // 3628800.0