背景
由于项目需求要获取某些网页的请求参数信息,get请求的参数拼接在url中,所以可以直接拦截url获得,但是post请求的参数信息存放在body里面,android没有提供方法直接获取,而该网页是其他第三方提供的,不方便修改网页代码来传递参数给android原生这边,所以可以通过js注入的方式来获取。
关键步骤
js代码
核心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();
}
}
WebViewClient注入js代码
在页面加载完成回调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;
}
}
js与android通信桥梁
当页面有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) {
mWebViewClient.nextMessageIsFormRequest(
new FormRequestContents(method, json, enctype));
}
}