2011-11-02 45 views
5

Đây là toàn bộ mã Java tôi đã sử dụng. Tôi sẽ giải thích chi tiết hơn bên dưới ...JavascriptInterface trong WebView của Android: nhiều cuộc gọi tới JS gây ra bế tắc

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')"); 
    } 
} 

Và có vẻ như nó hoạt động tốt.

Bạn có thể thấy rằng tôi đã có một nút (mà chúng ta có thể gọi button1), và nhấp vào nó, nó sẽ cố gắng để thực hiện một phương pháp JS, gọi func().

public void button1(View v) { 
    wv.loadUrl("javascript:func('1')"); 
} 

Bên trong phương thức JS này, tôi phải gọi một phương thức Java khác. Đây là mã:

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

Tôi cần trả lại kết quả của JSInterface.getNewString() vào biến innerHTML.

Mã của JSInterface.getNewString() là thế này:

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

Bạn có thể thấy rằng tôi sử dụng phương pháp setReturnValuegetReturnValue để trả về giá trị trả về bởi phương pháp JS khác. Đây là mã:

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

Vấn đề là khi tôi cố gắng đặt returnValue, hàm createNewString sẽ không bao giờ được thực thi! Nếu tôi thêm một dòng console.log(), logCat của tôi sẽ không hiển thị gì cả!

Tôi không thể hiểu tại sao điều này xảy ra.

Trả lời

2

Tất cả javascript và các phương thức JSInterface của bạn được gọi từ javascript đang chạy trên một chuỗi trong Android Webview. Vì vậy, trong khi bạn đang chờ đợi trong condVarOnJS.await() không có javascript có thể được thực hiện, chỉ vì nó được thực thi trên cùng một luồng.

Hơn nữa, tất cả các phiên bản webview trong ứng dụng của bạn đều dùng cùng một chuỗi javascript.

0

Trong Internet Explorer, tôi đã tìm thấy cùng một vấn đề. Bạn có thể sử dụng setTimeout như thế này:

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

Không, nó không hoạt động –

0

tôi đã làm các chức năng gì bạn có ý định trong mã đó, đối với tôi createNewString() được gọi,

tôi sẽ hiển thị mã i sử dụng,

trong 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; 
    } 

dưới dạng 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> 

Chức năng getter và setter gọi và giá trị cũng được thiết lập, nhưng tôi có các bản ghi đầu ra như ..

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 gọi từ JS và createnewString() hay còn gọi là từ java để JS, nhưng nó trả về giá trị trước khi nó được thiết lập, vì tôi don `t mục đích sử dụng khóa là gì, thậm chí tôi đã cố gắng sử dụng khóa như bạn đã làm cho rằng nó sẽ in

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

sử dụng khóa cũng là chức năng gọi lại làm việc theo cách sai, bạn cần làm việc trên ổ khóa.

+0

Ok, tôi sẽ thử. Nhưng đây không phải là một câu trả lời hoàn chỉnh ... –

+0

Những thay đổi bạn đã làm để thực hiện công việc .. – Karthi

+0

Thật không may vẫn không hoạt động ... Tôi không biết làm thế nào tôi có thể giải quyết vấn đề này ... –

Các vấn đề liên quan