需求背景:

需要在用户点击提交按钮的时候拦截用户提交的数据。

遇到的问题:

1.页面不是自家前端做的,不能修改网页中的代码

2.要拦截的请求不是get请求,而是一个post请求 (难点在于:如果拦截的请求是get请求的话,我只需要拿到url,将后面拼接的参数键值对取出来就好了,但是post请求的参数键值对我们是看不到的。。。)

解决重点:

重写webViewClient的shouldInterceptRequest这个方法

1.这个方法是API21以后才出现的,还有一个过时的方法也要重写,不要忘了!

2.在加载网页时,所有的资源都会经过shouldInterceptRequest这个方法,我们可以通过shouldInterceptRequest和抓包工具(Fidder,Charles)去获取你想要获取信息的网址和资源文件

3.这个方法是执行在子线程的,如果你想要更新UI的话,记得切换线程

解决方案:

我这里找到了两种解决方案(总有一款适合你)

方案A : 适合 精通js 的大大们

1.拦截页面上按钮的点击事件,将点击事件的操作进行替换

$('#J_submit').off('click'); //1.将id为J_submit的按钮点击事件关闭
$('#J_submit').on('click',function(){ //2.将id为J_submit的按钮点击事件重新打开,并执行function里的内容
 if ($(this).hasClass("btn-disabled")) { // -----  此处为原页面代码,不做解释  -----
    return;
   }
 
   try {
    trackDealerEvent('dlr_order_page_form_submit_click', {
     'esfrom': _mediaId,
     'business': 'songshu',
     'series': _seriesId,
     'city': _cityId
    });
   } catch (e) {
    console.log(e);
   }   // -----  此处为原页面代码,不做解释  -----
 var pageFormData = validateAllField(alertDiv);
 if (pageFormData) {  //3.获取到页面内的数据
  $.ajax({  //4.ajax方式上传到服务器中
   url: 'https://gouche.jxedt.com/gouche/clue/submit',
   data: {
   cityid: _cityId,
   brandid: _brandId,
   seriesid: _seriesId,
   classesid: _specId,
   name: $("[name='userName']").val(),
   phone: $('#phoneNumber').val(),
   type: 4
   }
  });
  postOrder(pageFormData);
 }
})

2.动态的加载一段js代码

mCommonWebView.setCommonWebViewClient(new CommonWebViewClient() { //添加自定义的 WebViewClient
 @Override
 public void onPageFinished(WebView view, String url) { //重写onPageFinished方法
  super.onPageFinished(view, url);
  //请求js的网址
  runRemoteJs(Constant.QueryCarPrice.loadJsUrl_CarHome);
 }
 
 private void runJs(String remoteJs){ //把获取到的js代码添加到当前网页
  if(TextUtils.isEmpty(remoteJs)) {
   return;
  }
  String js = "javascript:";  //作用:指明字符串后面的都是js代码
  js = "var script = document.createElement('script');"; // 作用:创建script节点
  js = "script.type = 'text/javascript';"; 
  js =remoteJs;
  mCommonWebView.callJsFunction(js); //加载js代码
 }
 
 private void runRemoteJs(String url) {//前端大大提供的一个网址,网址里面就是上面的js代码,将网页中的代码获取下来
  RxRequest<String> request = new RxRequest<String>()
    .setUrl(url)
    .setMethod(Request.Method.GET);
  RxHttpEngineWrapper.commonExec(request)
    .subscribeOn(AndroidSchedulers.mainThread())
    .subscribe(new UtilsRx.DefaultSubscriber<String>(){
   @Override
   public void onNext(String s) {
    runJs(s);
   }
  });
 }
});

3.到时候只要前端的大大修改页面中的js就可以了

此方案的坑:

1.要加载的js代码中不能包含script节点

2.要加载的js代码中不能有注释

3.要加载的js代码一定要加上分号

*如果不满足上面的三点要求,要加载的js都不能正确的执行

方案B : 原生的Android方式,相对于上一种方案,这种方案比较麻烦

1.重写shouldInterceptRequest去拦截资源

2.将第三方网页上进行网络请求的js页面下载下来(就是把网页的所有下载下来,找到进行网络请求的js页),对js页进行修改

3.将处理好的js页加载到本地,以后加载时就利用本地的js替换第三方的js(我会在本地的js页面中添加与webview沟通的桥梁)

//以下为具体操作,我把具体的方法贴了上去,如果不太懂的可以看看代码,我写了注释
 
 
//初始化WebView
private void initWebView() {
 mWebView.getSettings().setDomStorageEnabled(true);
 mWebView.getSettings().setDefaultTextEncodingName("utf-8");
 if(Build.VERSION.SDK_INT >=21){//Added in API level 21
  mWebView.getSettings().setMixedContentMode(android.webkit.WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
 }
 mWebView.getSettings().setJavaScriptEnabled(true);
 mWebView.getSettings().setUseWideViewPort(true); //设置webview推荐使用的窗口,使html界面自适应屏幕
 mWebView.getSettings().setLoadWithOverviewMode(true);
 
 mWebView.getSettings().setGeolocationEnabled(true);
 
 mWebView.getSettings().setAllowFileAccess(true);
 
 if (Build.VERSION.SDK_INT >= 16) {
  //屏蔽Webview的跨域漏洞
  mWebView.getSettings().setAllowFileAccessFromFileURLs(false);
  mWebView.getSettings().setAllowUniversalAccessFromFileURLs(false);
 }
 
 mWebView.getSettings().setPluginState(WebSettings.PluginState.ON);
 if (Build.VERSION.SDK_INT >= 11) {
  mWebView.getSettings().setAllowContentAccess(true);
 }
 
 mWebView.loadUrl(currUrl);
 mWebView.setWebViewClient(new MyWebViewClient());
 
 //与js通讯的桥梁
 mWebView.addJavascriptInterface(new StubClass(),"stub");
 
}
 
public class MyWebViewClient extends WebViewClient {
 /*两个shouldInterceptRequest方法体中的内容大致相同,因为是demo,我也没有抽取方法*/
 
 @Override
 public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
  //获取的请求参数的 Map 集合
  HashMap<String,String> params;
 
  Uri uri=Uri.parse(url);  //获取网址对应的Uri
 
  if (rightUrl(uri.toString())) {
   /*get请求获取参数*/
   params=paramForGET(uri);
 
   /*重头戏,post请求获取参数*/
   /*
    * 获取post请求参数的思路就是:
    * 找到其网址中进行网络请求的js代码,对这段js代码进行替换
    * 我采取的是拦截第三方网址上请求数据的js资源,将本地的资源提交上去替换原资源
    */
   if (uri.toString().contains("index.js")) {      //拦截该网页下对应的js资源并进行替换
    try {
     //WebResourceResponse的构造器三个参数作用 String mimeType:指定替换资源的类型  String encoding:字符集  InputStream input:输入流
     return new WebResourceResponse("application/x-javascript","UTF-8",getAssets().open("index.js"));
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
  return super.shouldInterceptRequest(view, url);
 }
 
 //API21及21以后才支持此方法
 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
 @Override
 public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
  //获取的请求参数的 Map 集合
  HashMap<String,String> params;
 
  String method=request.getMethod();         //当前网址的提交方式
  Map<String, String> requestHeaders = request.getRequestHeaders(); //获取请求头
  Uri uri=request.getUrl();           //获取网址对应的Uri
 
  if (rightUrl(uri.toString())) {
   /*get请求获取参数*/
   params=paramForGET(uri);
 
   /*重头戏,post请求获取参数*/
   /*
    * 获取post请求参数的思路就是:
    * 找到其网址中进行网络请求的js代码,对这段js代码进行替换
    * 我采取的是拦截第三方网址上请求数据的js资源,将本地的资源提交上去替换原资源
    */
   if (uri.toString().contains("index.js")) {      //拦截该网页下对应的js资源并进行替换
    try {
     //WebResourceResponse的构造器三个参数作用 String mimeType:指定替换资源的类型  String encoding:字符集  InputStream input:输入流
     return new WebResourceResponse("application/x-javascript","UTF-8",getAssets().open("index.js"));
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  }
  return super.shouldInterceptRequest(view, request);
 }
 
 private boolean rightUrl(String url){
  if (url.contains(COLLECT_URL))         //判断资源网址是否是我需要的
   return true;
  return false;
 }
 
 private HashMap<String,String> paramForGET(Uri uri){
  HashMap<String,String> params=new HashMap<>();
 
  Set<String> paramNames = uri.getQueryParameterNames();   //获取此get请求中所有的参数名
 
  /*我这里是将所有的参数都填了进去,大家在获取的时候可以进行筛选和过滤*/
  for (String param : paramNames) {
   params.put(param,uri.getQueryParameter(param));    //存储键值对
  }
 
  return params;
 }
}
 
public class StubClass{
 @JavascriptInterface
 public void getData(String json){
  Log.i("xxx","json -> " json);
 }
}

这是我本地的js,对原来的js进行了修改,添加了与Android通讯的桥梁,来截取数据。

补充知识:android WebView使用Post请求和设置浏览器弹框

这里要注意:post请求参数只能传byte数组,而且必须是键值对字符串形式的byte数组,其中的key是后台服务器接收key,后台规定key是什么值就是什么值,不能随意更改,没有key=value格式或者key不正确,都会请求不到数据网页打不开。

下面代码直接看initWebView()方法就好

package com.xxxxx.xxx.activity.banksign;
 
import org.json.JSONException;
import org.json.JSONObject;
 
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
 
import com.xinzong.etc.R;
import com.xinzong.xx.base.BaseGestureActivty;
import com.xinzong.xxx.utils.ShowReloadUtil;
/**
 * 
 * @author 
 *
 */
public class WebViewActivity extends BaseGestureActivty implements OnClickListener{
	
	private ShowReloadUtil reloadUtil;
 
	private String url = "http://120.1.1.1/xx/xxxx";
	private WebView webView;
	private String urlParameter = "";
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_sign_webview);
		findViewById(R.id.ibBack).setOnClickListener(this);
 
		//获取传过来的支付参数
		urlParameter = getIntent().getStringExtra("urlParameter");
		Log.i("TAG", urlParameter);
		
		//初始化重新加载框
		reloadUtil = new ShowReloadUtil(this);
		reloadUtil.setReloadView(this, R.id.ll_show_data_mc,
				R.id.rl_reload_parent_mc);
		//刷新界面,加载webview
		refresh();
		
		
	}
	
	
	 
	 private void refresh() {
	  if(isNetworkConnected()){
	   findView(R.id.webview1).setVisibility(View.VISIBLE);
	   reloadUtil.showDataView();
	   initWebView();
	  }else{
	   findView(R.id.webview1).setVisibility(View.GONE);
	   reloadUtil.showReload();
	  }
 
	 }
	 
	 private void initWebView() {
	  webView = (WebView) findViewById(R.id.webview1);
	  
	  //初始化webview
	  //启用支持javascript
	  WebSettings settings = webView.getSettings();
	  settings.setJavaScriptEnabled(true);//支持javaScript
	  settings.setDefaultTextEncodingName("utf-8");//设置网页默认编码
	  settings.setJavaScriptCanOpenWindowsAutomatically(true);
	  Log.d("TAG", "url:" url);
	  //post请求(使用键值对形式,格式与get请求一样,key=value,多个用&连接)
	  urlParameter = "JSONpriKey="  urlParameter;
	  webView.postUrl(url, urlParameter.getBytes());
//	  webView.loadUrl(url);//get
	  webView.setWebChromeClient(new MyWebChromeClient());// 设置浏览器可弹窗 
	  //覆盖WebView默认使用第三方或系统默认浏览器打开网页的行为,使网页用WebView打开
	  webView.setWebViewClient(new WebViewClient(){
	   @Override
	  public boolean shouldOverrideUrlLoading(WebView view, String url) {
	    //返回值是true的时候控制去WebView打开,为false调用系统浏览器或第三方浏览器
	    Log.d("TAG", "url:" url);
	    view.loadUrl(url);
	   return true;
	  }
	  @Override
	  	public void onPageStarted(WebView view, String url,
	  			Bitmap favicon) {
	  		Log.d("TAG", "onPageStarted--url:" url);
	  		//支付完成后,点返回关闭界面
	  		if(url.endsWith("http://120.1.1.1/xxx/xx/xxx")){
	  			finish();
	  		}
	  		
	  		super.onPageStarted(view, url, favicon);
	  	}
	  
	  
	  @Override
	  	public void onPageFinished(WebView view, String url) {
	  		super.onPageFinished(view, url);
	  		
	  	}
	   
	  });
	  
	  
 
	 }
 
 
 
		@Override
		public void onClick(View v) {
			if (v.getId() == R.id.btnReload) {// 点击 ‘重新加载'
				
				reloadUtil.showClickloadingView();
				Log.d("TAG", "RELOAD");
				if (this.isNetworkConnected()) {
					webView.loadUrl(url);
				} else {
					reloadUtil.showReload();
				}
			}else if(v.getId() == R.id.ibBack){
				if(webView !=null && webView.canGoBack()){
					webView.goBack();
				}else{
					finish();
				}
			}
			
		}
		
		
		@Override
	 public boolean onKeyDown(int keyCode, KeyEvent event) {
	  if(keyCode == KeyEvent.KEYCODE_BACK && webView !=null && webView.canGoBack()){
	   webView.goBack();
	   return true;
	  }
	  
	  return super.onKeyDown(keyCode, event);
	 }
 
	
		
		 /** 
	  * 浏览器可弹窗 
	  * 
	  * @author Administrator 
	  * 
	  */ 
	 final class MyWebChromeClient extends WebChromeClient { 
	  @Override 
	  public boolean onJsConfirm(WebView view, String url, String message, 
	    final JsResult result) { 
	   new AlertDialog.Builder(CTX) 
	     .setTitle("App Titler") 
	     .setMessage(message) 
	     .setPositiveButton(android.R.string.ok, 
	       new DialogInterface.OnClickListener() { 
	        public void onClick(DialogInterface dialog, 
	          int which) { 
	         result.confirm(); 
	        } 
	       }) 
	     .setNegativeButton(android.R.string.cancel, 
	       new DialogInterface.OnClickListener() { 
	        public void onClick(DialogInterface dialog, 
	          int which) { 
	         result.cancel(); 
	        } 
	       }).create().show(); 
	 
	   return true; 
	  } 
	 } 
}

以上这篇Android WebView通过动态的修改js去拦截post请求参数实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持Devmax。

Android WebView通过动态的修改js去拦截post请求参数实例的更多相关文章

  1. html5 拖拽及用 js 实现拖拽功能的示例代码

    这篇文章主要介绍了html5 拖拽及用 js 实现拖拽,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. 详解如何通过H5(浏览器/WebView/其他)唤起本地app

    这篇文章主要介绍了详解如何通过H5(浏览器/WebView/其他)唤起本地app的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  4. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  6. HTML5页面无缝闪开的问题及解决方案

    这篇文章主要介绍了HTML5页面无缝闪开方案,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  7. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  8. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

  9. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  10. ios – 永远不会调用shouldStartLoadWithRequest

    我已经研究和研究,但仍然不明白为什么从未调用过StartLoadWithRequest.我的页面加载正常,并调用了一些UIWebview委托协议方法.请从以下代码中找到相关的摘要:在我的.m中合成我的webview(在头文件中定义):我成功加载了我的webview:把我的代表设置为自己我的所有协议方法都被称为EXCEPTshouldStartLoadWithRequest提前致谢.解决方法尝试在V

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部