重生之传奇法师,太古仙人异界逍遥,辽宁影视频道
有些时候自家app中嵌入的h5页面并不是自家的。但是很多时候又想在h5不知情的情况下获取h5内部请求的参数,这应该怎么做到呢?
带着这个疑问,就有了这篇博客。
最开始想到的方案是直接拦截h5中所有的请求:
1 webview.setwebviewclient(new webviewclient() { 2 @override 3 public webresourceresponse shouldinterceptrequest(webview view, webresourcerequest request) { 4 try { 5 url url = new url(request.geturl()); 6 } catch (malformedurlexception e) { 7 e.printstacktrace(); 8 } 9 log.e("internetactivity", request + ""); 10 return super.shouldinterceptrequest(view, request); 11 } 12 13 });
但是通过此方法只能获取get请求的参数(因为参数直接拼在了url链接中),对于post请求的参数无可奈何。
后来参考了request_data_webviewclient,有了新的实现方式,具体原理为:给h5注入一段js代码,目的是在每次ajax请求都会调用android原生的方法,将请求参数传给客户端。
具体流程如下:
其中,
js注入代码:
1 <script language="javascript"> 2 3 function generaterandom() { 4 return math.floor((1 + math.random()) * 0x10000) 5 .tostring(16) 6 .substring(1); 7 } 8 9 10 // this only works if `open` and `send` are called in a synchronous way 11 // that is, after calling `open`, there must be no other call to `open` or 12 // `send` from another place of the code until the matching `send` is called. 13 requestid = null; 14 xmlhttprequest.prototype.reallyopen = xmlhttprequest.prototype.open; 15 xmlhttprequest.prototype.open = function(method, url, async, user, password) { 16 requestid = generaterandom() 17 var signed_url = url + "ajaxintercept" + requestid; 18 this.reallyopen(method, signed_url , async, user, password); 19 }; 20 xmlhttprequest.prototype.reallysend = xmlhttprequest.prototype.send; 21 xmlhttprequest.prototype.send = function(body) { 22 interception.customajax(requestid, body); 23 this.reallysend(body); 24 }; 25 26 </script>
客户端拦截请求:
1 @override 2 public final webresourceresponse shouldinterceptrequest(final webview view, webresourcerequest request) { 3 string requestbody = null; 4 uri uri = request.geturl(); 5 6 // 判断是否为ajax请求(只要链接中包含ajaxintercept即是) 7 if (isajaxrequest(request)) { 8 // 获取post请求参数 9 requestbody = getrequestbody(request); 10 // 获取原链接 11 uri = getoriginalrequesturi(request, marker); 12 } 13 14 // 重新构造请求,并获取response 15 webresourceresponse webresourceresponse = shouldinterceptrequest(view, new writehandlingwebresourcerequest(request, requestbody, uri)); 16 if (webresourceresponse == null) { 17 return webresourceresponse; 18 } else { 19 return injectintercept(webresourceresponse, view.getcontext()); 20 } 21 }
客户端注入js代码:
1 private webresourceresponse injectintercept(webresourceresponse response, context context) { 2 string encoding = response.getencoding(); 3 string mime = response.getmimetype(); 4 5 // webresourceresponse的mime必须为"text/html",不能是"text/html; charset=utf-8" 6 if (mime.contains("text/html")) { 7 mime = "text/html"; 8 } 9 10 inputstream responsedata = response.getdata(); 11 inputstream injectedresponsedata = injectintercepttostream( 12 context, 13 responsedata, 14 mime, 15 encoding 16 ); 17 return new webresourceresponse(mime, encoding, injectedresponsedata); 18 }
注:根据谷歌官方文档,mime必须为"text/html"。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Android apk 项目一键打包并上传到蒲公英的实现方法
Android 自定义LineLayout实现满屏任意拖动功能的示例代码
android 限制某个操作每天只能操作指定的次数(示例代码详解)
Android 集成 google 登录并获取性别等隐私信息的实现代码
网友评论