From fa79c3f807c8d7018c01ab09b5faeda2b2d7d4cd Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Wed, 11 Jun 2025 03:52:48 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=B7=E8=B1=86=E5=8C=85=E4=BC=98=E5=8C=96Ba?= =?UTF-8?q?seWebView=E7=9A=84WebSettings=E9=83=A8=E5=88=86=E5=90=8E?= =?UTF-8?q?=EF=BC=8C=E5=86=8D=E4=BF=AE=E5=A4=8D=E7=82=B9=E5=87=BB=E7=BD=91?= =?UTF-8?q?=E9=A1=B5=E9=93=BE=E6=8E=A5=E6=97=A0=E5=8F=8D=E5=BA=94=E7=9A=84?= =?UTF-8?q?Bug=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webpagesources/build.properties | 4 +- webpagesources/src/beta/AndroidManifest.xml | 15 +- webpagesources/src/main/AndroidManifest.xml | 75 +++-- .../webpagesources/common/BaseWebView.java | 269 ++++++------------ webpagesources/src/stage/AndroidManifest.xml | 10 + 5 files changed, 162 insertions(+), 211 deletions(-) diff --git a/webpagesources/build.properties b/webpagesources/build.properties index 6c25536..d2f1af9 100644 --- a/webpagesources/build.properties +++ b/webpagesources/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Tue Jun 10 07:12:46 GMT 2025 +#Tue Jun 10 19:49:43 GMT 2025 stageCount=0 libraryProject= baseVersion=15.0 publishVersion=15.0.0 -buildCount=11 +buildCount=19 baseBetaVersion=15.0.1 diff --git a/webpagesources/src/beta/AndroidManifest.xml b/webpagesources/src/beta/AndroidManifest.xml index ee78d9f..fa8f0b4 100644 --- a/webpagesources/src/beta/AndroidManifest.xml +++ b/webpagesources/src/beta/AndroidManifest.xml @@ -2,10 +2,23 @@ - + + + + + diff --git a/webpagesources/src/main/AndroidManifest.xml b/webpagesources/src/main/AndroidManifest.xml index 93f023c..848a857 100644 --- a/webpagesources/src/main/AndroidManifest.xml +++ b/webpagesources/src/main/AndroidManifest.xml @@ -12,6 +12,9 @@ + + + + - - + + + + + - - - - - + + + + + + + + + + + - - - - - - + + + + + + + + + + + + - - - - + + + + + + + + + + - - - - + + + + + + + + + + - + \ No newline at end of file diff --git a/webpagesources/src/main/java/cc/winboll/studio/webpagesources/common/BaseWebView.java b/webpagesources/src/main/java/cc/winboll/studio/webpagesources/common/BaseWebView.java index 43200de..c85b5a7 100644 --- a/webpagesources/src/main/java/cc/winboll/studio/webpagesources/common/BaseWebView.java +++ b/webpagesources/src/main/java/cc/winboll/studio/webpagesources/common/BaseWebView.java @@ -1,12 +1,5 @@ package cc.winboll.studio.webpagesources.common; -/** - * @Author ZhanGSKen@QQ.COM - * @Date 2023/06/22 12:57:08 - * @Describe 网页客户端视图基础类 - * 参考:https://blog.csdn.net/Azhuoyanyan/article/details/17531887?app_version=5.15.2&code=app_1562916241&csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%2217531887%22%2C%22source%22%3A%22weixin_38986226%22%7D&uLinkId=usr1mkqgl919blen&utm_source=app - * - */ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; @@ -14,8 +7,8 @@ import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.net.http.SslError; +import android.os.Build; import android.os.Handler; -import android.os.Looper; import android.os.Message; import android.util.AttributeSet; import android.view.GestureDetector; @@ -66,71 +59,87 @@ public class BaseWebView extends WebView { WebChromeClient.FileChooserParams mFileChooserParams; AuthLoginDialog mAuthLoginDialog; - // AuthenticationBean mLastAuthenticationBean; - /** - * 在java代码里new的时候会用到 - * @param context - */ public BaseWebView(Context context) { super(context); } - /** - * 在xml布局文件中使用时自动调用 - * @param context - */ public BaseWebView(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; mBaseWebViewHandler = new BaseWebViewHandler(); - /*TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.test); - String text = ta.getString(R.styleable.test_text); - setText(text + " ZhanGSKen.CN"); - ta.recycle();*/ - //setBackgroundResource(R.drawable.custom_edittext_background); - //setMinWidth(100); - //setPadding(10,0,10,0); - //setPaddingRelative(0,0,0,0); MyWebChromeClient mMyWebChromeClient = new MyWebChromeClient(); setWebChromeClient(mMyWebChromeClient); mBaseWebViewClient = new BaseWebViewClient(); setWebViewClient(mBaseWebViewClient); WebSettings mWebSettings = getSettings(); - // 设置是否启用安全浏览。 + + // ------------------- 优化后的 WebSettings 配置 ------------------- + // 基础功能配置 + mWebSettings.setJavaScriptEnabled(true); // 启用JavaScript + mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); // 允许JS打开新窗口 + mWebSettings.setDomStorageEnabled(true); // 启用DOM存储 + mWebSettings.setDatabaseEnabled(true); // 启用数据库存储 + //mWebSettings.setAppCacheEnabled(true); // 启用应用缓存 + String appCachePath = context.getCacheDir().getAbsolutePath(); + //mWebSettings.setAppCachePath(appCachePath); + mWebSettings.setCacheMode(WebSettings.LOAD_DEFAULT); // 缓存模式 + + // 页面渲染与缩放 + mWebSettings.setUseWideViewPort(true); // 支持viewport标签 + mWebSettings.setLoadWithOverviewMode(true); // 自动加载时适应屏幕 + mWebSettings.setSupportZoom(true); // 支持缩放 + mWebSettings.setBuiltInZoomControls(true); // 显示缩放控件 + mWebSettings.setDisplayZoomControls(false); // 隐藏默认缩放控件 + mWebSettings.setDefaultTextEncodingName("utf-8"); // 默认编码 + mWebSettings.setMinimumFontSize(12); // 最小字体大小 + + // 性能优化 + mWebSettings.setLoadsImagesAutomatically(true); // 自动加载图片 + mWebSettings.setBlockNetworkImage(false); // 不阻止图片加载 + mWebSettings.setRenderPriority(WebSettings.RenderPriority.HIGH); // 高渲染优先级 + + // 混合内容配置(Android 5.0+) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mWebSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); + } + + // 安全配置 + mWebSettings.setSafeBrowsingEnabled(true); // 启用安全浏览 + mWebSettings.setAllowFileAccess(true); // 允许访问文件URL + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + mWebSettings.setAllowFileAccessFromFileURLs(false); // 禁止文件URL访问其他文件 + mWebSettings.setAllowUniversalAccessFromFileURLs(false); // 禁止文件URL执行JS + } + + // 高级功能(可选) + mWebSettings.setGeolocationEnabled(true); // 启用地理位置 + mWebSettings.setNeedInitialFocus(true); // 获取初始焦点 + mWebSettings.setSaveFormData(true); // 保存表单数据 + mWebSettings.setEnableSmoothTransition(true); // 平滑过渡动画 + + // 硬件加速(Android 3.0+) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + + // 字体缩放(100%为默认) + mWebSettings.setTextZoom(100); + // ------------------- WebSettings 配置结束 ------------------- + mWebSettings.setSafeBrowsingEnabled(true); - // 启用JavaScript - mWebSettings.setJavaScriptEnabled(true); - // 设置可以支持缩放 - mWebSettings.setSupportZoom(true); - // 设置true,才能让Webivew支持标签的viewport属性 - mWebSettings.setUseWideViewPort(true); - // 设置出现缩放工具 - mWebSettings.setBuiltInZoomControls(true); - // 设置隐藏缩放控件 - mWebSettings.setDisplayZoomControls(false); - mWebSettings.setDefaultTextEncodingName("utf-8"); - // 允许WebView运行JavaScript,并开启JavaScript Console以接收日志 - mWebSettings.setDomStorageEnabled(true); // 如果有localStorage等需要 - mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); addJavascriptInterface(new JSConsole(mContext), "console"); addJavascriptInterface(new JS(mContext), "local_obj"); - // 最小缩放等级 setInitialScale(60); - mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true); - //winbollView.loadUrl("https://www.so.com"); - mGestureDetector = new GestureDetectorCompat(mContext, new GestureDetector.SimpleOnGestureListener() { @Override public void onLongPress(MotionEvent e) { downX = (int) e.getX(); downY = (int) e.getY(); - //LogUtils.d(TAG, "downX is " + Integer.toString(downX)); - //LogUtils.d(TAG, "downY is " + Integer.toString(downY)); } }); @@ -146,43 +155,19 @@ public class BaseWebView extends WebView { if (type == WebView.HitTestResult.UNKNOWN_TYPE) return false; if (type == WebView.HitTestResult.EDIT_TEXT_TYPE) { - //let TextViewhandles context menu return true; } final ItemLongClickedPopWindow itemLongClickedPopWindow = new ItemLongClickedPopWindow(mContext, ItemLongClickedPopWindow.IMAGE_VIEW_POPUPWINDOW, UIUtil.dip2px(mContext, 180), ViewGroup.LayoutParams.WRAP_CONTENT); - // Setup custom handlingdepending on the type - switch (type) { - case WebView.HitTestResult.PHONE_TYPE: // 处理拨号 - break; - case WebView.HitTestResult.EMAIL_TYPE: // 处理Email - break; - case WebView.HitTestResult.GEO_TYPE: // TODO - break; - case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE: - break; - case WebView.HitTestResult.SRC_ANCHOR_TYPE: // 超链接 - // Log.d(DEG_TAG, "超链接"); - //szUrl = result.getExtra(); - //break; - case WebView.HitTestResult.IMAGE_TYPE: // 处理长按图片的菜单项 - szUrl = result.getExtra(); - //通过GestureDetector获取按下的位置,来定位PopWindow显示的位置 - itemLongClickedPopWindow.showAtLocation(v, Gravity.TOP | Gravity.LEFT, downX, downY + 10); - break; - default: - break; - } + szUrl = result.getExtra(); + + itemLongClickedPopWindow.showAtLocation(v, Gravity.TOP | Gravity.LEFT, downX, downY + 10); itemLongClickedPopWindow.getView(R.id.item_longclicked_copylink) .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - // 复制链接到剪贴板 - // Gets a handle to the clipboard service. ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE); - // Creates a new text clip to put on the clipboard ClipData clip = ClipData.newPlainText("simple text", szUrl); - // Set the clipboard's primary clip. clipboard.setPrimaryClip(clip); Toast.makeText(mContext, "Copy to clipboard.", Toast.LENGTH_SHORT).show(); itemLongClickedPopWindow.dismiss(); @@ -199,67 +184,12 @@ public class BaseWebView extends WebView { return true; } }); - /*setOnCreateContextMenuListener(new View.OnCreateContextMenuListener(){ - public void onCreateContextMenu(ContextMenu menu, View arg1, - ContextMenuInfo arg2) { - final HitTestResult hitTestResult = ((WebView) arg1).getHitTestResult(); - - MenuItem.OnMenuItemClickListener handler = new MenuItem.OnMenuItemClickListener() { - - public boolean onMenuItemClick(MenuItem item) { - switch (item.getItemId()) { - case WEB_CopyLink : { - - break; - } - case WEB_DownLoadLink : { - // 下载链接地址 - new Thread(new LinkDownLoadThread(hitTestResult.getExtra())).start(); - break; - } - } - return true; - } - }; - - // 添加上下文菜单 - int resultType = hitTestResult.getType(); - if ((resultType == HitTestResult.ANCHOR_TYPE) || - (resultType == HitTestResult.IMAGE_ANCHOR_TYPE) || - (resultType == HitTestResult.SRC_ANCHOR_TYPE) || - (resultType == HitTestResult.SRC_IMAGE_ANCHOR_TYPE)) { - Intent i = new Intent(); - //AppLog.d("extrea", result.getExtra()); - MenuItem item = menu.add(0, WEB_CopyLink, 0, "Copy Link").setOnMenuItemClickListener(handler); - MenuItem item2 = menu.add(0, WEB_DownLoadLink, 0, "DownLoad Link").setOnMenuItemClickListener(handler); - item.setIntent(i); - //menu.setHeaderTitle(hitTestResult.getExtra()); - TextView tv = new TextView(mContext); - tv.setText(hitTestResult.getExtra()); - tv.setTextColor(0x8F000000); - tv.setPadding(15, 5, 15, 5); - menu.setHeaderView(tv); - } - } - }); - - setDownloadListener(new MyDownLoadListener(mContext));*/ } - /** - * 不会自动调用,如果有默认style时,在第二个构造函数中调用 - * @param context - * @param attrs - * @param defStyleAttr - */ public BaseWebView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } - /*public void setLastUrl(String lastUrl) { - this.mszLastUrl = lastUrl; - }*/ - public String getLastUrl() { return _mszLastUrl; } @@ -269,12 +199,10 @@ public class BaseWebView extends WebView { Pattern patternHttp = Pattern.compile("(?i)^http[s]{0,1}://", Pattern.CASE_INSENSITIVE); Matcher matcherHttp = patternHttp.matcher(url); if (matcherHttp.matches()) { - // 加载普通 Http 协议访问 stopLoading(); loadUrl(url); return; } else { - // 加载其他协议类型访问 Pattern pattern = Pattern.compile("^[a-z]+:.*", Pattern.MULTILINE); Matcher matcher = pattern.matcher(url); if (matcher.find()) { @@ -303,25 +231,24 @@ public class BaseWebView extends WebView { private class MyWebChromeClient extends WebChromeClient { @Override public void onProgressChanged(WebView view, int newProgress) { - //super.onProgressChanged(view, newProgress); } @Override public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { setFilePathCallback(filePathCallback); setFileChooserParams(fileChooserParams); - //ToastUtils.show("onShowFileChooser"); Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("*/*"); ((AppCompatActivity)mContext).startActivityForResult(intent, MainActivity.REQUEST_FILE_CHOOSER); return true; - //return super.onShowFileChooser(webView, filePathCallback, fileChooserParams); } } @Override public boolean onTouchEvent(MotionEvent event) { - mGestureDetector.onTouchEvent(event); + boolean ret = mGestureDetector.onTouchEvent(event); + LogUtils.d(TAG, String.format("onTouchEvent ret : %s", ret)); + return super.onTouchEvent(event); } @@ -335,7 +262,6 @@ public class BaseWebView extends WebView { public void handleMessage(Message msg) { switch (msg.what) { case MSG_SHOW_DATA:{ - //LogUtils.d(TAG, "(String)msg.obj is " + (String)msg.obj); loadDataWithBaseURL("", (String)msg.obj, "text/html", "UTF-8", ""); break; } @@ -344,14 +270,9 @@ public class BaseWebView extends WebView { } } - /** - * 逻辑处理 - * @author linzewu - */ final class InJavaScriptLocalObj { @JavascriptInterface public void getSource(String html) { - //LogUtils.d(TAG, html); } } @@ -370,11 +291,6 @@ public class BaseWebView extends WebView { } } - /** - * @Author ZhanGSKen@QQ.COM - * @Date 2023/06/22 12:57:08 - * @Describe 网页客户端基础类 - */ class BaseWebViewClient extends WebViewClient { public static final String TAG = "BaseWebViewClient"; @@ -387,42 +303,16 @@ public class BaseWebView extends WebView { mIOnPageFinished.onPageFinished(url); LogUtils.d(TAG, "Page load finished : " + url); _mszLastUrl = url; - //ToastUtils.show("onPageFinished"); - - new Handler(Looper.getMainLooper()).postDelayed(new Runnable(){ - @Override - public void run() { - if (mAuthLoginDialog != null) { - mAuthLoginDialog.checkAndSaveLastAuthenticationBean(); - mAuthLoginDialog = null; - } - } - }, 1000); - } @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { - // WinBoll Studio 网站证书校验 - /*if (SSLUtil.isSSLCertOk(error.getCertificate(), "9F568FCA9E2B3D59FF3BE2F5FF77CB5BFE1D30562D9880D2D354F0DF63A012E1")) { - LogUtils.d(TAG, "WinBoll Studio 网站证书校验通过。"); - handler.proceed(); - return; - }*/ LogUtils.d(TAG, "onReceivedSslError 0\nerror : " + error.toString()); - //LogUtils.d(TAG, "On Received Ssl Error."); - //handler.proceed(); - - //super.onReceivedSslError(view, handler, error); } @Override public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { int statusCode = errorResponse.getStatusCode(); - /*if (statusCode == 404) { - // 处理404错误 - Log.d("WebView", "Received a 404 error: " + failingUrl); - }*/ LogUtils.d(TAG, "onReceivedHttpError statusCode " + Integer.toString(statusCode)); super.onReceivedHttpError(view, request, errorResponse); } @@ -431,18 +321,8 @@ public class BaseWebView extends WebView { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); - /*if (errorCode == WebViewClient.ERROR_TIMEOUT) { - LogUtils.d(TAG, "WebViewClient.ERROR_TIMEOUT"); - ToastUtils.show("WebViewClient.ERROR_TIMEOUT"); - } else if (errorCode == WebViewClient.ERROR_UNKNOWN) { - LogUtils.d(TAG, "WebViewClient.ERROR_UNKNOWN"); - ToastUtils.show("WebViewClient.ERROR_UNKNOWN"); - }*/ LogUtils.d(TAG, "onReceivedError 1\nerrorCode : " + errorCode + "\ndescription :" + description + "\nfailingUrl : " + failingUrl); - - //在此处显示加载失败页面 - //loadFailure.setVisibility(View.VISIBLE); } @Override @@ -462,13 +342,11 @@ public class BaseWebView extends WebView { @Override public void onLoadResource(WebView view, String url) { super.onLoadResource(view, url); - //加载资源 } @Override public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { - //super.onReceivedHttpAuthRequest(view, handler, host, realm); mAuthLoginDialog = new AuthLoginDialog(view, handler, host, realm); mAuthLoginDialog.show(); } @@ -476,15 +354,20 @@ public class BaseWebView extends WebView { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); - //开始加载页面 LogUtils.d(TAG, "Page load started : " + url); _mszLastUrl = url; } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - //点击链接跳转,对网页中超链接按钮的响应。 - //view.loadUrl(url); + view.loadUrl(url); + return true; + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + // 修复Android 5.0点击无反应的问题 + view.loadUrl(request.getUrl().toString()); return true; } } @@ -496,4 +379,18 @@ public class BaseWebView extends WebView { public void setOnPageFinished(IOnPageFinished iOnPageFinished) { mIOnPageFinished = iOnPageFinished; } + + public class JSConsole { + private Context mContext; + + public JSConsole(Context context) { + this.mContext = context; + } + + @JavascriptInterface + public void log(String message) { + LogUtils.d(TAG, message); + } + } } + diff --git a/webpagesources/src/stage/AndroidManifest.xml b/webpagesources/src/stage/AndroidManifest.xml index ee78d9f..007e0f0 100644 --- a/webpagesources/src/stage/AndroidManifest.xml +++ b/webpagesources/src/stage/AndroidManifest.xml @@ -5,7 +5,17 @@ + + + +