0

環境

現在、ハイブリッド Android アプリ用のモデル ジェネレーターを設計しようとしています。目標は次のとおりです。PhoneGap を使用して開発されたハイブリッド Android アプリが与えられ場合、UI の状態 (この場合、UI の状態を DOM の状態と同等のものとして扱っています) とこれらの UI の状態への遷移を記述する UI モデルを生成します。 (アクションによって示されます - たとえば、DOM 要素 X をクリックします)。モデルは、ノードが UI 状態で、エッジが遷移である有限状態マシンによって表されます。

問題

私の現在のタスクは、DOM 要素にイベント ハンドラーが登録されているかどうかを確認する方法を考え出すことです (ここでは、最初のDOM 状態のみに関心があると仮定しましょう)。このStackOverflowの回答の助けを借りて、webView.loadURL("javascript:" + ....) を使用して、要素にイベントが登録されているかどうかを判断するソリューションを思いつくことができました。たとえば、element.onclick を使用するか、またはjQuery や Prototype などのライブラリによって提供されるメソッドを使用します。ただし、同じ StackOverflow 回答で指定されている理由により、要素に addEventListener() を介してイベントが登録されているかどうかを現在判断できません。(繰り返しになりますが、簡単にするために、ページが読み込まれた直後、ユーザー操作の前に登録されたイベントのみに関心があると仮定しましょう)。

質問

  1. 私がとろうとしているアプローチは次のとおりです。PhoneGap アプリから JavaScript コードをインターセプトする予定です。インターセプトされたら、addEventListener() を呼び出すたびに、その呼び出しに関係する DOM 要素の「マーカー」を配置するように、(Rhino などを使用して) コードを計測します。次に、このインストルメント化されたコードを WebView に渡し、元の JavaScript コードの代わりにこのインストルメント化された JavaScript コードが読み込まれるようにします。そうすることで、addEventListener() が呼び出された要素を特定できます。これは非常に簡単に思えますが、問題は、インストルメンテーションのために JavaScript コードをインターセプトし、渡す方法を理解できないことです。元のコードの代わりに読み込まれるように、インストルメント化されたコード。説明されているように、この傍受と通過を可能にするツールはありますか? ちなみに、PhoneGap アプリの実行には Android エミュレーターを使用しています。
  2. おそらくより単純な(またはよりエレガントな)他のアプローチはありますか?
4

1 に答える 1

1

私が思いついた解決策は次のとおりです。メソッドがオーバーライドされる新しいCordovaWebViewClient(同じアクティビティと webView オブジェクトをCordovaWebViewClientコンストラクターに渡す)を作成しました。ハイブリッド アプリの HTML ページの読み込みが開始されると、コードが実行されますonPageStarted()onPageStarted()オーバーライド コードは次のことを行います。

  1. すべての HTML/JS/CSS ファイルが配置されていると想定されるアセット フォルダー (file:///android_asset/) に関連する、読み込みを開始したばかりのページの URL を取得します。URL はonPageStarted()のパラメーターの 1 つであるため、このパラメーターの値にアクセスするだけで取得できます。: HTML ファイルが assets/www/foo.html にある場合、相対 URL は www/foo.html です。
  2. を介して入力ストリームを設定して、HTML コードを取得しますactivity.getAssets().open(relativeUrl)。ここactivityで、 は現在のDroidGapアクティビティ、relativeUrlは前の手順で見つかった相対 URL です。
  3. HTML コードをDocumentオブジェクトに解析します (これには Jsoup を使用しました)。
  4. インストルメンテーションとして追加する JS コードを準備し (たとえば、新しいコードをStringオブジェクトに格納することによって)、その新しい JS コードを新しいスクリプト タグの一部としてオブジェクトに挿入しDocumentます。(私の場合は、HTML のhead要素の先頭に新しい script タグを挿入しました)
  5. 変更されたオブジェクトを String に再変換しDocument(この string を呼び出すとしますnewHTML)、loadDataWithBaseURL()次のようにメソッドを呼び出しますwebView.loadDataWithBaseURL("file:///android_asset/www/", newHTML, "text/html", "UTF-8", null)。これにより、インストルメント化されたコードが含まれていますが、基本的にページがリロードされます。

次に、この拡張CordovaWebViewClientを webView オブジェクトの新しい webView クライアントとして設定します (webView.setWebViewClient()メソッドを使用)。最後に、webView.reload()上記の Web ビュー クライアントの変更が有効になるように呼び出しました。その結果、新しい HTML ページが Web ビューに読み込まれるたびに、onPageStarted私が書いたコードが実行されます。

上記の項目 5 はベース URL として「file:///android_asset/www/」を使用し、HTML は文字列で読み込まれるonPageStarted()ため、オーバーライド メソッドの先頭にチェックを含めて、ロードを開始したばかりのページがベース URL と等しくない (つまり、URL が file:///android_asset/www/ と正確に等しくないことを確認します) そうしないと、無限ループが発生します (私も指示しました)。 URL がfile:///android_asset (予想されるベース フォルダー) で始まらない場合onPageStartedは常に実行されません)。

于 2014-01-08T22:18:01.583 に答える