2012-06-09 78 views
21

我知道要從Javascript到Java進行交互,您必須在webview中使用addjavascriptInterface方法注入Java對象。瞭解Android的webview addjavascriptinterface

這是我面臨的問題。

  1. 我註冊一個java對象使用addJavascriptInterface方法可在我的JS。

  2. 我使用webview.loadURL("javascript:XXX");

  3. 注入在網頁視圖幾個JS給我寄了JS事件,當我與注射的JS完成。

的問題是,如果第1步之後,如果我執行下面的JavaScript:

mWebView.loadUrl("javascript:if(window.myobject) console.log('myobject found---------'); else {console.log('myobject not found----');}"); 

我得到了我的控制檯日誌「MyObject來未找到」。

我想知道如果有一段時間才能訪問我的對象,如果是這樣,我該如何知道應該等待多長時間來調用我的對象?

回答

44

我想知道,如果有一段時間之前,我可以訪問我的對象

是的,我認爲是有延遲,因爲WebView.addJavascriptInterface將在WebView中的內部工作線程運行。也許你已經考慮過這一點,並且意識到WebView必須至少維護一個工作線程來執行異步網絡IO。也許你在使用WebView時也注意到了DDMS中的這些線程。

事實證明,它也使用一個線程來執行其他一些公共方法的工作。我真的希望谷歌的文檔更清晰!但我希望我能幫助你,告訴你我是如何試圖爲自己確認的。

跟着我看看WebView的源代碼。這是合理的可讀性,即使你不能準確地跟蹤發生了什麼,也可以通過回答關於線程的一些問題來追蹤。

您可以通過SDK管理器工具下載Android框架源代碼,但它也可以在Github上進行鏡像,所以這就是我在這裏鏈接的內容。我猜測並選擇了一個接近某個版本的ICS的標籤。不難找到。我只是谷歌搜索「WebView.java網站:github.com/android」。

的方法WebView.addJavascriptInterface將消息發送到的WebViewCore一個實例:

mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg); 

WebViewCore.java有一堆所謂sendMessage重載方法,但我們並不真正需要知道究竟是被稱爲,因爲他們做的事情幾乎是一樣的。甚至有一個很好的評論給我們一個暗示,我們是在正確的地方!他們都在委託EventHub這是一些內部類的實例。 This method原來是同步的,並且正在向Handler的實例發送消息,這很好地表明這可能正在另一個線程中運行,但爲了完整起見,讓我們來查明!

HandlerEventHub.transferMessages中被實例化,其從WebViewCore.initialize被調用。這裏還有幾個跳轉點,但最終我發現這是從run中調用的WebCoreThreadRunnable的子類),它與新的Thread右邊的here一起實例化。

什麼冒險!因此,儘管我不能確定所有這些移動部件的運行情況,但我非常有信心地說這種方法不同步,並向WebView的工作線程發送消息。我希望這是有道理的!

如果是這樣,我該如何知道應該等待多久才能打電話給我的對象?

不幸的是,我不知道這個答案。我正在研究這個確切的問題,並在我的谷歌搜索過程中在StackOverflow上發現了這個問題。我認爲你有以下選擇,其中一些比其他更好或更容易:

1)只需Thread.sleep爲100毫秒或addJavascriptInterfaceloadUrl("javascript:...")之間的東西。 Blech,我不喜歡這個,但它可能是最簡單的。

2)另一種可能性是,您可以撥打WebView.loadUrl一段JavaScript代碼,專門測試接口是否已設置,並捕獲尚未設置時引發的ReferenceError。但是,正如您可能已經猜到的那樣,這種涉及到向WebView添加JavaScript接口!

3)改爲撥打WebView.setWebChromeClient,並改用JavaScript的alert()console.log。從我的實驗中,這種方法同步,所以沒有延遲。 (我已經在源代碼中證實了這一點,但是我將留給細節作爲練習給讀者)你可能會想出一些特殊的字符串來呼叫alert並在onJsAlert內檢查它,所以你不只是捕捉所有alert()秒。

對不起,這個答案的長度,我希望有幫助。祝你好運!

+0

良好精心答案適當引用的可能性。 –

+0

很酷。很好的回覆。但檢查警報和控制檯消息就像做Thread.sleep():)一樣糟糕。 – Akshat

+0

嘿,我都只是警告說,這些選項是次優的:P – spacemanaki

1

確保您的HTML/Javascript中聲明的您需要從Java訪問的Javascript對象聲明爲全局的,否則它們很可能會被收集。我有一些代碼,做這個(其中Android是我的界面addJavascriptInterface補充):

<script> 
    var cb = function(location) { 
    alert('location is ' + location); 
    } 
    Android.getLocation('cb'); 
</script> 

getLocation方法調用Android的LocationManager.requestSingleUpdate然後調用回調時LocationListener的火災。

沒有「var」我發現在位置查找調用回調時回調函數已被垃圾收集。

0

我已經採取了(從我上a similar question響應複製)賈森·沙阿和S先生的落實作爲構建塊我的修補程序,並在其上大大提高。

只有太多的代碼放在這個評論中,我會直接鏈接到它。

關鍵點是:

  • 適用於薑餅(2.3.x版本)從JS
  • 呼叫到Android的所有版本現在是同步的
  • 不再有t O映射出接口方法手動
  • 固定字符串分隔斷碼
  • 更容易改變JS簽名和接口名稱
相關問題