2014-03-06 88 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(); 

你不會吧()評估,然後返回,但你可以做到這一點之後立即。