1. 程式人生 > >Android H5微信支付 webview設定referer 請求頭無效問題解釋和詳細處理方案

Android H5微信支付 webview設定referer 請求頭無效問題解釋和詳細處理方案

Android H5微信支付(或H5視訊連結)webview設定referer 請求頭無效問題解釋和詳細處理方案(附原始碼)

本文說明
這次也是專案中所碰到的問題總結,這次是專案需要對接新的一套第三方微信H5支付。其實開始是很簡單的只需要一個集合了所以必要引數後提交後臺返回的支付連結再加上訂單號就沒有問題,不過由於特殊的ios 內購要求(對內購非常嚴)和對接情況都將按ios的來。

對接流程

通常對接流程

前端提交必要引數到後臺———-後臺生成支付加密連結返回給前端———-前端可以拼接訂單id呼叫微信H5(或者可以直接請求,有的需要提交在webview請求頭) ———– 支付完成(回撥成功失敗)

按ios流程對接

前端提交必要引數到後臺———-後臺生成支付加密連結返回給前端———-前端需要使用webview請求 過程中需要在連結中新增請求頭Referer ———– 支付完成(回撥成功失敗)

問題產生

問題背景

我們在配合第三方支付的技術時,對方表示必要引數是可以前端或者後臺任意一個可以拼接的引數生成支付連結,但是提交到微信H5 則是後臺表示無法執行的,由前端來做,那麼問題就產生了。
IOS 在使用webView是有原生的方法的可以非常方便的將請求頭新增到支付連結上,所以很快就解決了,而且沒有任何相容的問題。
Android 就不一樣了,由於個人對webView沒有過深入瞭解,所以當時還真不知道webView有新增請求頭的方法,後來發現確實有這個方法。

 public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {

    }

但是在使用過程中發現問題: 請求頭沒有新增上。

案發現場

案發現場還原一

上程式碼

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.achers.ascmake.R;
import java.util.HashMap;
import java.util.Map;

/**
 * Create on 2018/3/8 14:42
 * <p>
 * author lhm
 * <p>
 * Description:
 * <p>
 * Version: 1.2.3
 */
public class WebChonzhiAcvitity extends AppCompatActivity {

    private Context context = this;
    private String url;
    private String initUrl;//不拼接UserID的URL
    private String title;

    private WebView mWebView;
    private boolean isFirstLoad = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.webchongzhi);
        //初始化
        initView();

        mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        mWebView.setWebViewClient(new WebViewClient() {

            @Override
            public void onLoadResource(WebView view, String url) {
                super.onLoadResource(view, url);
            }

            @Override
            public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
                super.onReceivedHttpError(view, request, errorResponse);
            }

            @Override
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                handler.proceed();  // 接受所有網站的證書
                super.onReceivedSslError(view, handler, error);
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url1) {
                Map headers = new HashMap();
                if (url1.contains("wx.tenpay.com")) {
                    //wx.tenpay.com 收銀臺點選微信時,shouldOverrideUrlLoading會呼叫兩次,這裡是第二次
                    headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平臺請求頭 一般是對方固定
                } else {
                    //payh5.bbnpay
                    if(!isFirstLoad){
                        //跳轉到收銀臺
                        headers.put("Referer", "https://xxx.xxxx.cn");//商戶申請H5時提交的授權域名
                        isFirstLoad = true;
                    }else{
                        //收銀臺點選微信時,shouldOverrideUrlLoading會呼叫兩次,這裡是第一次
                        headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平臺請求頭 一般是對方固定

                    }
                }
                view.loadUrl(url1, headers);
                return true;
            }



        });
        String Referer="https://xxx.xxxx.cn";  //需要新增到支付連結的請求頭
        String targetUrl=";  //後臺返回的支付連結
        if (("4.4.3".equals(android.os.Build.VERSION.RELEASE))
                || ("4.4.4".equals(android.os.Build.VERSION.RELEASE))) {
            //相容這兩個版本設定referer無效的問題
            mWebView.loadDataWithBaseURL("https://xxx.xxxx.cn",
                    "<script>window.location.href=\"" + targetUrl + "\";</script>",
                    "text/html", "utf-8", null);
        } else {
            Map<String, String> extraHeaders = new HashMap<>();
            extraHeaders.put("Referer", "https://xxx.xxxx.cn");
            mWebView.loadUrl(targetUrl, extraHeaders);
      //  }
    }

    @Override
    protected void onResume() {
        super.onResume();
        mWebView.onResume();
    }

    private void initView() {
        // TODO Auto-generated method stub
        // customViewContainer = (FrameLayout)

        mWebView = (WebView) findViewById(R.id.web);
        WebSettings webSettings = mWebView.getSettings();
        mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        webSettings.setJavaScriptEnabled(true);
        webSettings.setDomStorageEnabled(true);
        webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
        String appCachePath = context.getApplicationContext().getCacheDir()
                .getAbsolutePath();
        webSettings.setAppCachePath(appCachePath);
        webSettings.setAllowFileAccess(true);
        webSettings.setAppCacheEnabled(true);
    }



    @Override
    protected void onPause() {
        super.onPause();
        mWebView.onPause();

    }

    @Override
    protected void onDestroy() {
        try {
            if (mWebView != null) {
                if (null != mWebView.getParent()) {
                    ((ViewGroup) mWebView.getParent()).removeView(mWebView);
                }
                mWebView.removeAllViews();
                mWebView.destroy();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }
}

結果

請求頭丟失

手機系統5.1
通過抓包發現 請求頭並沒有加上。
但是發現請求頭在第一次的時候是加上了,但是被第二次重複載入的時候給預設覆蓋了。

關鍵就是在這段程式碼

 @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url1) {
                Map headers = new HashMap();
                if (url1.contains("wx.tenpay.com")) {
                    //wx.tenpay.com 收銀臺點選微信時,shouldOverrideUrlLoading會呼叫兩次,這裡是第二次
                    headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平臺商請求頭 一般是對方固定
                } else {
                    //payh5.bbnpay
                    if(!isFirstLoad){
                        //跳轉到收銀臺
                        headers.put("Referer", "https://xxx.xxxx.cn");//商戶申請H5時提交的授權域名
                        isFirstLoad = true;
                    }else{
                        //收銀臺點選微信時,shouldOverrideUrlLoading會呼叫兩次,這裡是第一次
                        headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平臺商請求頭 一般是對方固定

                    }
                }
                view.loadUrl(url1, headers);
                return true;
            }

這段程式碼也已經寫得很清楚了,在與微信H5 互動的時候他這個shouldOverrideUrlLoading會調 用兩次 所以第一次加上的請求頭被第二次沒加的請求頭給預設覆蓋了。

解決方法

初始化的時候就新增一次請求頭,在呼叫shouldOverrideUrlLoading 再新增一次請求頭

案發現場還原二

@Route(path = Path.PFWebView)
public class PFWebViewActivity extends BaseBarActivity {

    @BindView(R.id.webView)
    WebView mWebView;
    @BindView(R.id.progressBar)
    ProgressBar pg;
    @Autowired
    Param param;
    private HashMap<String, String> stringStringHashMap;


    @Override
    public void initLayout() {
        setContentView(R.layout.activity_web_view);
    }

    @Override
    protected void initTitleBar() {

    }

    @Override
    protected void initData() {
        param.url="後臺返回的支付連結";
        stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("Referer", "https://shop.cp988.cn");
        mWebView.loadUrl(param.url, stringStringHashMap);

        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);//支援javascript
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//設定允許js彈出alert對話方塊
        webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);  //設定 快取模式
        webSettings.setUseWideViewPort(true);//擴大比例的縮放
        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);//自適應螢幕
        webSettings.setLoadWithOverviewMode(true);



        mWebView.requestFocus();//觸控焦點起作用
        mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);//取消滾動條

        //設定了Alert才會彈出,重新onJsAlert()方法return true可以自定義處理資訊
        mWebView.setWebChromeClient(new WebClient());
        mWebView.setWebViewClient(new TheWebViewClient());
    }

    class WebClient extends WebChromeClient {

        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            return true;
        }

        @Override
        public void onProgressChanged(WebView view, int i) {
            super.onProgressChanged(view, i);
            pg.setVisibility(i == 100 ? View.GONE : View.VISIBLE);
            pg.setProgress(i);
        }

    }

    boolean isFirstLoad = false;

    /**
     * 和H5的互動
     */
    class TheWebViewClient extends android.webkit.WebViewClient {

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url1) {
            Map<String, String> headers = new HashMap<>();
            if (url1.contains("wx.tenpay.com")) {
                //wx.tenpay.com 收銀臺點選微信時,shouldOverrideUrlLoading會呼叫兩次,這裡是第二次
                 headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平臺商請求頭 一般是對方固定
            } else {
                //payh5.bbnpay
                if(!isFirstLoad){
                    //跳轉到收銀臺
                    headers.put("Referer", "https://xxx.xxxx.cn");//商戶申請H5時提交的授權域名
                    isFirstLoad = true;
                }else{
                    //收銀臺點選微信時,shouldOverrideUrlLoading會呼叫兩次,這裡是第一次
                    headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平臺商請求頭 一般是對方固定
                }
            }
            UtilsLog.logger("shouldOverrideUrlLoading>>" + url1);
            view.loadUrl(url1, headers);
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            showLoadingTransparent();
            super.onPageStarted(view, url, favicon);
            UtilsLog.logger(url);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            disableLoadingTransparent();
            super.onPageFinished(view, url);
            UtilsLog.logger(url);
        }

        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            handler.proceed();
            super.onReceivedSslError(view, handler, error);
        }

        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        //    view.loadUrl(url, stringStringHashMap);
            UtilsLog.logger(url);
            return super.shouldInterceptRequest(view, url);
        }
    }



    /**
     * 網頁回退
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
            mWebView.goBack();// 返回前一個頁面
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onDestroy() {
        checkSign();
        if (mWebView != null) {
            mWebView.setVisibility(View.GONE);
            mWebView.removeAllViews();
            mWebView.destroy();
            releaseAllWebViewCallback();
        }
        super.onDestroy();
    }

    private void checkSign() {
        if (param.title.equals("簽到")) {
            RxBus.getInstance().post(new EventModel(EventId.checkh5SignState));
        }
    }

    /**
     * 防止記憶體洩露
     */
    public void releaseAllWebViewCallback() {
        try {
            Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");
            if (sConfigCallback != null) {
                sConfigCallback.setAccessible(true);
                sConfigCallback.set(null, null);
            }
        } catch (NoSuchFieldException e) {
            UtilsLog.log("ActivityWebView.class::" + e.toString());
        } catch (ClassNotFoundException e) {
            UtilsLog.log("ActivityWebView.class::" + e.toString());
        } catch (IllegalAccessException e) {
            UtilsLog.log("ActivityWebView.class::" + e.toString());
        }
    }


}

結果

webview載入網頁出現(“找不到網頁net:err_unknown_url_scheme”)
這樣表示你已經成功一半了,因為這樣的結果表示連結已經加上了請求頭 只是沒有呼叫到微信而已

解決方法

通過根據scheme 協議作出響應跳轉

 /**
     * 根據scheme 協議作出響應跳轉是跳系統瀏覽器還是應用內頁面還是用webView 開啟
     */
    public void doSchemeJump(String linkUrl, Map<String, String> headers) {
        try {
            UtilsLog.logger("doSchemeJump>>" + linkUrl);
            if (!TextUtils.isEmpty(linkUrl)) {
                Uri uri = Uri.parse(linkUrl);
                String scheme = uri.getScheme();

                if (scheme.equals("http") || scheme.equals("https")) {
                    UtilsLog.logger("doSchemeJump>>>loadUrl>>" + linkUrl);

                    loadUrl(linkUrl, uri, headers);
                } else {
                    // 呼叫系統瀏覽器
                    UtilsLog.logger("doSchemeJump>>>loadUrl>>" + linkUrl);

                    openBrowser(linkUrl);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void loadUrl(String linkUrl, Uri uri, Map<String, String> headers) {
        Bundle bundle = parseExtras(uri);
        if (bundle != null) {
            if (bundle.containsKey("scheme")) {
                String scheme = bundle.getString("scheme");
                if (scheme != null && scheme.startsWith("alipays")) {
                    String schemeUrl = URLDecoder.decode(scheme);
                    try {
                        UtilsLog.logger("loadUrl>>open>>" + linkUrl);

                        open(schemeUrl);
                    } catch (Exception e) {
                        e.printStackTrace();
                        openBrowser(linkUrl);
                        finish();
                    }
                    return;
                }
            }
        }
        UtilsLog.logger("loadUrl>>webview載入url>>" + linkUrl);

        mWebView.loadUrl(linkUrl, headers);
    }

    public static Bundle parseExtras(Uri uri) {
        Bundle extras = null;
        Set<String> queryParameterNames = uri.getQueryParameterNames();
        for (String key : queryParameterNames) {
            String value = uri.getQueryParameter(key);
            if (extras == null) {
                extras = new Bundle();
            }
            extras.putString(key, value);
        }

        return extras;
    }

    private void openBrowser(String url) {
        try {
            Uri uri = Uri.parse(url);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void open(String url) throws URISyntaxException {
        Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
        intent.addCategory("android.intent.category.BROWSABLE");
        intent.setComponent(null);
        startActivity(intent);
    }

案發現場三

結合案發一和案發二的修改程式碼執行,發現錘子手機Pro2 (Android 7.1)沒有任何問題的呼叫到微信支付頁面,但是其他手機都可以,在支付請求成功之後,請求頭成功新增,但是在呼叫的時候直接崩潰,當時以為是機型問題,畢竟有手機是可以的,經過測試 三星(Android 7.1) oppo(Android 5.1) vivo(Android 6.0) 華為(Android 4.4) 小米(Android 7.1) 都不可以,這就不是什麼機型問題了,而是程式碼問題。

經過斷點debug 發現問題出這行程式碼

  @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
            view.loadUrl(url, stringStringHashMap);
            UtilsLog.logger(url);
            return super.shouldInterceptRequest(view, url);
        }

解決方法

簡單粗暴,直接去掉就好。

但是我們還是要知道 這句程式碼到底影響了什麼
WebResourceResponse shouldInterceptRequest 在每一次請求資源時,都會通過這個函式來回調 那麼這個方法可以幹什麼可以攔截,對連結進行二次處理,這也是為什麼當初會加這段程式碼的因為就是擔心請求頭沒有加上。

這個方法在呼叫微信的時候結合起來的次數總共達到3次,那麼崩潰原因就在於與微信H5互動時的3次連續重複呼叫 導致資源衝突問題。

最終完整方案

@Route(path = Path.PFWebView)
public class PFWebViewActivity extends BaseBarActivity {

    @BindView(R.id.webView)
    WebView mWebView;
    @BindView(R.id.progressBar)
    ProgressBar pg;
    @Autowired
    Param param;
    private HashMap<String, String> stringStringHashMap;


    @Override
    public void initLayout() {
        setContentView(R.layout.activity_web_view);
    }

    @Override
    protected void initTitleBar() {

    }

    @Override
    protected void initData() {
        titleBar.setVisibility(View.GONE);
            stringStringHashMap = new HashMap<>();
            stringStringHashMap.put("Referer", "https://xxx.xxxx.cn");
            mWebView.loadUrl(param.url, stringStringHashMap);


        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);//支援javascript
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//設定允許js彈出alert對話方塊
        webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);  //設定 快取模式
        webSettings.setUseWideViewPort(true);//擴大比例的縮放
        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);//自適應螢幕
        webSettings.setLoadWithOverviewMode(true);



        mWebView.requestFocus();//觸控焦點起作用
        mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);//取消滾動條

        //設定了Alert才會彈出,重新onJsAlert()方法return true可以自定義處理資訊
        mWebView.setWebChromeClient(new WebClient());
        mWebView.setWebViewClient(new TheWebViewClient());
    }

    class WebClient extends WebChromeClient {

        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
            return true;
        }

        @Override
        public void onProgressChanged(WebView view, int i) {
            super.onProgressChanged(view, i);
            pg.setVisibility(i == 100 ? View.GONE : View.VISIBLE);
            pg.setProgress(i);
        }

    }

    boolean isFirstLoad = false;

    /**
     * 和H5的互動
     */
    class TheWebViewClient extends android.webkit.WebViewClient {

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url1) {
            Map<String, String> headers = new HashMap<>();
            if (url1.contains("wx.tenpay.com")) {
                //wx.tenpay.com 收銀臺點選微信時,shouldOverrideUrlLoading會呼叫兩次,這裡是第二次
                 headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平臺請求頭 一般是對方固定
            } else {
                //payh5.bbnpay
                if(!isFirstLoad){
                    //跳轉到收銀臺
                    headers.put("Referer", "https://xxx.xxxx.cn");//商戶申請H5時提交的授權域名
                    isFirstLoad = true;
                }else{
                    //收銀臺點選微信時,shouldOverrideUrlLoading會呼叫兩次,這裡是第一次
                     headers.put("Referer", "https://xxx.xxxx.cn");//第三方支付平臺請求頭 一般是對方固定
                }
            }
            UtilsLog.logger("shouldOverrideUrlLoading>>" + url1);
            doSchemeJump(url1, headers);
            //view.loadUrl(url1, headers);
            return true;
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            showLoadingTransparent();
            super.onPageStarted(view, url, favicon);
            UtilsLog.logger(url);
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            disableLoadingTransparent();
            super.onPageFinished(view, url);
            UtilsLog.logger(url);
        }

        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
            handler.proceed();
            super.onReceivedSslError(view, handler, error);
        }


    }

    /**
     * 根據scheme 協議作出響應跳轉是跳系統瀏覽器還是應用內頁面還是用webView 開啟
     */
    public void doSchemeJump(String linkUrl, Map<String, String> headers) {
        try {
            UtilsLog.logger("doSchemeJump>>" + linkUrl);
            if (!TextUtils.isEmpty(linkUrl)) {
                Uri uri = Uri.parse(linkUrl);
                String scheme = uri.getScheme();

                if (scheme.equals("http") || scheme.equals("https")) {
                    UtilsLog.logger("doSchemeJump>>>loadUrl>>" + linkUrl);

                    loadUrl(linkUrl, uri, headers);
                } else {
                    // 呼叫系統瀏覽器
                    UtilsLog.logger("doSchemeJump>>>loadUrl>>" + linkUrl);

                    openBrowser(linkUrl);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void loadUrl(String linkUrl, Uri uri, Map<String, String> headers) {
        Bundle bundle = parseExtras(uri);
        if (bundle != null) {
            if (bundle.containsKey("scheme")) {
                String scheme = bundle.getString("scheme");
                if (scheme != null && scheme.startsWith("alipays")) {
                    String schemeUrl = URLDecoder.decode(scheme);
                    try {
                        UtilsLog.logger("loadUrl>>open>>" + linkUrl);

                        open(schemeUrl);
                    } catch (Exception e) {
                        e.printStackTrace();
                        openBrowser(linkUrl);
                        finish();
                    }
                    return;
                }
            }
        }
        UtilsLog.logger("loadUrl>>webview載入url>>" + linkUrl);

        mWebView.loadUrl(linkUrl, headers);
    }

    public static Bundle parseExtras(Uri uri) {
        Bundle extras = null;
        Set<String> queryParameterNames = uri.getQueryParameterNames();
        for (String key : queryParameterNames) {
            String value = uri.getQueryParameter(key);
            if (extras == null) {
                extras = new Bundle();
            }
            extras.putString(key, value);
        }

        return extras;
    }

    private void openBrowser(String url) {
        try {
            Uri uri = Uri.parse(url);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void open(String url) throws URISyntaxException {
        Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
        intent.addCategory("android.intent.category.BROWSABLE");
        intent.setComponent(null);
        startActivity(intent);
    }


    /**
     * 網頁回退
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
            mWebView.goBack();// 返回前一個頁面
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onDestroy() {
        checkSign();
        if (mWebView != null) {
            mWebView.setVisibility(View.GONE);
            mWebView.removeAllViews();
            mWebView.destroy();
            releaseAllWebViewCallback();
        }
        super.onDestroy();
    }

    private void checkSign() {
        if (param.title.equals("簽到")) {
            RxBus.getInstance().post(new EventModel(EventId.checkh5SignState));
        }
    }

    /**
     * 防止記憶體洩露
     */
    public void releaseAllWebViewCallback() {
        try {
            Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");
            if (sConfigCallback != null) {
                sConfigCallback.setAccessible(true);
                sConfigCallback.set(null, null);
            }
        } catch (NoSuchFieldException e) {
            UtilsLog.log("ActivityWebView.class::" + e.toString());
        } catch (ClassNotFoundException e) {
            UtilsLog.log("ActivityWebView.class::" + e.toString());
        } catch (IllegalAccessException e) {
            UtilsLog.log("ActivityWebView.class::" + e.toString());
        }
    }


    @Override
    protected void onPause() {
        super.onPause();
        finish();
    }
}

可能出現的版本問題

在4.4.4、4.4.3的裝置上,設定的Referer沒有生效

if (("4.4.3".equals(android.os.Build.VERSION.RELEASE))
                || ("4.4.4".equals(android.os.Build.VERSION.RELEASE))) {
     //相容這兩個版本設定referer無效的問題
     view.loadDataWithBaseURL("商戶申請H5時提交的授權域名",
                    "<script>window.location.href=\"" + targetUrl + "\";</script>",
                    "text/html", "utf-8", null);
 } else {
      Map<String, String> extraHeaders = new HashMap<>();
      extraHeaders.put("Referer", "商戶申請H5時提交的授權域名");
      view.loadUrl(targetUrl, extraHeaders);
 }

友情提示

本文原始碼 使用了阿里ARouter 和繼承了基類base 按需求刪除替換就好。