由于项目需求要获取某些网页的请求参数信息,get请求的参数拼接在url中,所以可以直接拦截url获得,但是post请求的参数信息存放在body里面,android没有提供方法直接获取,而该网页是其他第三方提供的,不方便修改网页代码来传递参数给android原生这边,所以可以通过js注入的方式来获取。
2022-06-30 23:05:23.808 15890-16193/com.my.demo E/zbm: 拦截到的post请求数据:
2022-06-30 23:05:23.814 15890-16193/com.my.demo E/zbm: [
{
"name": "action",
"value": "prospect",
"type": "hidden"
},
{
"name": "first_name",
"value": "萌面",
"type": "text"
},
{
"name": "last_name",
"value": "小侠",
"type": "text"
},
{
"name": "country",
"value": "US",
"type": "select-one"
},
{
"name": "zip",
"value": "12345",
"type": "tel"
},
{
"name": "address",
"value": "cupertino ca 95014",
"type": "text"
},
{
"name": "address_2",
"value": "",
"type": "text"
},
{
"name": "city",
"value": "Schenectady",
"type": "text"
},
{
"name": "state",
"value": "NY",
"type": "select-one"
},
{
"name": "phone",
"value": "(123) 458-8555",
"type": "tel"
},
{
"name": "email",
"value": "[email protected]",
"type": "email"
}
]
核心js代码下载jscore
从文件中读取js代码为字符串,便于后面给webview加载
public class IOUtils {
public static byte[] readFully(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
for (int count; (count = in.read(buffer)) != -1; ) {
out.write(buffer, 0, count);
}
return out.toByteArray();
}
}
在页面加载完成回调onPageFinished的时候通过webview.loadUrl()将js代码注入到当前页面
public class InterceptingWebViewClient extends WebViewClient {
private Context mContext = null;
private WebView mWebView = null;
private PostInterceptJavascriptInterface mJSSubmitIntercept;
public InterceptingWebViewClient(Context context, WebView webView) {
mContext = context;
mWebView = webView;
mJSSubmitIntercept = new PostInterceptJavascriptInterface(this);
mWebView.addJavascriptInterface(mJSSubmitIntercept, "interception");
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
mNextAjaxRequestContents = null;
mNextFormRequestContents = null;
view.loadUrl(url);
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
try {
String mInterceptHeader = new String(IOUtils.readFully(mContext.getAssets().open("jscore")));
view.loadUrl("javascript:" + mInterceptHeader);
}catch (Exception e){
Log.e("zbm", "js注入失败:" + e);
}
}
private PostInterceptJavascriptInterface.FormRequestContents mNextFormRequestContents = null;
public void nextMessageIsFormRequest(PostInterceptJavascriptInterface.FormRequestContents formRequestContents) {
mNextFormRequestContents = formRequestContents;
}
private PostInterceptJavascriptInterface.AjaxRequestContents mNextAjaxRequestContents = null;
public void nextMessageIsAjaxRequest(PostInterceptJavascriptInterface.AjaxRequestContents ajaxRequestContents) {
mNextAjaxRequestContents = ajaxRequestContents;
}
}
当页面有post请求时会回调customAjax与customSubmit接口将请求参数传给原生层。
public class PostInterceptJavascriptInterface {
private static String mInterceptHeader;
private InterceptingWebViewClient mWebViewClient;
public PostInterceptJavascriptInterface(InterceptingWebViewClient webViewClient) {
mWebViewClient = webViewClient;
}
public class FormRequestContents {
public String method = null;
public String json = null;
public String enctype = null;
public FormRequestContents(String method, String json, String enctype) {
this.method = method;
this.json = json;
this.enctype = enctype;
}
}
public class AjaxRequestContents {
public String method = null;
public String body = null;
public AjaxRequestContents(String method, String body) {
this.method = method;
this.body = body;
}
}
@JavascriptInterface
public void customAjax(final String method, final String body) {
mWebViewClient.nextMessageIsAjaxRequest(new AjaxRequestContents(method, body));
}
@JavascriptInterface
public void customSubmit(String json, String method, String enctype) {
Log.e("zbm", "customSubmit data: " + json + "---encrypt:" + encrypt);
mWebViewClient.nextMessageIsFormRequest(
new FormRequestContents(method, json, enctype));
}
}