中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android WebView通過動態的修改js去攔截post請求參數實例

發布時間:2020-09-15 22:55:25 來源:腳本之家 閱讀:790 作者:xp_code 欄目:移動開發

需求背景:

需要在用戶點擊提交按鈕的時候攔截用戶提交的數據。

遇到的問題:

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請求參數實例就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

玉山县| 饶阳县| 新竹市| 呼和浩特市| 宜宾县| 广宁县| 乌兰浩特市| 旅游| 定结县| 文安县| 兴文县| 舟曲县| 衡南县| 都江堰市| 沧源| 梁山县| 永川市| 天柱县| 秦安县| 汉阴县| 务川| 宕昌县| 且末县| 柞水县| 独山县| 淮滨县| 高青县| 修水县| 曲阳县| 阿克陶县| 夏河县| 南城县| 沽源县| 团风县| 泉州市| 观塘区| 九江市| 延川县| 高邮市| 金川县| 竹北市|