Android中的JavascriptInterface';s WebView:对JS的多次调用导致死锁
这是我使用的全部Java代码。我将在下面更详细地解释Android中的JavascriptInterface';s WebView:对JS的多次调用导致死锁,javascript,android,webview,Javascript,Android,Webview,这是我使用的全部Java代码。我将在下面更详细地解释 public class Test7 extends Activity { //debug private final static String TAG = "JSInterface"; private WebView wv; private class JSInterface { private WebView wv; // Variables to manage in
public class Test7 extends Activity {
//debug
private final static String TAG = "JSInterface";
private WebView wv;
private class JSInterface {
private WebView wv;
// Variables to manage interfacing with JS
private String returnValue;
private boolean canReadReturnValue;
private Lock lockOnJS;
private Condition condVarOnJS;
public JSInterface (WebView wv) {
this.wv = wv;
this.canReadReturnValue = false;
this.lockOnJS = new ReentrantLock();
this.condVarOnJS = lockOnJS.newCondition();
}
public void setReturnValue(String ret) {
lockOnJS.lock();
returnValue = ret;
canReadReturnValue = true;
condVarOnJS.signal();
lockOnJS.unlock();
Log.d(TAG, "returnValue = " + returnValue);
}
public String getReturnValue() {
Log.d(TAG, "enter in getReturnValue");
lockOnJS.lock();
while (!canReadReturnValue) {
try {
Log.d(TAG, "get wait...");
condVarOnJS.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lockOnJS.unlock();
Log.d(TAG, "returnValue: " + returnValue);
return returnValue;
}
public String getNewString() {
wv.loadUrl("javascript:JSInterface.setReturnValue(createNewString())");
return getReturnValue();
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
wv = (WebView) findViewById(R.id.webView1);
wv.getSettings().setJavaScriptEnabled(true);
wv.addJavascriptInterface(new JSInterface(wv), "JSInterface");
wv.loadUrl("file:///android_asset/prova7.html");
}
public void button1(View v) {
wv.loadUrl("javascript:func('1')");
}
}
而且看起来效果不错
你可以看到我有一个按钮(我们可以称之为button1),点击它,它试图执行一个JS方法,名为func()
public void button1(View v) {
wv.loadUrl("javascript:func('1')");
}
在这个JS方法中,我必须调用另一个Java方法。代码如下:
function func(id) {
document.getElementById(id).innerHTML = JSInterface.getNewString();
}
function createNewString() {
return "my New String";
}
我需要将JSInterface.getNewString()的结果返回给innerHTML变量
JSInterface.getNewString()的代码如下:
public String getNewString() {
wv.loadUrl("javascript:JSInterface.setReturnValue(createNewString())");
return getReturnValue();
}
您可以看到,我使用方法setReturnValue
和getReturnValue
返回另一个JS方法返回的值。代码如下:
function func(id) {
document.getElementById(id).innerHTML = JSInterface.getNewString();
}
function createNewString() {
return "my New String";
}
问题是,当我试图设置returnValue时,函数createNewString从未执行过!如果我添加一个console.log()行,我的logCat将不显示任何内容
我不明白为什么会发生这种情况。在Internet Explorer中,我发现了同样的问题。您可以像这样使用setTimeout:
function func(id) {
setTimeout(
function(){
document.getElementById(id).innerHTML = JSInterface.getNewString();
},
500);
}
我在代码中实现了您想要的功能,对我来说,createNewString()被调用 我将显示我使用的代码 在爪哇 , 在HTML中
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script>
function inform(){
alert('et');
document.getElementById('myText').value=window.demo.videoPlay();
alert('et');
}
function createNewString() {
return "my New String";
}
</script>
</head>
<body onload="init()">
<form>
<input type='text' id='myText' />
<input type="button" name="test" value="Click me" onclick="inform()">
</form>
</body>
</html>
videoPlay从JS调用,createnewString()也从java调用到JS,但它会在设置之前返回值,因为我不知道使用lock的目的是什么,甚至我尝试过使用lock,就像你那样,它会打印出来
11-08 19:18:17.155: INFO/System.out(847): videoPlay
11-08 19:18:17.165: INFO/System.out(847): getnull
使用lock函数回调也会以错误的方式工作,您需要处理锁 所有javascript和从javascript调用的JSInterface方法都在Android
WebView
中的单个线程上运行。因此,当您在condVarOnJS.await()中等待时,不能执行任何javascript,因为它是在同一个线程上执行的
此外,应用程序中的所有webview实例共享相同的javascript线程