标题可能看起来有点模糊,但我想不出另一个,所以我希望我能把问题弄清楚:
我正在使用Android WebView和JavascriptInterface。从我的应用程序(Java)到WebView(JavaScript)的通信就像这样完成:
webview.loadUrl("javascript:function()");
这是一个异步调用,之后应由JavaBridge-Thread处理。
另一种方式(Javascript to Java)可以从我的Javascript代码调用我的JavascriptInterface mainInterface
。我可以在JavascriptInterface中调用用@JavascriptInterface
声明的Java方法。
此调用也由JavaBridge-Thread执行。
在详细介绍之前,以下是重要的代码:
ModelActivity.java
public boolean loadPropertyIntoWebview(final String element, final String property, final String value){
final int requestId = jsCallIndex.incrementAndGet();
webview.loadUrl("javascript:setProperty('"+element+"', '"+property.toLowerCase()+"', '"+value+"', "+requestId+")");
return waitForJsReturnValue(requestId, 1000);
}
private boolean waitForJsReturnValue(int index, int timeout){
long start = System.currentTimeMillis();
while(true){
long elapsed = System.currentTimeMillis() - start;
if(elapsed > timeout){
System.out.println("JS RESPONSE TIMEOUT");
break;
}
synchronized (jsReturnValueLock) {
String value = jsReturnValues.remove(index);
if(value != null){
if(value.toLowerCase().equals("true")){
return true;
}else{
System.out.println("JS BAD RESPONSE");
return false;
}
}
long toWait = timeout - (System.currentTimeMillis() - start);
if (toWait > 0)
try {
System.out.println("WAIT NOW FOR "+toWait+" ms on index "+index);
jsReturnValueLock.wait(toWait);
} catch (InterruptedException e) {
break;
}
else{
System.out.println("JS RESPONSE TIMEOUT");
break;
}
}
}
return false;
}
public void processJsReturnValue(int index, String value){
System.out.println("RECEIVED ANSWER "+value+" for index "+index+" WAIT FOR UNLOCK");
synchronized (jsReturnValueLock) {
System.out.println("UNLOCKED FOR INDEX "+index);
jsReturnValues.put(index, value);
jsReturnValueLock.notifyAll();
}
}
JavascriptInterface.java
@JavascriptInterface
public void onClick(String elementId, String property, String value){
final String[] info = elementId.split("_");
dbHandler.addOrUpdateOutVariable(Integer.parseInt(info[0]), Integer.parseInt(info[1]), property, value);
((ModelActivity)context).runOnUiThread(new Runnable() {
@Override
public void run() {
actionManager.fireClickEvent(Integer.valueOf(info[0]), Integer.valueOf(info[1]));
}
});
}
@JavascriptInterface
public void processJsReturnValue(String index, String value){
try{
((ModelActivity)context).processJsReturnValue(Integer.parseInt(index), value);
}catch(NumberFormatException e){
e.printStackTrace();
}
}
我基本上想要做的是从我的JavaScript函数setProperty()
(ModelActivity - > loadPropertyIntoWebview)获取返回值。
在初始化期间,方法loadPropertyIntoWebview()
从Main-Thread多次调用,并始终通过processJsReturnValue()
函数从JavaBridge-Thread接收答案。
另一种不起作用的情况是用户在我的网页浏览中按下按钮,然后调用
onClick(String elementId, String property, String value)
在我的JavascriptInterface中。函数调用
actionManager.fireClickEvent(Integer.valueOf(info[0]), Integer.valueOf(info[1]));
经历了几个我无法详细解释的类和函数,但在最后一个实例中它会调用
loadPropertyIntoWebview(final String element, final String property, final String value)
。
这个调用也来自主线程,因为我在onClick函数中明确说过:
((ModelActivity)context).runOnUiThread(new Runnable() {
@Override
public void run() {
actionManager.fireClickEvent(Integer.valueOf(info[0]), Integer.valueOf(info[1]));
}
});
调试显示以下内容:
在启动期间和致电后
webview.loadUrl("javascript:setProperty('"+element+"', '"+property.toLowerCase()+"', '"+value+"', "+requestId+")");
JavaBridge-Thread immediatley返回processJsReturnValue()
。
通过用户调用时,它不会这样做。然后它将不会去那里,直到主线程完成我的timedout while(true)循环。
我希望整件事情不会太混乱,有人理解我的问题,甚至对这里出了什么问题有所了解。
答案 0 :(得分:0)
尝试将onClick和processJsReturnValue分隔为两个不同的JavascriptInterface类,创建它们的实例并单独注册它们。不确定,但似乎现在他们互相阻止。