Как передать непримитивный объект из Java в JS с помощью Android addJavascriptInterface?
У меня были проблемы на эту тему (в течение нескольких дней).
Например, в основном, я хочу передать объект Java WebSocketClient в Android Webview JS по требованию , поэтому написал код, ссылающийся кому:
- http://foretribe.blogspot.com.au/2013/08/how-to-make-android-webview-support.html
- https://github.com/thinksource/vw_websocket/blob/master/src/com/strumsoft/websocket/phonegap/WebSocketFactory.java
JAVA
wv.addJavascriptInterface(new WebSocketFactory(), "factoryJ");
public class WebSocketFactory {
//.............
public WebSocket getInstance(String url) {
socket = new WebSocket(new URI(url));
return socket;
}
}
JS
var url = "ws:someaddress";
var ws = factoryJ.getInstance(url);
console.log(ws.toString()) // object pointer displayed
console.log(ws.getReadyState()); //Uncaught Error: Error calling method on NPObject!
Uncaught Error: Error calling method on NPObject!
Эта концепция не работает, по крайней мере, для меня avove Android4.2+.,
потому что addJavascriptInterface() работает только с примитивными типами Java и Веревка.
Cf)
передача объекта JavaScript с помощью addJavascriptInterface () на Android
ошибка вызова метода на NPObject! в Android 2.2
Насколько мне известно, единственный способ передать объект JAVA в JS - это:
wv.addJavascriptInterface(JavaObject, "JsObject");
Конечно, это должно работать нормально, пока передача JavaObject предопределена, но поскольку WebSocket Object(s) находится по требованию, мне нужно как-то взломать для этого.
Итак, я готовлюсь JavaObject как некий массив WebSocket .
WebSocketNew[] ws = new WebSocketNew[99999];
wv.addJavascriptInterface(ws, "wsJ");
К сожалению, JS трактует wsJ[n] как undefined; похоже, что он также не может передать ArrayObject.
Я читал JSON или JSON array Java можно передать, но это string В конце концов и не может быть этим решением, я прав?
Вероятно, в былые времена взаимодействие Android Java-JS реализовывалось более свободно, но в вопросах безопасности они ограничивают больше (аннотация @JavascriptInterface является одной, и не только это, но и другие факторы ) Android 4.2.1, WebView и JavaScript интерфейсные разрывы
Как передать непримитивный объект из Java в JS с помощью Android addJavascriptInterface?
Есть мысли?
Спасибо.
2 ответов:
Вы правы, что методы интерфейса Javascript могут возвращать только строки и примитивные типы. Если вам нужно вернуть более сложный объект, вы можете попробовать сериализовать объект в JSON. Но это работает только для объектов уровня модели. Если вам нужно вернуть класс, содержащий функциональность, единственный известный мне способ сделать это-обернуть класс и представить каждый из его методов как @JavascriptInterface. Например:
class Foo { private WrappedClass myWrappedClass; public Foo(WrappedClass classToWrap) { myWrappedClass = classToWrap; } @JavascriptInterface public String doSomething1() { return myWrappedClass.doSomething1(); } @JavascriptInterface public int doSomething2() { return myWrappedClass.doSomething2(); } // Etc. }Это довольно утомительно.
Но, похоже, что вы пытаетесь использовать websockets. А вы подумали Socket.io это позволит вам использовать веб-сокеты в Javascript, а не полагаться на JavascriptInterface.
Это был один из самых беспокойных хаков для меня.
Основная проблема возникает с Android
UI-threadиnon-UI-threadсвязывается сaddJavascriptInterfaceВо-первых, мое упоминание: насколько мне известно, единственный способ передать объект JAVA в JS-это : западная вирджиния.addJavascriptInterface (JavaObject, "JsObject"); неправильный.
Фактически, я мог бы передать
WebSocketNew= мой пользовательский объект Java правильно в JS как возвращаемое значениеgetInstance.Однако , объект, предназначенный для передачи / возврата JS должен находиться в области действия Android
UI-thread.Если мы просто делаем
return new WebSocketNew(new URI(url))), он не найден JS, вероятно, потому, что JS работает в UI-потоке, а origin работает наnon-UI-threadизaddJavascriptInterface.Как я уже упоминал ранее, так как экземпляр WebScoket находится по требованию, поэтому я решил сначала создать пул объектов в
UI-thread. Это можно сделать с помощью HashMap с запрошенной строкой url.Java
final HashMap<String, WebSocketNew> ws = new HashMap<>(); //runs on non-UI-thread class WebSocketFactory { public WebSocketFactory() { } @JavascriptInterface public WebSocketNew getInstance(String url) { System.out.println("============WebSocketFactory============getInstance " + url); try { ws.put(url, new WebSocketNew(new URI(url))); ws.get(url).connect(); System.out.println("=====WebSocketNew=====" + url + " " + ws.get(url).getReadyState()); return ws.get(url); } catch (Exception e) { System.out.println("==========ERROR"); return null; } } } wv.addJavascriptInterface(new WebSocketFactory(), "factoryJ"); wv.loadUrl("file:///android_asset/Content/app.html");JS
window.WebSocket = function(url) { console.log('####################creating new WebScoketInstance JS ' + url); var p = { url: null }; p.url = url; var ws = factoryJ.getInstance(p.url); var obj = { send: function(data) { console.log('--- send: function(data)----- ws.send1(data);------'); ws.send1(data); }, //....... //....... } return obj; };Код JS связан с темой: реализация событий JavaScript для Объект на основе замыкания
Comments