2011-11-02 16 views
5

To jest cały kod Java, którego użyłem. Wyjaśnię bardziej szczegółowo poniżej ...JavaScriptInterface w Androidzie WebView: wiele połączeń z JS powoduje impas

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

Wygląda na to, że działa dobrze.

Widać, że mam przycisku (który możemy nazwać button1) i kliknięcie na niego, próbuje wykonać metodę JS, zwany func().

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

Wewnątrz tej metody JS, muszę wywołać inną metodę Java. Jest to kod:

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

muszę zwrócić wynik JSInterface.getNewString() do zmiennej innerHTML.

Kodeks JSInterface.getNewString() to:

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

Można zobaczyć, że użycie metody setReturnValue i getReturnValue do zwrotu wartości zwracanych inną metodą JS. Jest to kod:

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

Problemem jest to, że gdy próbuję ustawić returnValue The createNewString funkcja jest nigdy wykonywany! Jeśli dodaję linię console.log(), mój logCat nic nie wyświetla!

Nie mogę zrozumieć, dlaczego tak się dzieje.

Odpowiedz

2

Wszystkie javascript i metody JSInterface wywoływane z javascript są uruchamiane w jednym wątku w widoku Web systemu Android. Tak więc, gdy czekasz w condVarOnJS.await() nie można wykonać javascript, tylko dlatego, że jest wykonywany w tym samym wątku.

Co więcej, wszystkie instancje przeglądania w aplikacji użytkownika korzystają z tego samego wątku javascript.

0

W Internet Explorerze znalazłem ten sam problem. Można użyć setTimeout tak:

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

Nie, to nie działa –

0

zrobiłem funkcjonalność, co zamierzasz w tym kodzie, dla mnie createNewString() jest wywoływana,

pokażę się kod I używany,

w Javie ,

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

w 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 i setter funkcja o nazwie i wartości ustawić również, ale mam dziennik wyjściowy jako ..

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 wywoływana z JS i createnewString() nazywany również z Java JS, ale zwraca wartość zanim ustawione, bo don `t, co jest celem, aby użyć blokady, nawet Próbowałem za pomocą zamka jak to było, że będzie drukować

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

stosując blokadę również zwrotna funkcja działa w niewłaściwy sposób, ty potrzebujesz pracy przy zamkach.

+0

Dobrze, spróbuję. Ale to nie jest kompletna odpowiedź ... –

+0

Jakie zmiany wprowadziłeś w pracy ... – Karthi

+0

Niestety nadal nie działa ... Nie wiem, jak mogę rozwiązać ten problem ... –

Powiązane problemy