Android WebView拦截base64格式图片失败,求解决方案
Android WebView拦截JS注入的Base64图片问题解决
问题背景
在Android WebView中使用WebViewClient的shouldInterceptRequest方法过滤图片,尝试用正则表达式data:image/(jpg|png|jpeg);base64,或直接判断url.contains("data:image")拦截Google的Base64格式图片(示例:data:image/jpeg;base64,+),但均未成功。后续调研得知这类图片是通过JS动态注入的背景图。
无效原因
shouldInterceptRequest仅能拦截网络请求,而data:image格式的Base64图片是直接嵌入在页面中的本地数据,不会触发WebView的网络请求流程;JS动态注入的这类图片更是在DOM渲染阶段生成,完全不走网络请求通道,因此该方法无法捕获到这类图片资源。
解决方法:通过JS注入拦截处理
我们可以通过向WebView注入自定义JS脚本,在页面DOM层面直接处理Base64图片,覆盖静态渲染和动态生成的内容场景。
1. 开启WebView的JS支持
首先确保WebView允许执行JS:
webView.getSettings().setJavaScriptEnabled(true);
2. 注入JS脚本处理静态页面
在WebViewClient的onPageFinished方法中注入脚本,页面加载完成后一次性清理Base64图片:
@Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // 注入JS清理Base64图片 view.loadUrl("javascript:(function(){" + // 遍历所有元素,移除含data:image的背景图 "var elements = document.getElementsByTagName('*');" + "for(var i=0; i<elements.length; i++){" + " var bg = elements[i].style.backgroundImage;" + " if(bg && bg.indexOf('data:image') !== -1){" + " elements[i].style.backgroundImage = 'none';" + " }" + "}" + // 处理img标签的Base64图片 "var imgs = document.getElementsByTagName('img');" + "for(var j=0; j<imgs.length; j++){" + " var src = imgs[j].src;" + " if(src && src.indexOf('data:image') !== -1){" + " imgs[j].src = '';" + " imgs[j].style.display = 'none';" + " }" + "}" + "})()"); }
3. 监听DOM变化处理动态内容
如果页面存在JS动态生成的内容(如AJAX加载、动态DOM插入),需要通过MutationObserver监听DOM变化,实时清理Base64图片:
@Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); view.loadUrl("javascript:(function(){" + // 定义统一清理函数 "function clearBase64Images(){" + " var elements = document.getElementsByTagName('*');" + " for(var i=0; i<elements.length; i++){" + " var bg = elements[i].style.backgroundImage;" + " // 精准匹配目标图片格式的Base64资源" + " if(bg && /data:image\\/(jpg|png|jpeg|svg|ico|webp|tif|tiff|bmp|eps|apng|avif|jfif|pjpeg|pjp|cur);base64,/.test(bg)){" + " elements[i].style.backgroundImage = 'none';" + " }" + " }" + " var imgs = document.getElementsByTagName('img');" + " for(var j=0; j<imgs.length; j++){" + " var src = imgs[j].src;" + " if(src && /data:image\\/(jpg|png|jpeg|svg|ico|webp|tif|tiff|bmp|eps|apng|avif|jfif|pjpeg|pjp|cur);base64,/.test(src)){" + " imgs[j].src = '';" + " imgs[j].style.display = 'none';" + " }" + " }" + "}" + // 页面加载完成后先执行一次清理 "clearBase64Images();" + // 监听DOM变化,实时处理新生成的内容 "var observer = new MutationObserver(function(mutations){" + " mutations.forEach(function(mutation){" + " // 元素样式变化或新增节点时重新清理" + " if(mutation.type === 'attributes' && mutation.attributeName === 'style' || mutation.addedNodes.length > 0){" + " clearBase64Images();" + " }" + " });" + "});" + // 监听整个body的DOM变化 "observer.observe(document.body, {" + " attributes: true," + " childList: true," + " subtree: true" + "});" + "})()"); }
原问题代码参考
用户原拦截代码(仅作参考,无法处理JS注入的Base64图片):
@Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); if (imgCheck(url,res)) { return new WebResourceResponse( BrowserUnit.MIME_TYPE_TEXT_PLAIN, BrowserUnit.URL_ENCODING, new ByteArrayInputStream("".getBytes()) ); } return super.shouldInterceptRequest(view, request); }
private static boolean isImage(String url, Resources res) { BufferedReader imageUrlRegex = openRawFile(res, R.raw.image_regex); try { String line = imageUrlRegex.readLine(); while (line != null) { Pattern pattern = Pattern.compile(line); if (pattern.matcher(url).find()) return true; line = imageUrlRegex.readLine(); } } catch (IOException e) { e.printStackTrace(); return true; } return false; }
使用的正则表达式:
data:image/(jpg|png|jpeg|svg|ico|webp|tif|tiff|bmp|eps|apng|avif|jfif|pjpeg|pjp|cur);base64,
内容的提问来源于stack exchange,提问作者user19627732
相关产品推荐
相关产品推荐

