2011-11-02 72 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

不幸的是仍然沒有工作......我不知道我該怎麼解決這個問題... –

相關問題