拦截并覆盖来自WebView的HTTP请求

我有一个WebView在我的应用程序中打开一些网站(总是相同的,这是我自己的网页)。 该网站有一些JS代码,从远程主机加载一些图像。

我想拦截对这些图像的请求(通过URL模式),并给予我自己的内容(即另一个图像),或根据内部应用程序逻辑保持请求不变。

有没有可能做到这一点?

编辑 :目前的问题状态…

WebView有能力设置WebViewClient (如Axarydax所述)。 WebViewClient有两个有用的方法

  • shouldOverrideUrlLoading
  • onLoadResource

shouldOverrideUrlLoading能够拦截任何url加载,如果加载是由页面交互触发的(即单击页面上的链接,WebView.loadURL(“”)不触发此方法)。 也可以通过返回false来取消URL加载。 这种方法是不可用的,因为它不能拦截加载页面资源(和图像,我需要拦截,是这样一个页面资源)。

每次页面资源(和图片!thx到jessyjones)加载时, onLoadResource都会触发,但是无法取消该资源。 这使得这个方法也不适合我的任务。

它看起来像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加载,但由于它是一个空白,我还没有find一种方法来更改该url,并将其replace,以便它加载本地资源…

这是我用于我的应用程序的解决scheme。

我有几个资产文件夹与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; } 

您不提A​​PI的版本,但是从API 11开始,有方法WebViewClient.shouldInterceptRequest

也许这可能有帮助?

最终的解决scheme是在回环上embedded一个简单的http服务器监听你的“秘密”端口。 然后你可以用像http:// localhost:123 /…/ mypic.jpg这样的东西replace匹配的图片src URL

这可能有助于:

 @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; }