Browse Source

1.webview的缓存复用问题 无法返回的问题解决
2.HelpCenter改用缓存的方案完成

liukai 2 years ago
parent
commit
c3c04e8b3c

+ 42 - 94
cpt_main/src/main/java/com/hongyegroup/cpt_main/ui/HelpCenterProfileH5Activity.java

@@ -6,23 +6,19 @@ import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.webkit.GeolocationPermissions;
 import android.webkit.JavascriptInterface;
 import android.webkit.ValueCallback;
-import android.webkit.WebChromeClient;
-import android.webkit.WebView;
+import android.webkit.WebBackForwardList;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
 
 import com.guadou.cs_cptservices.YYConstants;
 import com.guadou.cs_cptservices.widget.PickPhotoDialog;
@@ -37,6 +33,7 @@ import com.guadou.lib_baselib.utils.SPUtils;
 import com.guadou.lib_baselib.utils.ThreadPoolUtils;
 import com.guadou.lib_baselib.utils.log.YYLogUtils;
 import com.guadou.lib_baselib.view.MyWebView;
+import com.guadou.lib_baselib.view.WebViewManager;
 import com.guadou.lib_baselib.view.WebViewProgressBar;
 import com.hongyegroup.cpt_main.R;
 import com.luck.picture.lib.entity.LocalMedia;
@@ -147,41 +144,38 @@ public class HelpCenterProfileH5Activity extends BaseVMActivity<BaseViewModel> {
     @SuppressLint("AddJavascriptInterface")
     private void initWeb() {
         FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
-        mWebView = new MyWebView(getApplicationContext());
-        mWebView.setLayoutParams(params);
 
-        //允许访问多媒体
-        mWebView.getSettings().setAllowFileAccess(true);
-        mWebView.getSettings().setAllowFileAccessFromFileURLs(true);
-        mWebView.getSettings().setAllowUniversalAccessFromFileURLs(true);
+        mWebView = WebViewManager.obtain(CommUtils.getContext());
+        mWebView.setLayoutParams(params);
 
         mWebView.addJavascriptInterface(new H5CallBackAndroid(), "webkit");
 
-        mWebView.setWebChromeClient(new WebChromeClient() {
-            //获取html的title标签
+        //文件与图片的选择回调
+        mWebView.setOnWebChooseFileListener(new MyWebView.OnWebChooseFileListener() {
+            @Override
+            public void onWebFileSelect(ValueCallback<Uri[]> callback) {
+                filePathCallback1 = callback;
+                showPickDialog();
+            }
+        });
+
+        //网络状态回调
+        mWebView.setOnWebChangeListener(new MyWebView.OnWebChangeListener() {
             @Override
-            public void onReceivedTitle(WebView view, String title) {
-                YYLogUtils.e("title" + title);
+            public void titleChange(String title) {
 
                 if (!CheckUtil.isEmpty(title) && mTvTitle != null && !title.equals("common_html")) {
                     mTvTitle.setText(title);
-
                     if (title.equals("Help Center")) {
-
                         mIvSearch.setVisibility(View.VISIBLE);
-
                     } else {
-
                         mIvSearch.setVisibility(View.GONE);
-
                     }
                 }
-                super.onReceivedTitle(view, title);
             }
 
-            //获取页面加载的进度
             @Override
-            public void onProgressChanged(WebView view, int newProgress) {
+            public void progressChange(int newProgress) {
 
                 if (newProgress == 100) {
                     mPbWebView.setProgress(100);
@@ -195,48 +189,6 @@ public class HelpCenterProfileH5Activity extends BaseVMActivity<BaseViewModel> {
                 }
                 //不断更新进度
                 mPbWebView.setProgress(newProgress);
-
-            }
-
-            // 指定源的网页内容在没有设置权限状态下尝试使用地理位置API。
-            @Override
-            public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
-                boolean allow = true;   // 是否允许origin使用定位API
-                boolean retain = false; // 内核是否记住这次制授权
-                callback.invoke(origin, true, false);
-            }
-
-            // 之前调用 onGeolocationPermissionsShowPrompt() 申请的授权被取消时,隐藏相关的UI。
-            @Override
-            public void onGeolocationPermissionsHidePrompt() {
-
-            }
-
-            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
-            @Override
-            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
-                //启动系统相册
-//                Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
-//                startActivityForResult(intent, 99);
-                YYLogUtils.w("网页尝试调取Android相机相册");
-                filePathCallback1 = filePathCallback;
-                CommUtils.getHandler().post(() -> {
-                    showPickDialog();
-                });
-
-                return true;
-
-            }
-        });
-
-        mWebView.setOnWebChangeListener(new MyWebView.OnWebChangeListener() {
-            @Override
-            public void titleChange(String title) {
-                YYLogUtils.e("titleChange-" + title);
-            }
-
-            @Override
-            public void progressChange(int newProgress) {
             }
 
             @Override
@@ -298,16 +250,12 @@ public class HelpCenterProfileH5Activity extends BaseVMActivity<BaseViewModel> {
 
                     @Override
                     public void onResult(List<LocalMedia> result) {
-
                         handlePath(result);
-
                     }
 
                     @Override
                     public void onCancel() {
-
                         cancelFilePick();
-
                     }
                 }, 1, false, false, true, 1, 1, false);
 
@@ -326,16 +274,12 @@ public class HelpCenterProfileH5Activity extends BaseVMActivity<BaseViewModel> {
                 ImageSelectExtKt.extOpenCamera(mActivity, new ArrayList<LocalMedia>(), new OnResultCallbackListener<LocalMedia>() {
                     @Override
                     public void onResult(List<LocalMedia> result) {
-
                         handlePath(result);
-
                     }
 
                     @Override
                     public void onCancel() {
-
                         cancelFilePick();
-
                     }
                 }, false, true, 1, 1);
 
@@ -448,9 +392,31 @@ public class HelpCenterProfileH5Activity extends BaseVMActivity<BaseViewModel> {
      * 集成了系统的回退和网页的回退
      */
     public boolean onKeyDown(int keyCode, KeyEvent event) {
+
+        WebBackForwardList webBackForwardList = mWebView.copyBackForwardList();
+        String historyOneOriginalUrl = webBackForwardList.getItemAtIndex(0).getOriginalUrl();
+        int curIndex = webBackForwardList.getCurrentIndex();
+
         if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
-            mWebView.goBack();
-            return true;
+
+            //判断是否是缓存的WebView
+            if (historyOneOriginalUrl.contains("data:text/html;charset=utf-8")) {
+                //说明是缓存复用的的WebView
+                if (curIndex > 1) {
+                    //内部跳转到另外的页面了,可以返回的
+                    mWebView.goBack();
+                    return true;
+                } else {
+                    //等于1的时候就要Finish页面了
+                    return super.onKeyDown(keyCode, event);
+                }
+
+            } else {
+                //如果不是缓存复用的WebView,可以直接返回
+                mWebView.goBack();
+                return true;
+            }
+
         }
         return super.onKeyDown(keyCode, event);
     }
@@ -474,25 +440,7 @@ public class HelpCenterProfileH5Activity extends BaseVMActivity<BaseViewModel> {
     @Override
     protected void onDestroy() {
         super.onDestroy();
-        if (mWebView != null) {
-            mWebView.clearCache(true); //清空缓存
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-                if (mFlContent != null) {
-                    mFlContent.removeView(mWebView);
-                }
-                mWebView.removeAllViews();
-                mWebView.destroy();
-            } else {
-                mWebView.removeAllViews();
-                mWebView.destroy();
-                if (mFlContent != null) {
-                    mFlContent.removeView(mWebView);
-                }
-            }
-            mWebView = null;
-        }
+        WebViewManager.recycle(mWebView);
 
-        //退出当前web进程
-//        System.exit(0);
     }
 }

+ 47 - 7
cs_baselib/src/main/java/com/guadou/lib_baselib/view/MyWebView.java

@@ -2,10 +2,12 @@ package com.guadou.lib_baselib.view;
 
 import android.annotation.SuppressLint;
 import android.content.Context;
+import android.net.Uri;
 import android.os.Build;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.webkit.GeolocationPermissions;
+import android.webkit.ValueCallback;
 import android.webkit.WebChromeClient;
 import android.webkit.WebResourceError;
 import android.webkit.WebResourceRequest;
@@ -15,6 +17,10 @@ import android.webkit.WebView;
 import android.webkit.WebViewClient;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+
+import com.guadou.lib_baselib.utils.CommUtils;
+import com.guadou.lib_baselib.utils.log.YYLogUtils;
 
 /**
  * 自己封装的Webview
@@ -23,6 +29,7 @@ import androidx.annotation.Nullable;
 public class MyWebView extends WebView {
 
     private WebSettings mWebSettings;
+    private boolean isNeedExe = true;
 
     public MyWebView(Context context) {
         super(context);
@@ -51,6 +58,11 @@ public class MyWebView extends WebView {
         mWebSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
         mWebSettings.setGeolocationEnabled(true);   //允许访问地址
 
+        //允许访问多媒体
+        mWebSettings.setAllowFileAccess(true);
+        mWebSettings.setAllowFileAccessFromFileURLs(true);
+        mWebSettings.setAllowUniversalAccessFromFileURLs(true);
+
         setVerticalScrollBarEnabled(false);
         setVerticalScrollbarOverlay(false);
         setHorizontalScrollBarEnabled(false);
@@ -134,10 +146,13 @@ public class MyWebView extends WebView {
         public boolean shouldOverrideUrlLoading(WebView view, String url) {
             if (mListener != null) mListener.onInnerLinkChecked();
 
-            if (!TextUtils.isEmpty(url)) {
-                view.loadUrl(url);
+            if (Build.VERSION.SDK_INT < 26) {
+                if (!TextUtils.isEmpty(url)) {
+                    view.loadUrl(url);
+                }
+                return true;
             }
-            return true;
+            return false;
         }
 
         //WebView加载错误的回调
@@ -157,8 +172,6 @@ public class MyWebView extends WebView {
     };
 
 
-    private boolean isNeedExe = true;
-
     WebChromeClient mWebChromeClient = new WebChromeClient() {
         //获取html的title标签
         @Override
@@ -182,7 +195,6 @@ public class MyWebView extends WebView {
                 }
             }
 
-
         }
 
         // 指定源的网页内容在没有设置权限状态下尝试使用地理位置API。
@@ -196,11 +208,26 @@ public class MyWebView extends WebView {
         // 之前调用 onGeolocationPermissionsShowPrompt() 申请的授权被取消时,隐藏相关的UI。
         @Override
         public void onGeolocationPermissionsHidePrompt() {
+        }
+
+        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+        @Override
+        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
+            //启动系统相册
+//                Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
+//                startActivityForResult(intent, 99);
+            YYLogUtils.w("网页尝试调取Android相机相册");
 
+            CommUtils.getHandler().post(() -> {
+                if (mFilesListener != null) mFilesListener.onWebFileSelect(filePathCallback);
+            });
+
+            return true;
         }
-    };
 
+    };
 
+    //网页状态的回调相关处理
     private OnWebChangeListener mListener;
 
     public interface OnWebChangeListener {
@@ -217,6 +244,19 @@ public class MyWebView extends WebView {
         mListener = listener;
     }
 
+    //网页选择图片文件的回调相关处理
+    private OnWebChooseFileListener mFilesListener;
+
+    public interface OnWebChooseFileListener {
+
+        void onWebFileSelect(ValueCallback<Uri[]> callback);
+    }
+
+    public void setOnWebChooseFileListener(OnWebChooseFileListener listener) {
+        mFilesListener = listener;
+    }
+
+
     /**
      * 暴露方法,是否滑动到底部
      */

+ 8 - 2
cs_baselib/src/main/java/com/guadou/lib_baselib/view/WebViewManager.kt

@@ -21,6 +21,7 @@ object WebViewManager {
     /**
      * 初始化
      */
+    @JvmStatic
     fun prepare(context: Context) {
         if (webViewCache.isEmpty()) {
             Looper.myQueue().addIdleHandler {
@@ -33,7 +34,9 @@ object WebViewManager {
     /**
      * 获取WebView
      */
+    @JvmStatic
     fun obtain(context: Context): MyWebView {
+
         if (webViewCache.isEmpty()) {
             webViewCache.add(create(MutableContextWrapper(context)))
         }
@@ -48,14 +51,16 @@ object WebViewManager {
     /**
      * 回收资源
      */
+    @JvmStatic
     fun recycle(webView: MyWebView) {
         try {
             webView.stopLoading()
             webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null)
             webView.clearHistory()
             webView.pauseTimers()
-            webView.webChromeClient = null
-//            webView.webViewClient = null
+            webView.clearFormData()
+            webView.removeJavascriptInterface("webkit")
+
             val parent = webView.parent
             if (parent != null) {
                 (parent as ViewGroup).removeView(webView)
@@ -72,6 +77,7 @@ object WebViewManager {
     /**
      * 销毁资源
      */
+    @JvmStatic
     fun destroy() {
         try {
             webViewCache.forEach {

+ 64 - 12
cs_cptServices/src/main/java/com/guadou/cs_cptservices/ui/GlobalWebActivity.kt

@@ -3,10 +3,10 @@ package com.guadou.cs_cptservices.ui
 import android.annotation.SuppressLint
 import android.content.Intent
 import android.os.Bundle
-import android.text.TextUtils
 import android.view.KeyEvent
 import android.view.View
 import android.view.ViewGroup
+import android.webkit.JavascriptInterface
 import android.widget.FrameLayout
 import com.guadou.cs_cptservices.R
 import com.guadou.cs_cptservices.base.activity.YYBaseVDBActivity
@@ -14,8 +14,10 @@ import com.guadou.cs_cptservices.databinding.ActivityGlobalWebBinding
 import com.guadou.lib_baselib.base.vm.EmptyViewModel
 import com.guadou.lib_baselib.bean.DataBindingConfig
 import com.guadou.lib_baselib.engine.toast
+import com.guadou.lib_baselib.engine.toastSuccess
 import com.guadou.lib_baselib.ext.checkEmpty
 import com.guadou.lib_baselib.utils.CommUtils
+import com.guadou.lib_baselib.utils.log.YYLogUtils
 import com.guadou.lib_baselib.view.MyWebView
 import com.guadou.lib_baselib.view.WebViewManager
 
@@ -85,12 +87,11 @@ class GlobalWebActivity : YYBaseVDBActivity<EmptyViewModel, ActivityGlobalWebBin
                 var newProgress = progress
                 if (newProgress == 100) {
                     mBinding.pbWebView.setProgress(100)
-                    CommUtils.getHandler()
-                        .postDelayed({ mBinding.pbWebView.visibility = View.GONE }, 200)//0.2秒后隐藏进度条
+                    CommUtils.getHandler().postDelayed({ mBinding.pbWebView.visibility = View.GONE }, 200)//0.2秒后隐藏进度条
                 } else if (mBinding.pbWebView.visibility == View.GONE) {
                     mBinding.pbWebView.visibility = View.VISIBLE
                 }
-                //设置初始进度10,这样会显得效果真一点,总不能从1开始吧
+                //设置初始进度10,这样会显得效果真一点
                 if (newProgress < 10) {
                     newProgress = 10
                 }
@@ -99,16 +100,18 @@ class GlobalWebActivity : YYBaseVDBActivity<EmptyViewModel, ActivityGlobalWebBin
             }
 
             override fun onInnerLinkChecked() {
-
+                YYLogUtils.w("内部跳转Url了")
             }
 
             override fun onWebLoadError() {
-                toast("Load Error")
+                toast("加载网页出错了")
             }
         })
 
-        if (!TextUtils.isEmpty(mWeburl))
-            mWebView.loadUrl(mWeburl!!)
+        mWeburl?.let { mWebView.loadUrl("http://dev-help-center.yycircle.com/helpCenter") }
+//        mWeburl?.let { mWebView.loadUrl(it) }
+
+        mWebView.addJavascriptInterface(H5CallBackAndroid(), "webkit")
 
         mBinding.flContent.addView(mWebView)
     }
@@ -118,11 +121,32 @@ class GlobalWebActivity : YYBaseVDBActivity<EmptyViewModel, ActivityGlobalWebBin
      * 集成了系统的回退和网页的回退
      */
     override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
-        if (keyCode == KeyEvent.KEYCODE_BACK && mWebView!!.canGoBack()) {
-            mWebView.goBack()
-            return true
+        val webBackForwardList = mWebView.copyBackForwardList()
+        val historyOneOriginalUrl = webBackForwardList.getItemAtIndex(0)?.originalUrl
+        val curIndex = webBackForwardList.currentIndex
+
+        return if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
+
+            //判断是否是缓存的WebView
+            if (historyOneOriginalUrl?.contains("data:text/html;charset=utf-8") == true) {
+                //说明是缓存复用的的WebView
+                if (curIndex > 1) {
+                    //内部跳转到另外的页面了,可以返回的
+                    mWebView.goBack()
+                    true
+                } else {
+                    //等于1的时候就要Finish页面了
+                    super.onKeyDown(keyCode, event)
+                }
+            } else {
+                //如果不是缓存复用的WebView,可以直接返回
+                mWebView.goBack()
+                true
+            }
+        } else {
+            super.onKeyDown(keyCode, event)
         }
-        return super.onKeyDown(keyCode, event)
+
     }
 
     override fun onPause() {
@@ -140,4 +164,32 @@ class GlobalWebActivity : YYBaseVDBActivity<EmptyViewModel, ActivityGlobalWebBin
         WebViewManager.recycle(mWebView)
     }
 
+    /**
+     * 内部类-JS与Android通信回调类
+     */
+    inner class H5CallBackAndroid {
+
+        //重新启动Activity加载url
+        @JavascriptInterface
+        fun hopRouting(obj: String) {
+            YYLogUtils.w("Url:$obj")
+            startInstance("", obj)
+        }
+
+        //关闭页面
+        @JavascriptInterface
+        fun onClose(obj: String) {
+            YYLogUtils.w("onClose-数据obj:$obj")
+            mActivity.finish()
+        }
+
+        //提交成功
+        @JavascriptInterface
+        fun onAgree(obj: String) {
+            YYLogUtils.w("onAgree-数据obj:$obj")
+            toastSuccess("提交成功")
+            mActivity.finish()
+        }
+
+    }
 }