2011-11-02 101 views
5

这是我用过的整个Java代码。我会在下面更详细地解释...Android的WebView中的JavascriptInterface:多次调用JS导致死锁

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()。我们不得不调用另一个Java方法。这是代码:

function func(id) { 
    document.getElementById(id).innerHTML = JSInterface.getNewString(); 
} 

我需要)返回JSInterface.getNewString(的结果的innerHTML变数。

JSInterface.getNewString()的代码是这样的:

public String getNewString() { 
    wv.loadUrl("javascript:JSInterface.setReturnValue(createNewString())");   
    return getReturnValue(); 
} 

你可以看到,我使用的方法setReturnValuegetReturnValue返回另一个JS方法的返回值。这是代码:

function createNewString() { 
    return "my New String"; 
} 

问题是,当我尝试设置returnValue时,函数createNewString永远不会执行!如果我添加一个console.log()行,我的logCat不显示任何内容!

我不明白为什么会发生这种情况。

回答

2

从JavaScript调用的所有JavaScript和JSInterface方法都在Android Webview的单线程上运行。所以当你在condVarOnJS等待。await()不能执行javascript,只是因为它在同一个线程上执行。

此外,应用程序中的所有webview实例共享相同的javascript线程。

0

在Internet Explorer中,我发现了同样的问题。您可以使用的setTimeout这样的:

function func(id) { 
    setTimeout(
     function(){ 
      document.getElementById(id).innerHTML = JSInterface.getNewString(); 
     }, 
     500); 
} 
+0

不,它不起作用 –

0

我做了什么,你的代码打算的功能,对我来说createNewString()被调用,

我将显示我使用的代码,

在java中 ,

public String videoPlay(){ 
     System.out.println("videoPlay"); 
     mWebView.loadUrl("javascript:window.demo.setReturnValue(createNewString())"); 
     return getReturnValue();} 

public void setReturnValue(String test){ 
     rotValue=test; 
     System.out.println(test); 

    } 
    public String getReturnValue(){ 
     System.out.println("get"+rotValue); 
     return rotValue; 
    } 
在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> 

功能getter和setter称为和值也被设置,但是我有输出日志作为..

11-08 19:18:17.155: INFO/System.out(847): videoPlay 
11-08 19:18:17.165: INFO/System.out(847): getnull 
11-08 19:18:17.875: INFO/System.out(847): my New String 

videoPlay从JS和createnewString()调用也从Java到JS调用,但是它返回值之前将其设置,因为我不`吨什么是使用锁的目的,即使我用锁试着像你一样的,它会使用锁也回调函数在错误的方式工作打印

11-08 19:18:17.155: INFO/System.out(847): videoPlay 
    11-08 19:18:17.165: INFO/System.out(847): getnull 

,你需要在锁上工作。

+0

好吧,我会尝试。但这不是一个完整的答案... –

+0

你做了什么改变,使作品.. – Karthi

+0

不幸的是仍然没有工作......我不知道我该怎么解决这个问题... –

相关问题