簡體   English   中英

從PhoneGap Android應用程序攔截和修改JavaScript代碼

[英]Intercepting and modifying the JavaScript code from PhoneGap Android apps

語境

我目前正在嘗試為混合Android應用程序設計模型生成器。 目標如下:給定使用PhoneGap開發的任何混合Android應用程序,生成一個描述UI狀態的UI模型(在這種情況下,我將UI狀態視為與DOM狀態等效)並轉換為這些UI狀態(由操作表示-例如,單擊DOM元素X)。 該模型由有限狀態機表示,其中節點是UI狀態,邊是過渡。

問題

我當前的任務是想出一種方法來確定DOM元素是否已向其注冊了事件處理程序(現在假設我們只對初始 DOM狀態感興趣)。 借助此StackOverflow答案 ,我能夠提出一個解決方案,該解決方案使用webView.loadURL(“ javascript:” + ....)來確定某個元素是否通過(例如)注冊了一個事件。 ,element.onclick或使用jQuery和Prototype之類的庫提供的方法。 但是,由於相同的StackOverflow答案中指定的原因,我目前無法確定某個元素是否通過addEventListener()向其注冊了事件。 (為簡單起見,再次假設我們只對頁面加載后立即注冊的事件感興趣,而在任何用戶交互之前)。

問題

  1. 我打算采用的方法如下:我計划從PhoneGap應用程序攔截JavaScript代碼。 一旦被攔截,我將檢測代碼(例如,使用Rhino),以便在每次調用addEventListener()之后,都將為該調用中涉及的DOM元素放置一個“標記”。 然后,我將把這個檢測過的代碼傳遞給WebView,以便加載的是這個檢測過的JavaScript代碼,而不是原始的JavaScript代碼。 這樣,我可以確定調用了哪些元素addEventListener()。 這似乎很簡單,但是問題是,我無法找到一種方法來攔截 JavaScript代碼以進行檢測,並傳遞所檢測的代碼以代替原始代碼被加載。 如所述,是否有任何工具可以讓我進行攔截和傳遞? 順便說一句,我正在使用Android模擬器來運行PhoneGap應用。
  2. 我是否應該考慮其他可能更簡單(或更優雅)的方法?

我想出的解決方案如下。 我創建了一個新的CordovaWebViewClient (將相同的活動和webView對象傳遞給CordovaWebViewClient構造函數),其中重寫了onPageStarted()方法。 一旦混合應用中的HTML頁面開始加載, onPageStarted()代碼將執行。 覆蓋的代碼執行以下操作:

  1. 相對於假定所有HTML / JS / CSS文件都位於的資產文件夾(file:/// android_asset /),檢索剛開始加載的頁面的URL。 該URL是onPageStarted()的參數之一,因此您可以通過簡單地訪問此參數的值來檢索它。 示例 :如果HTML文件位於asset / www / foo.html中,則相對URL為www / foo.html
  2. 通過通過activity.getAssets().open(relativeUrl)設置輸入流來檢索HTML代碼,其中activity是當前DroidGap活動,而relativeUrl是在上一步中找到的相對URL。
  3. 將HTML代碼解析為Document對象(我使用Jsoup做到了這一點)。
  4. 准備要添加為工具的JS代碼(例如,通過將新代碼存儲在String對象中),並將該新JS代碼作為新腳本標簽的一部分插入Document對象中。 (就我而言,我在HTML的head元素的開頭插入了新的腳本標簽)
  5. 將修改后的Document對象重新轉換為String(例如,我們將此字符串newHTML ),並按如下所示調用loadDataWithBaseURL()方法: webView.loadDataWithBaseURL("file:///android_asset/www/", newHTML, "text/html", "UTF-8", null) 盡管包含了檢測到的代碼,這實際上可以重新加載頁面。

然后,我將此擴展的CordovaWebViewClient設置為webView對象的新webView客戶端(使用webView.setWebViewClient()方法)。 最后,我調用了webView.reload()以便上面的Web視圖客戶端更改生效。 結果,每次在Web視圖中加載新的HTML頁面時,我編寫的onPageStarted代碼都將執行。

請注意,由於上述項目#5使用“ file:/// android_asset / www /作為基本URL,並且HTML是通過字符串加載的,因此,您還應該在覆蓋的onPageStarted()方法的開頭添加一個檢查,以確保剛開始加載的頁面的URL不等於基本URL(即,檢查URL是否不完全等於file:/// android_asset / www /)。否則,將遇到無限循環。我還指示只要URL不以file:/// android_asset(這是預期的基本文件夾)開頭,就不要執行onPageStarted

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM