Android WebViewはpost要求パラメータの例を動的に修正してブロックします。
需要背景:
ユーザが提出ボタンをクリックした時に、ユーザが提出したデータをブロックする必要があります。
遭遇した問題:
1.ページは自分のフロントエンドではなく、ウェブページのコードを修正できません。
2.ブロックする要求はget要求ではなく、post要求である(困難な点は、ブロックの要求がget要求であれば、urlを持ってきて、後のスティッチングのパラメータキーの値を取り出すだけでいいですが、post要求のパラメータキーの値は私たちには見えません。)
解決ポイント:
webView CientのshuldIntercept Requestを書き換えるという方法
1.この方法はAPI 21以降に現れたものです。もう一つの古い方法も書き換えます。忘れないでください。
2.ウェブページをロードする時、すべてのリソースはショルダーdIntercept Requestを通ります。私たちはショルダーdIntercept Requestとトラッキングツール(Fidder、Chares)を通じて情報を取得したいURLとリソースファイルを取得できます。
3.この方法はサブスレッドで実行されます。UIを更新するなら、スレッドを切り替えることを覚えてください。
ソリューション:
私はここで二つの解決策を見つけました。
方案A:jsに精通する大人達に適しています。
1.画面上のボタンのクリックイベントをブロックし、イベントをクリックする操作を交替します。
このスキームのピット:
1.ロードするjsコードにscriptノードは含まれません。
2.読み込むjsコードにはコメントがありません。
3.読み込むjsコードには必ずセミコロンを付けます。
*上の3つの要求を満たしていないと、ロードするjsは正しく実行できません。
案B:原生のAndroid方式は、前の案に比べて、このような方案は比較的に面倒です。
1.ShuldIntercept Requestを書き直して資源を遮断する
2.サードパーティのウェブページでネットワーク要求を行うjsページをダウンロードして(ウェブページのすべてをダウンロードして、ネットワーク要求を行うjsページを見つけます)、jsページを修正します。
3.処理されたjsページを現地にロードして、後で現地のjsを利用して第三者のjsに置き換えます。(地元のjsページにwebviewとコミュニケーションする橋を追加します。)
追加知識:android WebView Post要求を使用してブラウザのフレームを設置する。
ここで注意したいのですが、post要求パラメータはbyte配列だけでなく、文字列形式のbyte配列に対してキー値でなければなりません。その中のkeyはバックグラウンドサーバでkeyを受信します。バックグラウンドではkeyはどんな値ですか?
以下のコードは直接initWebView()の方法を見ればいいです。
ユーザが提出ボタンをクリックした時に、ユーザが提出したデータをブロックする必要があります。
遭遇した問題:
1.ページは自分のフロントエンドではなく、ウェブページのコードを修正できません。
2.ブロックする要求はget要求ではなく、post要求である(困難な点は、ブロックの要求がget要求であれば、urlを持ってきて、後のスティッチングのパラメータキーの値を取り出すだけでいいですが、post要求のパラメータキーの値は私たちには見えません。)
解決ポイント:
webView CientのshuldIntercept Requestを書き換えるという方法
1.この方法はAPI 21以降に現れたものです。もう一つの古い方法も書き換えます。忘れないでください。
2.ウェブページをロードする時、すべてのリソースはショルダーdIntercept Requestを通ります。私たちはショルダーdIntercept Requestとトラッキングツール(Fidder、Chares)を通じて情報を取得したいURLとリソースファイルを取得できます。
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コードには必ずセミコロンを付けます。
*上の3つの要求を満たしていないと、ロードするjsは正しく実行できません。
案B:原生のAndroid方式は、前の案に比べて、このような方案は比較的に面倒です。
1.ShuldIntercept Requestを書き直して資源を遮断する
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はどんな値ですか?
以下のコードは直接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は、post要求パラメータを動的に修正してブロックしました。例としては、小編集が皆さんに共有している内容です。参考にしていただければと思います。どうぞよろしくお願いします。