Android WebView无需shouldInterceptRequest为每个请求添加Header
Android WebView 全局添加自定义Header(避免POST请求丢失参数)
问题原因分析
你之前在shouldInterceptRequest里修改requestHeaders无效,核心原因是**WebResourceRequest的requestHeaders是只读集合**,直接调用put或clear不会对实际发送的请求产生任何影响。而且如果在这个方法里返回自定义WebResourceResponse,确实会丢失POST请求体,因为WebResourceRequest不包含请求体数据。
可行解决方案
1. 初始页面加载时添加Header
针对WebView加载的第一个页面(主请求),直接使用WebView.loadUrl的重载方法,传入自定义Header集合,系统会自动将Header附加到请求中,完全不会影响POST参数:
val customHeaders = HashMap<String, String>().apply { put("header", "value") } webView.loadUrl("https://your-target-url.com", customHeaders)
2. API 24+ 处理页面内所有子请求(AJAX、静态资源)
从Android 7.0(API 24)开始,WebViewClient新增了onSendHeaders方法——这个方法在请求即将发送前触发,不会拦截请求体,完美解决POST参数丢失的问题。由于requestHeaders仍是只读视图,需要通过反射修改内部的可变Map:
override fun onSendHeaders(view: WebView?, request: WebResourceRequest?) { super.onSendHeaders(view, request) request?.requestHeaders?.let { readOnlyHeaders -> try { // 通过反射获取内部的可变Header集合 val field = readOnlyHeaders.javaClass.getDeclaredField("mHeaders") field.isAccessible = true val mutableHeaders = field.get(readOnlyHeaders) as MutableMap<String, String> // 添加自定义Header mutableHeaders["header"] = "value" } catch (e: Exception) { e.printStackTrace() } } }
这个方法会覆盖页面内所有子请求(包括图片、CSS、AJAX请求),且不会干扰POST请求的参数传递。
3. 兼容API <24的方案(仅处理AJAX请求)
如果需要兼容7.0以下版本,且不想用OkHttp重构请求,可以通过JavaScript注入修改页面内的AJAX请求,给它们添加自定义Header。但这种方式只能处理页面内的XMLHttpRequest请求,无法覆盖静态资源加载:
// 先启用JavaScript webView.settings.javaScriptEnabled = true // 注入重写XMLHttpRequest的JS代码 val injectScript = """ (function() { const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async, user, password) { originalOpen.call(this, method, url, async, user, password); this.setRequestHeader('header', 'value'); }; })(); """ webView.loadUrl("javascript:$injectScript")
内容的提问来源于stack exchange,提问作者Renz Manacmol
相关产品推荐
相关产品推荐

