WebView/WebViewClient如何拦截<link>与<image>请求并加载本地文件?
WebView拦截样式表与
资源请求的解决方案
WebView会发起这类资源请求,你遇到的拦截方法未触发问题,通常是WebView配置缺失、相对路径解析错误或拦截方法使用不当导致的。以下是具体解决步骤:
1. 配置WebView基础权限
WebView需要开启文件访问权限才能加载本地相关资源,添加以下配置:
WebSettings webSettings = webView.getSettings(); // 允许访问文件 webSettings.setAllowFileAccess(true); // API 16+ 允许从文件URL加载其他文件 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { webSettings.setAllowFileAccessFromFileURLs(true); webSettings.setAllowUniversalAccessFromFileURLs(true); }
2. 正确设置HTML加载的Base URL
如果通过loadDataWithBaseURL加载HTML字符串,必须指定正确的Base URL,否则WebView无法解析相对路径的资源请求。比如你的HTML文件存放在file:///android_asset/epub/chapters/目录下,加载时:
String htmlContent = // 读取HTML文件的内容 String baseUrl = "file:///android_asset/epub/chapters/"; webView.loadDataWithBaseURL(baseUrl, htmlContent, "text/html", "UTF-8", null);
Base URL会作为相对路径的解析基准,确保../stylesheet.css这类路径能被WebView正确转化为完整URL,进而触发拦截方法。
3. 重写shouldInterceptRequest拦截资源请求
shouldInterceptRequest是拦截资源请求的核心方法,需针对不同API版本实现重载,解析请求URL并替换为本地资源:
webView.setWebViewClient(new WebViewClient() { @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Uri requestUri = request.getUrl(); String path = requestUri.getPath(); // 拦截样式表请求 if (path.endsWith(".css")) { // 替换为本地样式文件的输入流,示例从assets读取 try { InputStream inputStream = getAssets().open("epub/stylesheet.css"); return new WebResourceResponse("text/css", "UTF-8", inputStream); } catch (IOException e) { e.printStackTrace(); } } // 拦截图片请求(包括SVG内的image) else if (path.endsWith(".jpeg") || path.endsWith(".jpg")) { try { InputStream inputStream = getAssets().open("epub/image.jpeg"); return new WebResourceResponse("image/jpeg", null, inputStream); } catch (IOException e) { e.printStackTrace(); } } } return super.shouldInterceptRequest(view, request); } // 兼容低版本API(<21) @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { Uri requestUri = Uri.parse(url); String path = requestUri.getPath(); if (path.endsWith(".css")) { try { InputStream inputStream = getAssets().open("epub/stylesheet.css"); return new WebResourceResponse("text/css", "UTF-8", inputStream); } catch (IOException e) { e.printStackTrace(); } } else if (path.endsWith(".jpeg") || path.endsWith(".jpg")) { try { InputStream inputStream = getAssets().open("epub/image.jpeg"); return new WebResourceResponse("image/jpeg", null, inputStream); } catch (IOException e) { e.printStackTrace(); } } return super.shouldInterceptRequest(view, url); } });
关键注意点
- SVG内的
<image>标签使用xlink:href时,WebView会正常解析并发起请求,只要Base URL配置正确,就能被shouldInterceptRequest捕获。 - 若资源存放在外部存储而非assets,需确保App有读取外部存储的权限,且路径处理正确(可通过FileProvider适配Android 7.0+的文件访问限制)。
- 避免使用
onLoadResource拦截,该方法仅告知资源已开始加载,无法替换资源内容;shouldOverrideUrlLoading仅拦截页面跳转类的URL,不拦截资源请求。
内容的提问来源于stack exchange,提问作者Noah
相关产品推荐
相关产品推荐

