いくつかのサイトが開かれているアプリケーションにWebViewがあります(常に同じ、それは自分のページです)。このサイトには、リモートホストから画像を読み込むJSコードがあります。
このような画像へのリクエストを(URLパターンで)インターセプトし、独自のコンテンツ(つまり別の画像)を返すか、内部アプリケーションロジックに応じてリクエストをそのままにしておきます。
それは可能ですか?
[〜#〜] edit [〜#〜]:質問の現在の状態...
WebView
にはWebViewClient
を設定する機能があります(Axarydaxで説明されています)。 WebViewClient
には2つの便利なメソッドがあります
shouldOverrideUrlLoading
onLoadResource
shouldOverrideUrlLoading
は、ページインタラクションによってロードがトリガーされた場合(つまり、ページ上のリンクがクリックされた場合、WebView.loadURL( "")がこのメソッドをトリガーしない場合)、URLロードをインターセプトできます。 falseを返すことにより、URLの読み込みをキャンセルすることもできます。このアプローチは使用できません。原因は、ページリソースの読み込みをインターセプトできないことです(そして、画像、インターセプトする必要があるのはそのようなページリソースです)。
onLoadResource
は、ページリソース(および画像!からjessyjones)が読み込まれるたびにトリガーされますが、それをキャンセルする方法はありません。このため、この方法は私のタスクにも適していない。
APIレベル11は必要なものをサポートしているようです。 WebViewClient.shouldInterceptRequest()
を参照してください。
これを試して、私は個人的なwikiのようなアプリでそれを使用しました:
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("foo://")) {
// magic
return true;
}
return false;
}
});
私の知る限り、shouldOverrideUrlLoadingは画像ではなく、ハイパーリンクのために呼び出されます...適切なメソッドは
@Override public void onLoadResource(WebView view, String url)
このメソッドは、webviewによってロードされるすべてのリソース(画像、スタイルシート、スクリプト)に対して呼び出されますが、voidであるため、そのURLを変更し、ローカルリソースをロードするように置き換える方法を見つけていません...
これがアプリに使用するソリューションです。
Css/js/img anfフォントファイルを含む複数のアセットフォルダーがあります。
アプリケーションはすべてのファイル名を取得し、この名前のファイルが要求されているかどうかを確認します。はいの場合、アセットフォルダーからロードします。
//get list of files of specific asset folder
private ArrayList listAssetFiles(String path) {
List myArrayList = new ArrayList();
String [] list;
try {
list = getAssets().list(path);
for(String f1 : list){
myArrayList.add(f1);
}
} catch (IOException e) {
e.printStackTrace();
}
return (ArrayList) myArrayList;
}
//get mime type by url
public String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
if (extension.equals("js")) {
return "text/javascript";
}
else if (extension.equals("woff")) {
return "application/font-woff";
}
else if (extension.equals("woff2")) {
return "application/font-woff2";
}
else if (extension.equals("ttf")) {
return "application/x-font-ttf";
}
else if (extension.equals("eot")) {
return "application/vnd.ms-fontobject";
}
else if (extension.equals("svg")) {
return "image/svg+xml";
}
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
//return webresourceresponse
public WebResourceResponse loadFilesFromAssetFolder (String folder, String url) {
List myArrayList = listAssetFiles(folder);
for (Object str : myArrayList) {
if (url.contains((CharSequence) str)) {
try {
Log.i(TAG2, "File:" + str);
Log.i(TAG2, "MIME:" + getMimeType(url));
return new WebResourceResponse(getMimeType(url), "UTF-8", getAssets().open(String.valueOf(folder+"/" + str)));
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
//@TargetApi(Build.VERSION_CODES.Lollipop)
@SuppressLint("NewApi")
@Override
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
//Log.i(TAG2, "SHOULD OVERRIDE INIT");
//String url = webResourceRequest.getUrl().toString();
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
//I have some folders for files with the same extension
if (extension.equals("css") || extension.equals("js") || extension.equals("img")) {
return loadFilesFromAssetFolder(extension, url);
}
//more possible extensions for font folder
if (extension.equals("woff") || extension.equals("woff2") || extension.equals("ttf") || extension.equals("svg") || extension.equals("eot")) {
return loadFilesFromAssetFolder("font", url);
}
return null;
}
APIのバージョンについては言及しませんが、API 11以降のメソッドはあります WebViewClient.shouldInterceptRequest
たぶんこれが役立つでしょうか?
究極の解決策は、ループバックの「秘密」ポートでリッスンする単純なhttpサーバーを埋め込むことです。次に、一致した画像のsrc URLを http:// localhost:123 /.../ mypic.jpg のようなものに置き換えることができます
これが役立つ場合があります:
@TargetApi(Build.VERSION_CODES.Lollipop)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString();
WebResourceResponse response = super.shouldInterceptRequest(view, request);
// load native js
if (url != null && url.contains(INJECTION_TOKEN/* scheme define */)) {
response = new WebResourceResponse(
"text/javascript",
"utf-8",
loadJsInputStream(url, JsCache.getJsFilePath(path) /* InputStream */));
}
return response;
}