Android WebView 辅助类

Android studio webview显示URL内容 阅读详情

DevUtils Github

方法注释
setWebView设置 WebView
getWebView获取 WebView
isWebViewNotEmptyWebView 是否不为 null
setBuilder设置 WebView 常用配置构建类
getBuilder获取 WebView 常用配置构建类
apply应用 ( 设置 ) 配置
setGlobalBuilder设置全局 WebView 常用配置构建类
getGlobalBuilder获取全局 WebView 常用配置构建类
loadUrl加载网页
loadData加载 Html 代码
loadDataWithBaseURL加载 Html 代码
postUrl使用 POST 方法将带有 postData 的 url 加载到 WebView 中
getSettings获取 WebView 配置
getUserAgentString获取浏览器标识 UA
setUserAgentString设置浏览器标识
addJavascriptInterface添加 JS 交互注入对象
removeJavascriptInterface移除 JS 交互注入对象
evaluateJavascript执行 JS 方法
setWebViewClient设置处理各种通知和请求事件对象
getWebViewClient获取处理各种通知和请求事件对象
setWebChromeClient设置辅助 WebView 处理 Javascript 对话框、标题等对象
getWebChromeClient获取辅助 WebView 处理 Javascript 对话框、标题等对象
destroy销毁处理
canGoBackWebView 是否可以后退
goBackWebView 后退
canGoForwardWebView 是否可以前进
goForwardWebView 前进
canGoBackOrForwardWebView 是否可以跳转到当前起始点相距的历史记录
goBackOrForwardWebView 跳转到当前起始点相距的历史记录
reload刷新页面 ( 当前页面的所有资源都会重新加载 )
stopLoading停止加载
clearCache清除资源缓存
clearHistory清除当前 WebView 访问的历史记录
clearFormData清除自动完成填充的表单数据
getScale获取缩放比例
getScrollY获取当前可见区域的顶端距整个页面顶端的距离 ( 当前内容滚动的距离 )
getScrollX获取当前内容横向滚动距离
getContentHeight获取 HTML 的高度 ( 原始高度, 不包括缩放后的高度 )
getScaleHeight获取缩放高度
getHeight获取 WebView 控件高度
pageDown将视图内容向下滚动一半页面大小
pageUp将视图内容向上滚动一半页面大小
handlerKeyDown处理按键 ( 是否回退 )
setLayerTypeSoftware关闭 WebView 硬件加速功能
setLayerType设置 WebView 硬件加速类型
getUrl获取当前 Url
getOriginalUrl获取最初请求 Url
getHitTestResult获取长按事件类型
setCookie将 Cookie 设置到 WebView
getCookie获取指定 Url 的 Cookie
removeCookie移除 Cookie
removeSessionCookie移除 Session Cookie
removeAllCookie移除所有的 Cookie
setOnApplyListener设置应用配置监听事件
getApplyListener获取应用配置监听事件
clone克隆方法 ( 用于全局配置克隆操作 )
reset重置方法
isJavaScriptEnabled是否支持 JavaScript
setJavaScriptEnabled设置是否支持 JavaScript
getRenderPriority获取渲染优先级
setRenderPriority设置渲染优先级
isUseWideViewPort是否使用宽视图
setUseWideViewPort设置是否使用宽视图
isLoadWithOverviewMode是否按宽度缩小内容以适合屏幕
setLoadWithOverviewMode设置是否按宽度缩小内容以适合屏幕
getLayoutAlgorithm获取基础布局算法
setLayoutAlgorithm设置基础布局算法
isSupportZoom是否支持缩放
setSupportZoom设置是否支持缩放
isBuiltInZoomControls是否显示内置缩放工具
setBuiltInZoomControls设置是否显示内置缩放工具
isDisplayZoomControls是否显示缩放工具
setDisplayZoomControls设置是否显示缩放工具
getTextZoom获取文本缩放倍数
setTextZoom设置文本缩放倍数
getStandardFontFamily获取 WebView 字体
setStandardFontFamily设置 WebView 字体
getDefaultFontSize获取 WebView 字体大小
setDefaultFontSize设置 WebView 字体大小
getMinimumFontSize获取 WebView 支持最小字体大小
setMinimumFontSize设置 WebView 支持最小字体大小
getMixedContentMode获取混合内容模式
setMixedContentMode设置混合内容模式
isLoadsImagesAutomatically是否支持自动加载图片
setLoadsImagesAutomatically设置是否支持自动加载图片
isJavaScriptCanOpenWindowsAutomatically是否支持通过 JS 打开新窗口
setJavaScriptCanOpenWindowsAutomatically设置是否支持通过 JS 打开新窗口
getDefaultTextEncodingName获取编码格式
setDefaultTextEncodingName设置编码格式
isGeolocationEnabled是否允许网页执行定位操作
setGeolocationEnabled设置是否允许网页执行定位操作
isAllowFileAccess是否可以访问文件 ( false 不影响 assets 和 resources 资源的加载 )
setAllowFileAccess设置是否可以访问文件 ( false 不影响 assets 和 resources 资源的加载 )
isAllowFileAccessFromFileURLs是否允许通过 file url 加载的 JS 代码读取其他的本地文件
setAllowFileAccessFromFileURLs设置是否允许通过 file url 加载的 JS 代码读取其他的本地文件
isAllowUniversalAccessFromFileURLs是否允许通过 file url 加载的 JS 可以访问其他的源 ( 包括 http、https 等源 )
setAllowUniversalAccessFromFileURLs设置是否允许通过 file url 加载的 JS 可以访问其他的源 ( 包括 http、https 等源 )
getCacheMode获取 WebView 缓存模式
setCacheMode设置 WebView 缓存模式
isDomStorageEnabled是否支持 DOM Storage
setDomStorageEnabled设置是否支持 DOM Storage
isAppCacheEnabled是否开启 Application Caches 功能
setAppCacheEnabled设置是否开启 Application Caches 功能
getAppCachePath获取 Application Caches 地址
setAppCachePath设置 Application Caches 地址
getAppCacheMaxSize获取 Application Caches 大小
setAppCacheMaxSize设置 Application Caches 大小
isDatabaseEnabled是否支持数据库缓存
setDatabaseEnabled设置是否支持数据库缓存
getDatabasePath获取数据库缓存路径
setDatabasePath设置数据库缓存路径
onApply应用配置通知方法
package dev.assist;

import android.graphics.Paint;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.util.Map;

import dev.DevUtils;
import dev.utils.LogPrintUtils;
import dev.utils.app.ViewUtils;

/**
 * detail: WebView 辅助类
 * @author Ttt
 * <pre>
 *     WebView 截图使用 {@link dev.utils.app.CapturePictureUtils#snapshotByWebView(WebView)}
 *     <p></p>
 *     WebView 全面解析
 *     @see <a href="https://www.jianshu.com/p/3e0136c9e748"/>
 *     Android WebView 常见问题及解决方案汇总
 *     @see <a href="https://www.cnblogs.com/Free-Thinker/p/6179016.html"/>
 *     WebView 与 JavaScript 的交互总结
 *     @see <a href="https://www.jianshu.com/p/5cc2eae14e07"/>
 *     WebView 使用漏洞
 *     @see <a href="https://blog.youkuaiyun.com/carson_ho/article/details/64904635"/>
 *     Android Webview H5 交互之 LocalStorage
 *     @see <a href="https://www.jianshu.com/p/379a0681ce25"/>
 * </pre>
 */
public class WebViewAssist {

    // 日志 TAG
    private static final String TAG = WebViewAssist.class.getSimpleName();
    // WebView
    private WebView mWebView;
    // WebView 常用配置构建类
    private Builder mBuilder;
    // 全局配置
    private static Builder sGlobalBuilder;

    public WebViewAssist() {
        this(true);
    }

    /**
     * 构造函数
     * <pre>
     *     使用全局配置, 需要手动调用 {@link #apply} 方法
     * </pre>
     * @param listener 是否复用监听事件
     */
    public WebViewAssist(final boolean listener) {
        if (sGlobalBuilder != null) {
            mBuilder = sGlobalBuilder.clone(listener);
        }
    }

    /**
     * 设置 WebView
     * <pre>
     *     如果在 {@link #setWebView} 前调用了 {@link #setBuilder} 则需要手动调用 {@link #apply}
     * </pre>
     * @param webView {@link WebView}
     * @return {@link WebViewAssist}
     */
    public WebViewAssist setWebView(final WebView webView) {
        this.mWebView = webView;
        return this;
    }

    /**
     * 获取 WebView
     * @return {@link WebView}
     */
    public WebView getWebView() {
        return mWebView;
    }

    /**
     * WebView 是否不为 null
     * @return {@code true} yes, {@code false} no
     */
    public boolean isWebViewNotEmpty() {
        return mWebView != null;
    }

    /**
     * 设置 WebView 常用配置构建类
     * @param builder {@link Builder}
     * @return {@link WebViewAssist}
     */
    public WebViewAssist setBuilder(final Builder builder) {
        return setBuilder(builder, true);
    }

    /**
     * 设置 WebView 常用配置构建类
     * @param builder {@link Builder}
     * @param apply   是否应用配置
     * @return {@link WebViewAssist}
     */
    public WebViewAssist setBuilder(final Builder builder, final boolean apply) {
        this.mBuilder = builder;
        if (this.mBuilder != null) {
            this.mBuilder.setWebViewAssist(this);
            if (apply) {
                this.mBuilder.apply();
            }
        }
        return this;
    }

    /**
     * 获取 WebView 常用配置构建类
     * @return {@link Builder}
     */
    public Builder getBuilder() {
        return mBuilder;
    }

    /**
     * 应用 ( 设置 ) 配置
     * @return {@link Builder}
     */
    public WebViewAssist apply() {
        return setBuilder(mBuilder);
    }

    // =

    /**
     * 设置全局 WebView 常用配置构建类
     * @param builder {@link Builder}
     */
    public static void setGlobalBuilder(final Builder builder) {
        WebViewAssist.sGlobalBuilder = builder;
    }

    /**
     * 获取全局 WebView 常用配置构建类
     * @return {@link Builder}
     */
    public static Builder getGlobalBuilder() {
        return WebViewAssist.sGlobalBuilder;
    }

    // ============
    // = 加载方法 =
    // ============

    /**
     * 加载网页
     * <pre>
     *     加载一个网页
     *     loadUrl("http://www.baidu.com")
     *     加载应用资源文件内的网页
     *     loadUrl("file:///android_asset/test.html")
     * </pre>
     * @param url 资源地址
     * @return {@link WebViewAssist}
     */
    public WebViewAssist loadUrl(final String url) {
        if (isWebViewNotEmpty()) {
            mWebView.loadUrl(url);
        }
        return this;
    }

    /**
     * 加载网页
     * @param url                   资源地址
     * @param additionalHttpHeaders Http 请求头信息
     * @return {@link WebViewAssist}
     */
    public WebViewAssist loadUrl(final String url, final Map<String, String> additionalHttpHeaders) {
        if (isWebViewNotEmpty()) {
            mWebView.loadUrl(url, additionalHttpHeaders);
        }
        return this;
    }

    /**
     * 加载 Html 代码
     * @param data     Html 数据
     * @param mimeType 加载网页的类型
     * @param encoding 编码格式
     * @return {@link WebViewAssist}
     * @deprecated 推荐使用 loadDataWithBaseURL
     */
    @Deprecated
    public WebViewAssist loadData(final String data, final String mimeType, final String encoding) {
        if (isWebViewNotEmpty()) {
            mWebView.loadData(data, mimeType, encoding);
        }
        return this;
    }

    /**
     * 加载 Html 代码
     * @param baseUrl    基础链接
     * @param data       Html 数据
     * @param mimeType   加载网页的类型
     * @param encoding   编码格式
     * @param historyUrl 可用历史记录
     * @return {@link WebViewAssist}
     */
    public WebViewAssist loadDataWithBaseURL(final String baseUrl, final String data, final String mimeType, final String encoding, final String historyUrl) {
        if (isWebViewNotEmpty()) {
            mWebView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
        }
        return this;
    }

    /**
     * 使用 POST 方法将带有 postData 的 url 加载到 WebView 中
     * <pre>
     *     如果 url 不是网络 url {@link #loadUrl(String)} 加载
     * </pre>
     * @param url      资源地址
     * @param postData post 数据 ( 注意 UrlEncode )
     * @return {@link WebViewAssist}
     */
    public WebViewAssist postUrl(final String url, final byte[] postData) {
        if (isWebViewNotEmpty()) {
            mWebView.postUrl(url, postData);
        }
        return this;
    }

    // =

    /**
     * 加载 Html 代码
     * @param data Html 数据
     * @return {@link WebViewAssist}
     */
    public WebViewAssist loadDataWithBaseURL(final String data) {
        return loadDataWithBaseURL(null, data, null);
    }

    /**
     * 加载 Html 代码
     * @param baseUrl    基础链接
     * @param data       Html 数据
     * @param historyUrl 可用历史记录
     * @return {@link WebViewAssist}
     */
    public WebViewAssist loadDataWithBaseURL(final String baseUrl, final String data, final String historyUrl) {
        return loadDataWithBaseURL(baseUrl, data, "text/html", "utf-8", historyUrl);
    }

    // ================
    // = 快速操作方法 =
    // ================

    /**
     * 获取 WebView 配置
     * @return {@link WebSettings}
     */
    public WebSettings getSettings() {
        return isWebViewNotEmpty() ? mWebView.getSettings() : null;
    }

    /**
     * 获取浏览器标识 UA
     * @return 浏览器标识 UA
     */
    public String getUserAgentString() {
        WebSettings webSettings = getSettings();
        return (webSettings != null) ? webSettings.getUserAgentString() : null;
    }

    /**
     * 设置浏览器标识
     * @param ua 浏览器标识
     * @return {@link WebViewAssist}
     */
    public WebViewAssist setUserAgentString(final String ua) {
        WebSettings webSettings = getSettings();
        if (webSettings != null) {
            webSettings.setUserAgentString(ua);
        }
        return this;
    }

    // =

    /**
     * 添加 JS 交互注入对象
     * @param obj           JavaScript 交互方法注入对象
     * @param interfaceName 在 JavaScript 中公开对象的名称
     * @return {@link WebViewAssist}
     */
    public WebViewAssist addJavascriptInterface(final Object obj, final String interfaceName) {
        if (isWebViewNotEmpty()) {
            mWebView.addJavascriptInterface(obj, interfaceName);
        }
        return this;
    }

    /**
     * 移除 JS 交互注入对象
     * @param interfaceName 在 JavaScript 中公开对象的名称
     * @return {@link WebViewAssist}
     */
    public WebViewAssist removeJavascriptInterface(final String interfaceName) {
        if (isWebViewNotEmpty()) {
            mWebView.removeJavascriptInterface(interfaceName);
        }
        return this;
    }

    /**
     * 执行 JS 方法
     * @param script         JS 内容
     * @param resultCallback 执行回调结果 ( 返回值 )
     * @return {@link WebViewAssist}
     */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public WebViewAssist evaluateJavascript(final String script, final ValueCallback<String> resultCallback) {
        if (isWebViewNotEmpty()) {
            try {
                mWebView.evaluateJavascript(script, resultCallback);
            } catch (Exception e) {
                LogPrintUtils.eTag(TAG, e, "evaluateJavascript");
            }
        }
        return this;
    }

    // =

    /**
     * 设置处理各种通知和请求事件对象
     * <pre>
     *     常用方法
     *     onPageStarted()onPageFinished() 页面加载时和页面加载完毕时调用
     *     shouldOverrideKeyEvent() 重写此方法才能处理浏览器中的按键事件
     *     shouldInterceptRequest() 页面每一次请求资源之前都会调用这个方法 ( 非 UI 线程调用 )
     *     onLoadResource() 页面加载资源时调用, 每加载一个资源 ( 比如图片 ) 就调用一次
     *     onReceivedError() 加载页面的服务器出现错误 ( 比如 404 ) 时回调
     *     onReceivedSslError() 重写此方法可以让 WebView 处理 https 请求
     *     doUpdateVisitedHistory() 更新历史记录
     *     onFormResubmission() 应用程序重新请求网页数据
     *     onReceivedHttpAuthRequest() 获取返回信息授权请求
     *     onScaleChanged() WebView 发生缩放改变时调用
     *     onUnhandledKeyEvent() Key 事件未被加载时调用
     * </pre>
     * @param client {@link WebViewClient}
     * @return {@link WebViewAssist}
     */
    public WebViewAssist setWebViewClient(final WebViewClient client) {
        if (isWebViewNotEmpty()) {
            mWebView.setWebViewClient(client);
        }
        return this;
    }

    /**
     * 获取处理各种通知和请求事件对象
     * @return {@link WebViewClient}
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public WebViewClient getWebViewClient() {
        return isWebViewNotEmpty() ? mWebView.getWebViewClient() : null;
    }

    // =

    /**
     * 设置辅助 WebView 处理 Javascript 对话框、标题等对象
     * <pre>
     *     常用方法
     *     onProgressChanged() 获得网页的加载进度并显示
     *     onReceivedTitle() 获得网页的标题时回调
     *     onReceivedIcon() 获得网页的图标时回调
     *     onCreateWindow() 打开新窗口时回调
     *     onCloseWindow() 关闭窗口时回调
     *     onJsAlert() 网页弹出提示框时触发此方法
     *     onJsConfirm() 网页弹出确认框时触发此方法
     *     onJsPrompt() 网页弹出输入框时触发此方法
     * </pre>
     * @param client {@link WebChromeClient}
     * @return {@link WebViewAssist}
     */
    public WebViewAssist setWebChromeClient(final WebChromeClient client) {
        if (isWebViewNotEmpty()) {
            mWebView.setWebChromeClient(client);
        }
        return this;
    }

    /**
     * 获取辅助 WebView 处理 Javascript 对话框、标题等对象
     * @return {@link WebChromeClient}
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public WebChromeClient getWebChromeClient() {
        return isWebViewNotEmpty() ? mWebView.getWebChromeClient() : null;
    }

    // =

    /**
     * 销毁处理
     * <pre>
     *     避免 WebView 引起的内存泄漏
     *     可通过 WebView 所在的 Activity 新启一个进程结束时 System.exit(0) 退出当前进程
     *     Activity onDestroy use
     * </pre>
     * @return {@link WebViewAssist}
     */
    public WebViewAssist destroy() {
        if (isWebViewNotEmpty()) {
            mWebView.clearHistory();
            ViewUtils.removeSelfFromParent(mWebView);
            mWebView.loadUrl("about:blank");
            mWebView.stopLoading();
            mWebView.setWebChromeClient(null);
            mWebView.setWebViewClient(null);
            mWebView.destroy();
            mWebView = null;
            if (mBuilder != null) {
                mBuilder.setWebViewAssist(null);
            }
        }
        return this;
    }

    /**
     * WebView 是否可以后退
     * @return {@code true} yes, {@code false} no
     */
    public boolean canGoBack() {
        return isWebViewNotEmpty() ? mWebView.canGoBack() : false;
    }

    /**
     * WebView 后退
     * @return {@link WebViewAssist}
     */
    public WebViewAssist goBack() {
        if (isWebViewNotEmpty()) {
            mWebView.goBack();
        }
        return this;
    }

    // =

    /**
     * WebView 是否可以前进
     * @return {@code true} yes, {@code false} no
     */
    public boolean canGoForward() {
        return isWebViewNotEmpty() ? mWebView.canGoForward() : false;
    }

    /**
     * WebView 前进
     * @return {@link WebViewAssist}
     */
    public WebViewAssist goForward() {
        if (isWebViewNotEmpty()) {
            mWebView.goForward();
        }
        return this;
    }

    // =

    /**
     * WebView 是否可以跳转到当前起始点相距的历史记录
     * @param steps 相距索引
     * @return {@code true} yes, {@code false} no
     */
    public boolean canGoBackOrForward(final int steps) {
        return isWebViewNotEmpty() ? mWebView.canGoBackOrForward(steps) : false;
    }

    /**
     * WebView 跳转到当前起始点相距的历史记录
     * <pre>
     *     以当前的 index 为起始点前进或者后退到历史记录中指定的 steps
     *     如果 steps 为负数则为后退, 正数则为前进
     * </pre>
     * @param steps 相距索引
     * @return {@link WebViewAssist}
     */
    public WebViewAssist goBackOrForward(final int steps) {
        if (isWebViewNotEmpty()) {
            mWebView.goBackOrForward(steps);
        }
        return this;
    }

    // =

    /**
     * 刷新页面 ( 当前页面的所有资源都会重新加载 )
     * @return {@link WebViewAssist}
     */
    public WebViewAssist reload() {
        if (isWebViewNotEmpty()) {
            mWebView.reload();
        }
        return this;
    }

    /**
     * 停止加载
     * @return {@link WebViewAssist}
     */
    public WebViewAssist stopLoading() {
        if (isWebViewNotEmpty()) {
            mWebView.stopLoading();
        }
        return this;
    }

    /**
     * 清除资源缓存
     * <pre>
     *     缓存是针对每个应用程序的, 因此这将清除所有使用的 WebView 的缓存
     * </pre>
     * @param includeDiskFiles 是否清空本地缓存 ( false 则只会清空内存缓存, true 全部清空 )
     * @return {@link WebViewAssist}
     */
    public WebViewAssist clearCache(final boolean includeDiskFiles) {
        if (isWebViewNotEmpty()) {
            mWebView.clearCache(includeDiskFiles);
        }
        return this;
    }

    /**
     * 清除当前 WebView 访问的历史记录
     * @return {@link WebViewAssist}
     */
    public WebViewAssist clearHistory() {
        if (isWebViewNotEmpty()) {
            mWebView.clearHistory();
        }
        return this;
    }

    /**
     * 清除自动完成填充的表单数据
     * <pre>
     *     并不会清除 WebView 存储到本地的数据
     * </pre>
     * @return {@link WebViewAssist}
     */
    public WebViewAssist clearFormData() {
        if (isWebViewNotEmpty()) {
            mWebView.clearFormData();
        }
        return this;
    }

    /**
     * 获取缩放比例
     * @return 缩放比例
     */
    public float getScale() {
        if (isWebViewNotEmpty()) {
            return mWebView.getScale();
        }
        return 1.0f;
    }

    /**
     * 获取当前可见区域的顶端距整个页面顶端的距离 ( 当前内容滚动的距离 )
     * @return 当前内容滚动的距离
     */
    public int getScrollY() {
        return isWebViewNotEmpty() ? mWebView.getScrollY() : 0;
    }

    /**
     * 获取当前内容横向滚动距离
     * @return 当前内容横向滚动距离
     */
    public int getScrollX() {
        return isWebViewNotEmpty() ? mWebView.getScrollX() : 0;
    }

    /**
     * 获取 HTML 的高度 ( 原始高度, 不包括缩放后的高度 )
     * <pre>
     *     可通过 setWebViewClient onScaleChanged(WebView view, float oldScale, float newScale) 获取缩放比例
     *     或者通过 webView.getScale(); 获取 ( 该方法已抛弃 )
     * </pre>
     * @return HTML 的高度 ( 原始高度, 不包括缩放后的高度 )
     */
    public int getContentHeight() {
        return isWebViewNotEmpty() ? mWebView.getContentHeight() : 0;
    }

    /**
     * 获取缩放高度
     * @return 缩放高度
     */
    public int getScaleHeight() {
        return getScaleHeight(getScale());
    }

    /**
     * 获取缩放高度
     * @param scale 缩放比例
     * @return 缩放高度
     */
    public int getScaleHeight(final float scale) {
        return (int) (getContentHeight() * scale);
    }

    /**
     * 获取 WebView 控件高度
     * @return WebView 控件高度
     */
    public int getHeight() {
        return isWebViewNotEmpty() ? mWebView.getHeight() : 0;
    }

    /**
     * 将视图内容向下滚动一半页面大小
     * @param bottom 是否滑动到底部
     * @return {@link WebViewAssist}
     */
    public WebViewAssist pageDown(final boolean bottom) {
        if (isWebViewNotEmpty()) {
            mWebView.pageDown(bottom);
        }
        return this;
    }

    /**
     * 将视图内容向上滚动一半页面大小
     * @param top 是否滑动到顶部
     * @return {@link WebViewAssist}
     */
    public WebViewAssist pageUp(final boolean top) {
        if (isWebViewNotEmpty()) {
            mWebView.pageUp(top);
        }
        return this;
    }

    /**
     * 处理按键 ( 是否回退 )
     * <pre>
     *     Activity use
     *     @Override
     *     public boolean onKeyDown(int keyCode, KeyEvent event) {
     *          if (webViewAssist.handlerKeyDown(keyCode, event)) return true;
     *          return super.onKeyDown(keyCode, event);
     *     }
     * </pre>
     * @param keyCode 按键类型
     * @param event   按键事件
     * @return {@code true} 拦截事件, {@code false} 不拦截接着处理
     */
    public boolean handlerKeyDown(final int keyCode, final KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && canGoBack()) {
            goBack();
            return true;
        }
        return false;
    }

    /**
     * 关闭 WebView 硬件加速功能
     * <pre>
     *     解决 WebView 闪烁问题
     * </pre>
     * @return {@link WebViewAssist}
     */
    public WebViewAssist setLayerTypeSoftware() {
        return setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    /**
     * 设置 WebView 硬件加速类型
     * @param layerType 硬件加速类型
     * @param paint     {@link Paint}
     * @return {@link WebViewAssist}
     */
    public WebViewAssist setLayerType(final int layerType, final Paint paint) {
        if (isWebViewNotEmpty()) {
            mWebView.setLayerType(layerType, paint);
        }
        return this;
    }

    /**
     * 获取当前 Url
     * @return 当前 Url
     */
    public String getUrl() {
        return isWebViewNotEmpty() ? mWebView.getUrl() : null;
    }

    /**
     * 获取最初请求 Url
     * @return 最初请求 Url
     */
    public String getOriginalUrl() {
        return isWebViewNotEmpty() ? mWebView.getOriginalUrl() : null;
    }

    /**
     * 获取长按事件类型
     * <pre>
     *     WebView.HitTestResult.UNKNOWN_TYPE // 未知类型
     *     WebView.HitTestResult.PHONE_TYPE // 电话类型
     *     WebView.HitTestResult.EMAIL_TYPE // 电子邮件类型
     *     WebView.HitTestResult.GEO_TYPE // 地图类型
     *     WebView.HitTestResult.SRC_ANCHOR_TYPE // 超链接类型
     *     WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE // 带有链接的图片类型
     *     WebView.HitTestResult.IMAGE_TYPE // 单纯的图片类型
     *     WebView.HitTestResult.EDIT_TEXT_TYPE // 选中的文字类型
     *     <p></p>
     *     mWebView.setOnLongClickListener(new View.OnLongClickListener() {
     *          @Override
     *          public boolean onLongClick(View view) {
     *              WebView.HitTestResult result = webViewAssist.getHitTestResult();
     *              if(result != null) {
     *                  switch (result.getType()) {
     *                      case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
     *                          String imgUrl = result.getExtra();
     *                          return true;
     *                  }
     *              }
     *              return false;
     *          }
     *      });
     *      <p></p>
     *      HitTestResult.getType() 获取所选中目标的类型, 可以是图片、超链接、邮件、电话等等
     *      HitTestResult.getExtra() 获取额外的信息
     * </pre>
     * @return 长按事件类型
     */
    public WebView.HitTestResult getHitTestResult() {
        return isWebViewNotEmpty() ? mWebView.getHitTestResult() : null;
    }

    // ==========
    // = Cookie =
    // ==========

    /**
     * 将 Cookie 设置到 WebView
     * <pre>
     *     若两次设置相同, 则覆盖上一次的
     *     同步 Cookie 要在 WebView 加载 url 之前, 否则 WebView 无法获得相应的 Cookie, 也就无法通过验证
     *     Cookie 应该被及时更新, 否则很可能导致 WebView 拿的是旧的 session id 和服务器进行通信
     * </pre>
     * @param url    加载的 Url
     * @param cookie 同步的 cookie
     * @return {@code true} success, {@code false} fail
     */
    public static boolean setCookie(final String url, final String cookie) {
        try {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                CookieSyncManager.createInstance(DevUtils.getContext());
            }
            CookieManager cookieManager = CookieManager.getInstance();
            // 如果没有特殊需求, 这里只需要将 session id 以 "key=value" 形式作为 Cookie 即可
            cookieManager.setCookie(url, cookie);
            return true;
        } catch (Exception e) {
            LogPrintUtils.eTag(TAG, e, "setCookie");
        }
        return false;
    }

    /**
     * 获取指定 Url 的 Cookie
     * @param url Url
     * @return Cookie
     */
    public static String getCookie(final String url) {
        try {
            CookieManager cookieManager = CookieManager.getInstance();
            return cookieManager.getCookie(url);
        } catch (Exception e) {
            LogPrintUtils.eTag(TAG, e, "getCookie");
        }
        return null;
    }

    /**
     * 移除 Cookie
     * @param callback 移除回调
     */
    public static void removeCookie(final ValueCallback<Boolean> callback) {
        removeSessionCookie(callback);
        removeAllCookie(callback);
    }

    /**
     * 移除 Session Cookie
     * @param callback 移除回调
     * @return {@code true} success, {@code false} fail
     */
    public static boolean removeSessionCookie(final ValueCallback<Boolean> callback) {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                CookieManager.getInstance().removeSessionCookies(callback);
            } else {
                CookieManager.getInstance().removeSessionCookie();
            }
            return true;
        } catch (Exception e) {
            LogPrintUtils.eTag(TAG, e, "removeSessionCookie");
        }
        return false;
    }

    /**
     * 移除所有的 Cookie
     * @param callback 移除回调
     * @return {@code true} success, {@code false} fail
     */
    public static boolean removeAllCookie(final ValueCallback<Boolean> callback) {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                CookieManager.getInstance().removeAllCookies(callback);
            } else {
                CookieManager.getInstance().removeAllCookie();
            }
            return true;
        } catch (Exception e) {
            LogPrintUtils.eTag(TAG, e, "removeAllCookie");
        }
        return false;
    }

    // ============
    // = 配置相关 =
    // ============

    /**
     * detail: WebView 常用配置构建类
     * @author Ttt
     * <pre>
     *     有特殊配置可在 {@link OnApplyListener#onApply(WebViewAssist, Builder)} 回调中进行增加配置设置
     * </pre>
     */
    public static class Builder {

        // WebView 辅助类
        private WebViewAssist mWebViewAssist;
        // 应用配置监听事件
        private OnApplyListener mApplyListener;

        public Builder() {
        }

        /**
         * 构造函数
         * @param applyListener 应用配置监听事件
         */
        public Builder(final OnApplyListener applyListener) {
            setOnApplyListener(applyListener);
        }

        // =

        /**
         * 设置 WebView 辅助类
         * @param webViewAssist WebView 辅助类
         * @return {@link Builder}
         */
        private Builder setWebViewAssist(final WebViewAssist webViewAssist) {
            this.mWebViewAssist = webViewAssist;
            return this;
        }

        /**
         * 应用 ( 设置 ) 配置
         * @return {@link Builder}
         */
        public Builder apply() {
            return applyPri();
        }

        // ========
        // = 事件 =
        // ========

        /**
         * 设置应用配置监听事件
         * @param applyListener {@link OnApplyListener}
         * @return {@link Builder}
         */
        public Builder setOnApplyListener(final OnApplyListener applyListener) {
            this.mApplyListener = applyListener;
            return this;
        }

        /**
         * 获取应用配置监听事件
         * @return {@link OnApplyListener}
         */
        public OnApplyListener getApplyListener() {
            return mApplyListener;
        }

        /**
         * detail: 应用配置监听事件
         * @author Ttt
         */
        public interface OnApplyListener {

            /**
             * 应用配置通知方法
             * @param webViewAssist WebView 辅助类
             * @param builder       WebView 常用配置构建类
             */
            void onApply(WebViewAssist webViewAssist, Builder builder);
        }

        // ============
        // = 克隆方法 =
        // ============

        /**
         * 克隆方法 ( 用于全局配置克隆操作 )
         * @param listener 是否复用监听事件
         * @return {@link Builder}
         */
        public Builder clone(final boolean listener) {
            Builder builder = new Builder();
            if (listener) { // 复用监听事件
                builder.setOnApplyListener(mApplyListener);
            }
            builder.mJavaScriptEnabled = mJavaScriptEnabled;
            builder.mRenderPriority = mRenderPriority;
            builder.mUseWideViewPort = mUseWideViewPort;
            builder.mLoadWithOverviewMode = mLoadWithOverviewMode;
            builder.mLayoutAlgorithm = mLayoutAlgorithm;
            builder.mSupportZoom = mSupportZoom;
            builder.mBuiltInZoomControls = mBuiltInZoomControls;
            builder.mDisplayZoomControls = mDisplayZoomControls;
            builder.mTextZoom = mTextZoom;
            builder.mStandardFontFamily = mStandardFontFamily;
            builder.mDefaultFontSize = mDefaultFontSize;
            builder.mMinimumFontSize = mMinimumFontSize;
            builder.mMixedContentMode = mMixedContentMode;
            builder.mLoadsImagesAutomatically = mLoadsImagesAutomatically;
            builder.mJavaScriptCanOpenWindowsAutomatically = mJavaScriptCanOpenWindowsAutomatically;
            builder.mDefaultTextEncodingName = mDefaultTextEncodingName;
            builder.mGeolocationEnabled = mGeolocationEnabled;
            builder.mUserAgentString = mUserAgentString;
            builder.mAllowFileAccess = mAllowFileAccess;
            builder.mAllowFileAccessFromFileURLs = mAllowFileAccessFromFileURLs;
            builder.mAllowUniversalAccessFromFileURLs = mAllowUniversalAccessFromFileURLs;
            builder.mCacheMode = mCacheMode;
            builder.mDomStorageEnabled = mDomStorageEnabled;
            builder.mAppCacheEnabled = mAppCacheEnabled;
            builder.mAppCachePath = mAppCachePath;
            builder.mAppCacheMaxSize = mAppCacheMaxSize;
            builder.mDatabaseEnabled = mDatabaseEnabled;
            builder.mDatabasePath = mDatabasePath;
            return builder;
        }

        /**
         * 重置方法
         * @return {@link Builder}
         */
        public Builder reset() {
            this.mJavaScriptEnabled = true;
            this.mRenderPriority = null;
            this.mUseWideViewPort = false;
            this.mLoadWithOverviewMode = true;
            this.mLayoutAlgorithm = null;
            this.mSupportZoom = true;
            this.mBuiltInZoomControls = false;
            this.mDisplayZoomControls = false;
            this.mTextZoom = 0;
            this.mStandardFontFamily = null;
            this.mDefaultFontSize = 0;
            this.mMinimumFontSize = 0;
            this.mMixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW;
            this.mLoadsImagesAutomatically = true;
            this.mJavaScriptCanOpenWindowsAutomatically = true;
            this.mDefaultTextEncodingName = "utf-8";
            this.mGeolocationEnabled = true;
            this.mUserAgentString = null;
            this.mAllowFileAccess = true;
            this.mAllowFileAccessFromFileURLs = false;
            this.mAllowUniversalAccessFromFileURLs = false;
            this.mCacheMode = WebSettings.LOAD_NO_CACHE;
            this.mDomStorageEnabled = true;
            this.mAppCacheEnabled = true;
            this.mAppCachePath = null;
            this.mAppCacheMaxSize = 5 * 1024 * 1024;
            this.mDatabaseEnabled = true;
            this.mDatabasePath = null;
            return this;
        }

        // ============
        // = 配置方法 =
        // ============

        // 是否支持 JavaScript
        private boolean mJavaScriptEnabled = true;
        // 渲染优先级
        private WebSettings.RenderPriority mRenderPriority = null;
        // 是否使用宽视图 ( 是否支持 html viewport 设置了会导致字体变小 )
        private boolean mUseWideViewPort = false;
        // 是否按宽度缩小内容以适合屏幕
        private boolean mLoadWithOverviewMode = true;
        // 基础布局算法
        private WebSettings.LayoutAlgorithm mLayoutAlgorithm = null;
        // 是否支持缩放
        private boolean mSupportZoom = true;
        // 是否显示内置缩放工具
        private boolean mBuiltInZoomControls = false;
        // 是否显示缩放工具
        private boolean mDisplayZoomControls = false;
        // 文本缩放倍数
        private int mTextZoom = 0;
        // WebView 字体, 默认字体 "sans-serif"
        private String mStandardFontFamily = null;
        // WebView 字体大小
        private int mDefaultFontSize = 0;
        // WebView 支持最小字体大小
        private int mMinimumFontSize = 0;
        // 混合内容模式
        private int mMixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW;
        // 是否支持自动加载图片
        private boolean mLoadsImagesAutomatically = true;
        // 是否支持通过 JS 打开新窗口
        private boolean mJavaScriptCanOpenWindowsAutomatically = true;
        // 编码格式
        private String mDefaultTextEncodingName = "utf-8";
        // 是否允许网页执行定位操作
        private boolean mGeolocationEnabled = true;
        // 浏览器标识 UA
        private String mUserAgentString = null;
        // 是否可以访问文件 ( false 不影响 assets 和 resources 资源的加载 )
        private boolean mAllowFileAccess = true;
        // 是否允许通过 file url 加载的 JS 代码读取其他的本地文件
        private boolean mAllowFileAccessFromFileURLs = false;
        // 是否允许通过 file url 加载的 JS 可以访问其他的源 ( 包括 http、https 等源 )
        private boolean mAllowUniversalAccessFromFileURLs = false;
        // WebView 缓存模式
        private int mCacheMode = WebSettings.LOAD_NO_CACHE;
        // 是否支持 DOM Storage
        private boolean mDomStorageEnabled = true;
        // 是否开启 Application Caches 功能
        private boolean mAppCacheEnabled = true;
        // Application Caches 地址
        private String mAppCachePath = null;
        // Application Caches 大小
        private long mAppCacheMaxSize = 5 * 1024 * 1024;
        // 是否支持数据库缓存
        private boolean mDatabaseEnabled = true;
        // 数据库缓存路径
        private String mDatabasePath = null;

        /**
         * 应用 ( 设置 ) 配置
         * @return {@link Builder}
         */
        private Builder applyPri() {
            if (mWebViewAssist != null) {
                WebSettings webSettings = mWebViewAssist.getSettings();
                if (webSettings != null) {
                    // 如果访问的页面中要与 JavaScript 交互, 则 WebView 必须设置支持 JavaScript
                    webSettings.setJavaScriptEnabled(mJavaScriptEnabled);

                    if (mRenderPriority != null) {
                        webSettings.setRenderPriority(mRenderPriority);  // 设置渲染优先级
                    }

                    // 设置自适应屏幕两者合用
                    webSettings.setUseWideViewPort(mUseWideViewPort); // 是否使用宽视图
                    webSettings.setLoadWithOverviewMode(mLoadWithOverviewMode); // 是否按宽度缩小内容以适合屏幕
                    if (mLayoutAlgorithm != null) { // WebSettings.LayoutAlgorithm.SINGLE_COLUMN 4.4 抛弃了
                        webSettings.setLayoutAlgorithm(mLayoutAlgorithm);
                    }

                    // 缩放操作
                    webSettings.setSupportZoom(mSupportZoom); // 是否支持缩放
                    webSettings.setBuiltInZoomControls(mBuiltInZoomControls); // 是否显示内置缩放工具, 若为 false 则该 WebView 不可缩放
                    webSettings.setDisplayZoomControls(mDisplayZoomControls); // 是否显示缩放工具

                    if (mTextZoom > 0) {
                        webSettings.setTextZoom(mTextZoom); // 文本缩放倍数
                    }
                    if (mStandardFontFamily != null) {
                        webSettings.setStandardFontFamily(mStandardFontFamily); // 设置 WebView 字体
                    }
                    if (mDefaultFontSize > 0) {
                        webSettings.setDefaultFontSize(mDefaultFontSize); // 设置 WebView 字体大小
                    }
                    if (mMinimumFontSize > 0) {
                        webSettings.setMinimumFontSize(mMinimumFontSize); // 设置 WebView 支持最小字体大小
                    }

                    // 5.0 以上默认禁止了 https 和 http 混用以下方式是开启
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        webSettings.setMixedContentMode(mMixedContentMode);
                    }

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                        webSettings.setLoadsImagesAutomatically(mLoadsImagesAutomatically); // 是否支持自动加载图片
                    }

                    // 是否支持通过 JS 打开新窗口
                    webSettings.setJavaScriptCanOpenWindowsAutomatically(mJavaScriptCanOpenWindowsAutomatically);
                    // 设置编码格式
                    if (mDefaultTextEncodingName != null) {
                        webSettings.setDefaultTextEncodingName(mDefaultTextEncodingName);
                    }
                    // 是否允许网页执行定位操作
                    webSettings.setGeolocationEnabled(mGeolocationEnabled);
                    // 设置浏览器标识 UA
                    if (mUserAgentString != null) {
                        webSettings.setUserAgentString(mUserAgentString);
                    }

                    // 是否可以访问文件
                    webSettings.setAllowFileAccess(mAllowFileAccess);
                    // 是否允许通过 file url 加载的 JS 代码读取其他的本地文件
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                        webSettings.setAllowFileAccessFromFileURLs(mAllowFileAccessFromFileURLs);
                    }
                    // 是否允许通过 file url 加载的 JS 可以访问其他的源 ( 包括 http、https 等源 )
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                        webSettings.setAllowUniversalAccessFromFileURLs(mAllowUniversalAccessFromFileURLs);
                    }
                    // 设置 WebView 缓存模式
                    if (mCacheMode > 0) {
                        // LOAD_CACHE_ONLY 不使用网络, 只读取本地缓存数据
                        // LOAD_DEFAULT ( 默认 ) 根据 cache-control 决定是否从网络上取数据
                        // LOAD_NO_CACHE 不使用缓存, 只从网络获取数据.
                        // LOAD_CACHE_ELSE_NETWORK 只要本地有, 无论是否过期或者 no-cache 都使用缓存中的数据
                        webSettings.setCacheMode(mCacheMode);
                    }

                    // 是否支持 DOM Storage
                    webSettings.setDomStorageEnabled(mDomStorageEnabled);
                    // 是否开启 Application Caches 功能
                    webSettings.setAppCacheEnabled(mAppCacheEnabled);
                    if (mAppCacheEnabled) {
                        // Application Caches 地址
                        if (mAppCachePath != null) {
                            webSettings.setAppCachePath(mAppCachePath);
                        }
                        // Application Caches 大小
                        webSettings.setAppCacheMaxSize(mAppCacheMaxSize);
                    }

                    // 是否支持数据库缓存
                    webSettings.setDatabaseEnabled(mDatabaseEnabled);
                    if (mDatabaseEnabled) {
                        // 数据库缓存路径
                        if (mDatabasePath != null) {
                            webSettings.setDatabasePath(mDatabasePath);
                        }
                    }
                }
            }

            if (mApplyListener != null) {
                mApplyListener.onApply(mWebViewAssist, this);
            }
            return this;
        }

        // ===========
        // = get/set =
        // ===========

        /**
         * 是否支持 JavaScript
         * @return {@code true} yes, {@code false} no
         */
        public boolean isJavaScriptEnabled() {
            return mJavaScriptEnabled;
        }

        /**
         * 设置是否支持 JavaScript
         * @param javaScriptEnabled {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setJavaScriptEnabled(final boolean javaScriptEnabled) {
            this.mJavaScriptEnabled = javaScriptEnabled;
            return this;
        }

        /**
         * 获取渲染优先级
         * @return 渲染优先级
         */
        public WebSettings.RenderPriority getRenderPriority() {
            return mRenderPriority;
        }

        /**
         * 设置渲染优先级
         * @param renderPriority 渲染优先级
         * @return {@link Builder}
         */
        public Builder setRenderPriority(final WebSettings.RenderPriority renderPriority) {
            this.mRenderPriority = renderPriority;
            return this;
        }

        /**
         * 是否使用宽视图
         * @return {@code true} yes, {@code false} no
         */
        public boolean isUseWideViewPort() {
            return mUseWideViewPort;
        }

        /**
         * 设置是否使用宽视图
         * <pre>
         *      是否支持 html viewport 设置了会导致字体变小
         * </pre>
         * @param useWideViewPort {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setUseWideViewPort(final boolean useWideViewPort) {
            this.mUseWideViewPort = useWideViewPort;
            return this;
        }

        /**
         * 是否按宽度缩小内容以适合屏幕
         * @return {@code true} yes, {@code false} no
         */
        public boolean isLoadWithOverviewMode() {
            return mLoadWithOverviewMode;
        }

        /**
         * 设置是否按宽度缩小内容以适合屏幕
         * @param loadWithOverviewMode {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setLoadWithOverviewMode(final boolean loadWithOverviewMode) {
            this.mLoadWithOverviewMode = loadWithOverviewMode;
            return this;
        }

        /**
         * 获取基础布局算法
         * @return 基础布局算法
         */
        public WebSettings.LayoutAlgorithm getLayoutAlgorithm() {
            return mLayoutAlgorithm;
        }

        /**
         * 设置基础布局算法
         * @param layoutAlgorithm 基础布局算法
         * @return {@link Builder}
         */
        public Builder setLayoutAlgorithm(final WebSettings.LayoutAlgorithm layoutAlgorithm) {
            this.mLayoutAlgorithm = layoutAlgorithm;
            return this;
        }

        /**
         * 是否支持缩放
         * @return {@code true} yes, {@code false} no
         */
        public boolean isSupportZoom() {
            return mSupportZoom;
        }

        /**
         * 设置是否支持缩放
         * @param supportZoom {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setSupportZoom(final boolean supportZoom) {
            this.mSupportZoom = supportZoom;
            return this;
        }

        /**
         * 是否显示内置缩放工具
         * @return {@code true} yes, {@code false} no
         */
        public boolean isBuiltInZoomControls() {
            return mBuiltInZoomControls;
        }

        /**
         * 设置是否显示内置缩放工具
         * @param builtInZoomControls {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setBuiltInZoomControls(final boolean builtInZoomControls) {
            this.mBuiltInZoomControls = builtInZoomControls;
            return this;
        }

        /**
         * 是否显示缩放工具
         * @return {@code true} yes, {@code false} no
         */
        public boolean isDisplayZoomControls() {
            return mDisplayZoomControls;
        }

        /**
         * 设置是否显示缩放工具
         * @param displayZoomControls {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setDisplayZoomControls(final boolean displayZoomControls) {
            this.mDisplayZoomControls = displayZoomControls;
            return this;
        }

        /**
         * 获取文本缩放倍数
         * @return 文本缩放倍数
         */
        public int getTextZoom() {
            return mTextZoom;
        }

        /**
         * 设置文本缩放倍数
         * @param textZoom 文本缩放倍数
         * @return {@link Builder}
         */
        public Builder setTextZoom(final int textZoom) {
            this.mTextZoom = textZoom;
            return this;
        }

        /**
         * 获取 WebView 字体
         * @return WebView 字体
         */
        public String getStandardFontFamily() {
            return mStandardFontFamily;
        }

        /**
         * 设置 WebView 字体
         * @param standardFontFamily WebView 字体
         * @return {@link Builder}
         */
        public Builder setStandardFontFamily(final String standardFontFamily) {
            this.mStandardFontFamily = standardFontFamily;
            return this;
        }

        /**
         * 获取 WebView 字体大小
         * @return WebView 字体大小
         */
        public int getDefaultFontSize() {
            return mDefaultFontSize;
        }

        /**
         * 设置 WebView 字体大小
         * @param defaultFontSize WebView 字体大小
         * @return {@link Builder}
         */
        public Builder setDefaultFontSize(final int defaultFontSize) {
            this.mDefaultFontSize = defaultFontSize;
            return this;
        }

        /**
         * 获取 WebView 支持最小字体大小
         * @return WebView 支持最小字体大小
         */
        public int getMinimumFontSize() {
            return mMinimumFontSize;
        }

        /**
         * 设置 WebView 支持最小字体大小
         * @param minimumFontSize WebView 支持最小字体大小
         * @return {@link Builder}
         */
        public Builder setMinimumFontSize(final int minimumFontSize) {
            this.mMinimumFontSize = minimumFontSize;
            return this;
        }

        /**
         * 获取混合内容模式
         * @return 混合内容模式
         */
        public int getMixedContentMode() {
            return mMixedContentMode;
        }

        /**
         * 设置混合内容模式
         * @param mixedContentMode 混合内容模式
         * @return {@link Builder}
         */
        public Builder setMixedContentMode(final int mixedContentMode) {
            this.mMixedContentMode = mixedContentMode;
            return this;
        }

        /**
         * 是否支持自动加载图片
         * @return {@code true} yes, {@code false} no
         */
        public boolean isLoadsImagesAutomatically() {
            return mLoadsImagesAutomatically;
        }

        /**
         * 设置是否支持自动加载图片
         * @param loadsImagesAutomatically {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setLoadsImagesAutomatically(final boolean loadsImagesAutomatically) {
            this.mLoadsImagesAutomatically = loadsImagesAutomatically;
            return this;
        }

        /**
         * 是否支持通过 JS 打开新窗口
         * @return {@code true} yes, {@code false} no
         */
        public boolean isJavaScriptCanOpenWindowsAutomatically() {
            return mJavaScriptCanOpenWindowsAutomatically;
        }

        /**
         * 设置是否支持通过 JS 打开新窗口
         * @param javaScriptCanOpenWindowsAutomatically {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setJavaScriptCanOpenWindowsAutomatically(final boolean javaScriptCanOpenWindowsAutomatically) {
            this.mJavaScriptCanOpenWindowsAutomatically = javaScriptCanOpenWindowsAutomatically;
            return this;
        }

        /**
         * 获取编码格式
         * @return 编码格式
         */
        public String getDefaultTextEncodingName() {
            return mDefaultTextEncodingName;
        }

        /**
         * 设置编码格式
         * @param defaultTextEncodingName 编码格式
         * @return {@link Builder}
         */
        public Builder setDefaultTextEncodingName(final String defaultTextEncodingName) {
            this.mDefaultTextEncodingName = defaultTextEncodingName;
            return this;
        }

        /**
         * 是否允许网页执行定位操作
         * @return {@code true} yes, {@code false} no
         */
        public boolean isGeolocationEnabled() {
            return mGeolocationEnabled;
        }

        /**
         * 设置是否允许网页执行定位操作
         * @param geolocationEnabled {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setGeolocationEnabled(final boolean geolocationEnabled) {
            this.mGeolocationEnabled = geolocationEnabled;
            return this;
        }

        /**
         * 获取浏览器标识 UA
         * @return 浏览器标识 UA
         */
        public String getUserAgentString() {
            return mUserAgentString;
        }

        /**
         * 设置浏览器标识 UA
         * @param userAgentString 浏览器标识 UA
         * @return {@link Builder}
         */
        public Builder setUserAgentString(final String userAgentString) {
            this.mUserAgentString = userAgentString;
            return this;
        }

        /**
         * 是否可以访问文件 ( false 不影响 assets 和 resources 资源的加载 )
         * @return {@code true} yes, {@code false} no
         */
        public boolean isAllowFileAccess() {
            return mAllowFileAccess;
        }

        /**
         * 设置是否可以访问文件 ( false 不影响 assets 和 resources 资源的加载 )
         * @param allowFileAccess {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setAllowFileAccess(final boolean allowFileAccess) {
            this.mAllowFileAccess = allowFileAccess;
            return this;
        }

        /**
         * 是否允许通过 file url 加载的 JS 代码读取其他的本地文件
         * @return {@code true} yes, {@code false} no
         */
        public boolean isAllowFileAccessFromFileURLs() {
            return mAllowFileAccessFromFileURLs;
        }

        /**
         * 设置是否允许通过 file url 加载的 JS 代码读取其他的本地文件
         * @param allowFileAccessFromFileURLs {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setAllowFileAccessFromFileURLs(final boolean allowFileAccessFromFileURLs) {
            this.mAllowFileAccessFromFileURLs = allowFileAccessFromFileURLs;
            return this;
        }

        /**
         * 是否允许通过 file url 加载的 JS 可以访问其他的源 ( 包括 http、https 等源 )
         * @return {@code true} yes, {@code false} no
         */
        public boolean isAllowUniversalAccessFromFileURLs() {
            return mAllowUniversalAccessFromFileURLs;
        }

        /**
         * 设置是否允许通过 file url 加载的 JS 可以访问其他的源 ( 包括 http、https 等源 )
         * @param allowUniversalAccessFromFileURLs {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setAllowUniversalAccessFromFileURLs(final boolean allowUniversalAccessFromFileURLs) {
            this.mAllowUniversalAccessFromFileURLs = allowUniversalAccessFromFileURLs;
            return this;
        }

        /**
         * 获取 WebView 缓存模式
         * @return WebView 缓存模式
         */
        public int getCacheMode() {
            return mCacheMode;
        }

        /**
         * 设置 WebView 缓存模式
         * @param cacheMode WebView 缓存模式
         * @return {@link Builder}
         */
        public Builder setCacheMode(final int cacheMode) {
            this.mCacheMode = cacheMode;
            return this;
        }

        /**
         * 是否支持 DOM Storage
         * @return {@code true} yes, {@code false} no
         */
        public boolean isDomStorageEnabled() {
            return mDomStorageEnabled;
        }

        /**
         * 设置是否支持 DOM Storage
         * @param domStorageEnabled {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setDomStorageEnabled(final boolean domStorageEnabled) {
            this.mDomStorageEnabled = domStorageEnabled;
            return this;
        }

        /**
         * 是否开启 Application Caches 功能
         * @return {@code true} yes, {@code false} no
         */
        public boolean isAppCacheEnabled() {
            return mAppCacheEnabled;
        }

        /**
         * 设置是否开启 Application Caches 功能
         * @param appCacheEnabled {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setAppCacheEnabled(final boolean appCacheEnabled) {
            this.mAppCacheEnabled = appCacheEnabled;
            return this;
        }

        /**
         * 获取 Application Caches 地址
         * @return Application Caches 地址
         */
        public String getAppCachePath() {
            return mAppCachePath;
        }

        /**
         * 设置 Application Caches 地址
         * @param appCachePath Application Caches 地址
         * @return {@link Builder}
         */
        public Builder setAppCachePath(final String appCachePath) {
            this.mAppCachePath = appCachePath;
            return this;
        }

        /**
         * 获取 Application Caches 大小
         * @return Application Caches 大小
         */
        public long getAppCacheMaxSize() {
            return mAppCacheMaxSize;
        }

        /**
         * 设置 Application Caches 大小
         * @param appCacheMaxSize Application Caches 大小
         * @return {@link Builder}
         */
        public Builder setAppCacheMaxSize(final long appCacheMaxSize) {
            this.mAppCacheMaxSize = appCacheMaxSize;
            return this;
        }

        /**
         * 是否支持数据库缓存
         * @return {@code true} yes, {@code false} no
         */
        public boolean isDatabaseEnabled() {
            return mDatabaseEnabled;
        }

        /**
         * 设置是否支持数据库缓存
         * @param databaseEnabled {@code true} yes, {@code false} no
         * @return {@link Builder}
         */
        public Builder setDatabaseEnabled(final boolean databaseEnabled) {
            this.mDatabaseEnabled = databaseEnabled;
            return this;
        }

        /**
         * 获取数据库缓存路径
         * @return 数据库缓存路径
         */
        public String getDatabasePath() {
            return mDatabasePath;
        }

        /**
         * 设置数据库缓存路径
         * @param databasePath 数据库缓存路径
         * @return {@link Builder}
         */
        public Builder setDatabasePath(final String databasePath) {
            this.mDatabasePath = databasePath;
            return this;
        }
    }
}
Android Webview 详解 一个基于webkit引擎、展现web页面的控件Android 4.4前:Android Webview在低版本 & 高版本采用了不同的webkit版本的内核Android 4.4后:直接使用了Chrome内核Android去调用JS的代码JS去调用Android的代码二者沟通的桥梁是WebView通过WebView的loadUrl()通过WebView的evaluateJavascript()通过WebView的addJavascriptInterface()进行对象映射。 阅读详情

相关推荐

Android开发之——Android和WebView相互调用,干货

**@description:android调用js无参函数*//**@description:android调用js带参函数*//**@description:js调用android无参函数*//**@description:js调用android带参函数*//**@description:android调用js无参函数*//**@description:android调用js带参函数*//**@description:js调用android无参函数。

m0_60388338的博客 947

android webView工具类

package com.youche.cango.webview; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.webkit.WebChromeClient; import android.webkit.WebView; imp

刘胡来 1313

二叉树随机漫步

元旦快乐! 学习到中本聪bitcoin的文章的calculation部分的时候,出现了binomial random walk,不是很明白什么是random walk。发现这个文章写的很好:https://blog.youkuaiyun.com/fireguard/article/details/16111603 随机漫步,也叫随机游走,最早是物理学中做"布朗运动"的微观粒子的运动形态来形成的一个模型,布朗运...

gjq5464的博客 1737

Android_UI:WebView

WebView 根据url加载数据 相关的类: WebView WebViewClient:很多重写方法 WebSettings:设置字体大小 Demo: 先显示进度条,当webview数据加载完成后,再把进度条隐藏。 注意加网络访问权限。 布局:activity_main.xml<RelativeLayout xmlns:android="http://schemas.android

Java技术博客,不再更新Android内容 1191

Cobalt Strike4.0安装包(内附中文版)

1.什么是 Cobalt Strike Cobalt Strike 是一个为对手模拟和红队行动而设计的平台,主要用于执行有目标的攻击和模拟高级威胁 者的后渗透行动。 Cobalt Strike已经不再使用MSF而是作为单独的平台使用,它分为客户端与服务端,服务端是一个,客户端可以有多个,可被团队进行分布式协团操作。集成了端口转发、扫描多模式端口Listener、Windows exe程序生成、W...

梦之序章的博客 2万+

新出的智谱GLM-4.7很牛逼?

Zhipu AI(智谱)最近发布的 GLM-4.7 再次刷新了开源大模型的天花板。作为一款约 400B 参数规模的 MoE 模型,它不仅在传统的代码与推理任务上超越了 DeepSeek-V3.2 和 Kimi-K2 等强力对手,更通过**“保留思考(Preserved Thinking)”和“交错思考(Interleaved Thinking)”**等架构级创新,重新定义了 Agentic Workflow 的设计范式。

kakaZhui的博客 2394

Android WebView开发(一):基础应用

一、WebView的基础配置 WebSettings ws = getSettings(); ws.setBuiltInZoomControls(true);// 隐藏缩放按钮 ws.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);// 排版适应屏幕 ws.setUseWideViewPort(true);// 可任意比例缩放 ws.setLoadWithOverviewMode(true);// setUseWideViewPort方法设

红日 3244

ADC选型实战:从参数指标到精准应用的工程指南

本文深入解析ADC(模数转换器)选型的关键参数与实战技巧,涵盖分辨率、转换误差等核心指标,并提供高精度温度测量、高速数据采集等五大应用场景的选型指南。通过实际案例和代码示例,详细讲解校准方法、功耗优化策略及常见问题排查,帮助工程师实现从参数指标到精准应用的工程实践。

weixin_29166013的博客 326

Application Cache

一、什么是应用程序缓存 html5引入了应用程序缓存,这意味着web应用可进行混村,并苛杂IMEI有因特网连接时进行访问  二、三大优势 1、离线浏览:用户可在应用离线时使用她们 2、速度:已缓存资源加载得更快 3、减少服务器负载:浏览器将只从服务器下载更新过或更改过的资源 离线缓存步骤: 1、配置app服务器:1)引入express资源  2)使用express  3)配置

奋斗的小青年 412

STM32F4与LAN8720硬件连接避坑指南:从原理图到RMII信号完整性的实战解析

本文深入解析了STM32F4与LAN8720以太网连接的硬件设计要点与常见陷阱。重点剖析了电源上电时序、复位电路设计、RMII接口配置等关键环节,并提供了从原理图设计到PCB布局、信号完整性调试的完整实战指南,帮助硬件工程师规避设计风险,确保以太网通信的长期稳定运行。

weixin_29189003的博客 211

微信小程序 | 小程序开发

事实上,目前小程序在我们生活中已经随处可见(特别是这次疫情的推动,不管是什么岗位、什么年龄阶段的人,到哪都需要打开健康码)WePY是由腾讯开源的,一款让小程序支持组件化开发的框架,通过预编译的手段让开发者可以选择自己喜欢的开发风格去开发小程序。Mpvue是一个使用Vue开发小程序的前端框架,也是 支持 微信小程序、百度智能小程序,头条小程序 和 支付宝小程序;微信小程序、支付宝小程序、淘宝小程序、抖音小程序、头条小程序、QQ小程序、美团小程序等。,其他平台的小程序往往是平台本身的一些公司或者顺手开发的。

CoderHing的博客~ 1万+

离线存储之Application Cache

1、什么是应用缓存(Application Cache) HTML5引入了应用程序缓存(又叫离线缓存),这意味着web应用可进行缓存,并可在没有网络连接时进行访问。 2、应用缓存的优势 1)离线浏览-用户可以在离线状态下浏览网站内容 2)速度-因为数据被存储在本地,所以速度会更快 3)减少服务器负载-浏览器只会下载在服务器上发生改...

weixin_46513664的博客 551

车载软件架构 —— AUTOSAR Vector SIP包(三)

### 上一篇文章中介绍了AUTOSAR基础软件供应商Vector公司的开发工具链,本文将继续介绍Vector公司的AUTOSAR产品。 ### -> 1、Vector SIP包中的StartApplication ### -> 2、StartApplication如何开始使用

Soly_kun的博客 828

android创建webview,Android Webview总结

这些都是曾经收集到的一些关于Webview的知识,有些工作中用到了,有些暂时还没有用到,这次统一整理下,希望对自己,对大家有所帮助。另外,欢迎大家补充(当然,有错也要指正呀,不胜感激),如果可以的话,我会 更新到本帖中。一.权限二.创建Webview对象WebView webview = new WebView(this);三.加载网页的方式loadData(String data, String...

weixin_29535577的博客 1180

【Go语言实战】(3) Gin + Gorm 简单备忘录 | 含接口文档

Go语言实战:TodoList 备忘录

面向生活编程 6139

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Android WebView 总结,Android Webview总结

这些都是曾经收集到的一些关于Webview的知识,有些工作中用到了,有些暂时还没有用到,这次统一整理下,希望对自己,对大家有所帮助。另外,欢迎大家补充(当然,有错也要指正呀,不胜感激),如果可以的话,我会 更新到本帖中。一.权限二.创建Webview对象WebView webview = new WebView(this);三.加载网页的方式loadData(String data, String...

weixin_35808698的博客 223

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

[Android基础] WebView

[ Demo下载 ]资源 Web Apps WebView Android4.4 webview实现分析 Android WebView使用深入浅出 深入讲解WebView(上) - 互调,缓存,异常处理等 深入讲解WebView(下) - session,cookie等 Android WebView Memory Leak WebView内存泄漏 ==! 这个我用leakcanary没检测出来

冰川孤辰的专栏 4560

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Android WebView控件

前言 WebView主要用来显示网页,采用Webkit内核。 1. 访问网页 (1) 添加权限 &amp;amp;amp;lt;uses-permission android:name=&amp;amp;quot;android.permission.INTERNET&amp;amp;quot;/&amp;amp;amp;gt; (2) 布局文件 &amp;amp;amp;lt;WebView android:id=&amp;amp;

假装你是大灰狼的专栏 572

Android webview 打开相册选择图片并上传到服务器

package cn.hellomrhuang.webapp.webview;import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.Dialog

像风一样自由 3322

android中在webview里操作文件

首先如果仅仅是想下载文件的话,这里介绍一个比较简单的方法 webView.setDownloadListener(new DownloadListener() {        public void onDownloadStart(String url, String userAgent,                String contentDisposition, String m

chen052210123的专栏 3122

Android中WebViewClient与WebChromClient两个类区别

WebViewClient类与WebChromClient两个类在android开发的过程中,主要是在使用WebView这个组件的时候,可能会使用到。那么这两个类到底有什么不同之处呢? WebViewClient 这个类主要帮助WebView处理各种通知、请求时间的,比如: onLoadResource onPageStart onPageFinis

runHome的博客 699

Android开发之WebView的使用

Android开发之WebView的使用 http://note.youdao.com/share/?id=d4e2e028fc96f3448442c5e490bc6324&type=note Android开发之WebView的使用 Webkit网页渲染流程: http://blog.youkuaiyun.com/milado_nju/article/details

shenggaofei的博客 666

WebView详解

此外,android还为我们提供了一些类来辅助我们的webview的使用。 WebViewClient: 。WebViewClient就是帮助WebView处理各种通知、请求事件的,具体来说包括:   onLoadResource:通知webView加载url指定的资源时触发  onPageStart:页面开始加载时触发  onPageFinish:页面加载完毕时触发  onRe

qq_25138543的博客 542

安卓WebView的使用

WebView是Android中的原生UI控件,主要用于在app应用中方便地访问远程网页或本地html资源。同时,WebView也在Android中充当Java代码和JS代码之间交互的桥梁。实际上,也可以将WebView看做一个功能最小化的浏览器。

qq_40364278的博客 1万+

Android安卓自带的 WebView 浏览器内核更新

Android 安卓自带 WebView 浏览器内核更新教程

aken 8万+

【Android WebView】WebView基础

web的error 页面比较丑,我们可以在加载失败时,展示安卓自定义的错误展示页。4、动画、银屏、视频 合适加载释放动画、银屏、视频 加载会造成cpu、电量消耗可在activity、 fragment的onResume、onStop进行开关控制。

dev晴天的博客 6991
上一篇: Android Fastjson 工具类
下一篇: Android ZXing 二维码工具类
「已注销」
博客等级 码龄11年 14粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值