66

我的应用程序中有一个 WebView,其中打开了一些站点(始终相同,它是我自己的页面)。该站点有一些从远程主机加载一些图像的 JS 代码。

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

有可能这样做吗?

编辑:问题的当前状态......

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

  • shouldOverrideUrlLoading
  • onLoadResource

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

onLoadResource每次加载该页面资源(和图像!感谢 Jessyjones)时都会触发,但没有办法取消它。这使得这种方法也不适合我的任务。

4

7 回答 7

72

试试这个,我已经在一个类似 wiki 的个人应用程序中使用它:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith("foo://")) {
            // magic
            return true;
        }
        return false;
    }
});
于 2011-01-26T13:23:19.750 回答
55

看起来 API 级别 11 支持您需要的内容。见WebViewClient.shouldInterceptRequest()

于 2011-03-03T14:16:11.493 回答
11

据我所知,shouldOverrideUrlLoading 不是为图像调用,而是为超链接调用......我认为合适的方法是

@Override public void onLoadResource(WebView view, String url)

为 webview 加载的每个资源(图像、样式表、脚本)调用此方法,但由于它是无效的,我还没有找到一种方法来更改该 url 并替换它,以便它加载本地资源......

于 2011-01-26T15:59:20.380 回答
9

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

我有几个带有 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;
        }
于 2016-01-27T00:17:09.073 回答
4

您没有提到 API 版本,但是从 API 11 开始,就有了WebViewClient.shouldInterceptRequest方法

也许这会有所帮助?

于 2012-08-08T12:36:22.737 回答
3

最终的解决方案是在环回上嵌入一个简单的 http 服务器,监听您的“秘密”端口。然后您可以将匹配的图像 src URL 替换为http://localhost:123/.../mypic.jpg

于 2011-09-30T20:19:13.883 回答
3

这可能会有所帮助:

@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;
}
于 2016-03-25T06:00:49.510 回答