2011-11-02 11 views
5

Este es el código completo de Java que he usado. Voy a explicar en más detalle a continuación ...JavaScriptInterface en Android WebView: llamadas múltiples a JS causan un punto muerto

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

Y parece que funciona bien.

Se puede ver que tengo un botón (que podemos llamar botón1), y haciendo clic en él, se trata de ejecutar un método JS, llamados func().

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

Dentro de este método de JS, tengo que llamar a otro método de Java. Este es el código:

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

necesito devolver el resultado de JSInterface.getNewString() a la variable innerHTML.

El código de JSInterface.getNewString() es la siguiente:

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

Se puede ver que utilizo el método setReturnValue y getReturnValue para devolver el valor devuelto por otro método JS. Este es el código:

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

El problema es que cuando intento configurar el returnValue, la createNewString función no se ejecuta nunca! Si agrego una línea console.log(), ¡mi logCat no muestra nada!

No puedo entender por qué sucede esto.

Respuesta

2

Todos los javascript y sus métodos JSInterface llamados desde javascript se ejecutan en el único hilo en Android Webview. Entonces, mientras espera en condVarOnJS.await() no se puede ejecutar javascript, simplemente porque se ejecuta en el mismo hilo.

Además, todas las instancias de vista web en su aplicación comparten el mismo hilo de JavaScript.

0

En Internet Explorer encontré el mismo problema. Puede utilizar setTimeout así:

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

No, no funciona –

0

hice la funcionalidad de lo que se propone en ese código, para mí createNewString() se llama,

voy a mostrar el código i utilizada,

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

en 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> 

El getter y setter función llamaron y establecer valores también, pero tengo el registro de salida como ..

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 llamado desde JS y createnewString() también llamado de Java a JS, pero devuelve el valor antes de que se puso, porque el `t ¿cuál es el propósito de utilizar el bloqueo, incluso he intentado usar el bloqueo que lo hizo para que se imprimirá

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

usar el bloqueo también la devolución de llamada función funciona de manera equivocada que, necesito trabajar en cerraduras.

+0

Ok, lo intentaré. Pero esta no es una respuesta completa ... –

+0

¿Qué cambios hizo para hacer obras ... – Karthi

+0

Lamentablemente todavía no funciona ... No sé cómo puedo resolver este problema ... –

Cuestiones relacionadas