Как мы называем javascript с Android? У меня есть эта библиотека javascript, которую я хотел бы использовать, я хочу вызвать функцию javascript и передать значение результата в javas-код андроида. С этого момента я не нашел ответа. мне удалось вызвать код Android из javascript, но я хочу наоборот.
Как вызвать javascript с Android?
Ответ 1
Есть взлома:
-
Привязать некоторый объект Java, чтобы его можно было вызвать из Javascript с помощью WebView:
addJavascriptInterface(javaObjectCallback, "JavaCallback")
-
Принудительно выполнить javascript на существующей странице
WebView.loadUrl("javascript: var result = window.YourJSLibrary.callSomeFunction(); window.JavaCallback.returnResult(result)");
(в этом случае ваш класс java JavaObjectCallback
должен иметь метод returnResult(..)
)
Примечание. Это риск для безопасности. Любой JS-код на этой веб-странице может получить доступ к вашему связанному объекту Java. Лучше всего передать некоторые разовые файлы cookie для загрузкиUrl() и передать их обратно на Java-объект, чтобы проверить, что ваш код выполняет вызов.
Ответ 2
Чтобы соответствовать вызову метода iOS WebviewJavascriptBridge (https://github.com/marcuswestin/WebViewJavascriptBridge), я сделал некоторый прокси для вызовов register_handle
и call_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, которые могут иметь параметр String
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();
}
и вы можете вернуться к Javascript с помощью
javascriptBridge.registerHandler('successfullAuthentication', function () {
alert('hello');
})
и
private Handler webViewHandler = new Handler(Looper.myLooper());
webViewHandler.post(
new Runnable()
{
public void run()
{
webView.loadUrl("javascript: javascriptBridge.getHandlers().successfullAuthentication();"
}
}
);
Если вам нужно передать параметр, выполните сериализацию в строку JSON, затем вызовите StringEscapeUtils.escapeEcmaScript(json)
, иначе вы получите ошибку unexpected identifier: source (1)
.
Немного липкий и взломанный, но он работает. Вам просто нужно удалить следующее.
connectWebViewJavascriptBridge(function(bridge) {
}
EDIT:
чтобы изменить глобальную переменную на фактическое свойство, я изменил приведенный выше код на следующее:
(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);
Я получил идею от глобального модуля Javascript или глобальной переменной.
Ответ 3
Вы можете использовать библиотеку Rhino
для выполнения JavaScript без WebView.
сначала загрузите Rhino, распакуйте его, поместите файл js.jar в папку libs. Это очень мало, поэтому вам не нужно беспокоиться, что ваш файл apk будет смехотворно большим из-за этой внешней банки.
Вот несколько простых кодов для выполнения кода JavaScript.
Object[] params = new Object[] { "javaScriptParam" };
// Every Rhino VM begins with the enter()
// This Context is not Android 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();
}
Вы можете увидеть более подробную информацию на мой пост.
Ответ 4
Для полной реализации JavaScript, который не требует использования медленного WebView, см. AndroidJSCore, который является полным портом Webkit JavaScriptCore для Android.
Функции вызова с 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
Версия 2.0 имеет очень небольшую площадь.