2014-03-06 51 views
0

我已经建立了一个非常简单的JavaScript实现执行任意JavaScript:使用Android的WebView中于Android的WebView回调/接口

的index.html

<!DOCTYPE html> 
<html> 
    <head> 
    <title></title> 
    <script type="text/javascript" charset="utf-8" src="Test.js"></script> 
    </head> 
</html> 

MyJavaScript.java

public class MyJavaScript 
{ 
    public MyJavaScript() 
    { 
     // create the WebView 
     mWebView = new WebView(mContext); 

     // enable javaScript 
     WebSettings webSettings = mWebView.getSettings(); 
     webSettings.setJavaScriptEnabled(true); 

     // add javaScript interface 
     mWebView.addJavascriptInterface(new JavaScriptTest, "_test"); 

     // load our dummy page 
     mWebView.loadUrl("file:///android_asset/javascript/index.html"); 
    } 

    public void exec(String script) 
    { 
     mWebView.loadUrl("javascript:" + script); 
    } 
} 

测试.js文件

function Test() 
{ 
}; 

Test.prototype.foo = function() 
{ 
    window._test.foo(); 
}; 

Test.prototype.bar = function() 
{ 
    window._test.bar(); 
}; 

var test = new Test(); 

JavaScriptTest.java

public class JavaScriptTest 
{ 
    public void foo() 
    { 
     Log.d("Test", "foo"); 
    } 

    public void bar() 
    { 
     Log.d("Test", "bar"); 
    } 
} 

当主叫用户呼叫是这样的:

MyJavaScript.exec("foo();"); 

执行最终传播到JavaScriptTest.foo()。该执行在WebView的工作线程中。

我想在JavaScriptTest.foo()做的,是一样的东西的eval( “栏();”);.我基本上想要从java回调/接口同步执行更多的JavaScript。也就是说,我希望JavaScript bar()方法在返回到JavaScriptTest.foo()之前完全执行。我无法弄清楚如何做到这一点。

如果我备份一个图层,调用bar()方法很简单;来自Test.js中的foo方法。但是,这并不能真正满足我的需求。我需要能够在JavaScriptTest.foo()中执行由JavaScriptTest.foo()发现的任意JavaScript。

因为JavaScripTest.foo()在WebView的工作线程中执行,所以将JavaScriptTest.foo()发现的任意javascript传递给WebView.loadUrl(...)将无法工作,因为您需要从该API调用该API UI线程。

理想情况下,将执行一些任意JavaScript的方式,而在它在的WebView工作者线程执行的Java回调/接口存根。

我也许可以通过将任意JavaScript回为foo()在Test.js解决问题,但它是不是我的第一选择了比较特殊的和丑陋的解决方案。如果我的第一选择不存在,那么我没有选择。

+1

您是否需要bar()在JavascriptTest.foo()内同步执行,即在foo()返回JavaScript之前? – ksasq

+0

是的。感谢您提出这个问题。我应该在描述中包含这些细节。 – Carl

回答

0

由于web视图的线程的要求,我不认为你可以实现你想要我怕什么。从后台线程开始在Java中执行新的JavaScript执行的唯一方法是将任务发回到UI线程,但这会破坏您的同步需求。

我认为你唯一的选择是让Java对象返回一个字符串返回到你的JavaScript,然后它的eval(因为你的建议,我认为)。

+0

我可以以某种方式将eval能力传递给java代码,即window._test.foo(function(script){return eval(script);}); ? JavaScriptTest中的回调/接口是什么样的? public void foo(???)? – Carl

0

您可以修改您的JavaScriptTest界面以返回您要评估的JavaScript。

public class JavaScriptTest 
{ 
    public String foo() 
    { 
     return "bar();" 
    } 

    public void bar() 
    { 
     Log.d("Test", "bar"); 
    } 
} 

然后,在JavaScript:

function Test() 
{ 
}; 

Test.prototype.foo = function() 
{ 
    eval(window._test.foo()); 
}; 

Test.prototype.bar = function() 
{ 
    window._test.bar(); 
}; 

var test = new Test(); 

你不会吧()评估,然后返回,但你可以做到这一点之后立即。