WebView入门(二)——抽取WebView基类

抽取一个简单的WebView基类

在安卓开发过程中经常需要接入H5页面,但每次接入都重新写一个WebView是很不方便的,所以为了减少工作量,特抽取一个WebView基类,将所有的公共操作均放入基类中执行。

1 抽取WebView基类

1.1 设置WebView属性

WebSettings用来管理WebView的状态配置,下面列出了常用的几种设置

 WebSettings webSettings = mWebView.getSettings();
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
     webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); // 允许加载混合网路协议内容
 }
 webSettings.setLoadWithOverviewMode(true);  // 适应屏幕
 webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
 webSettings.setJavaScriptEnabled(true); // 允许使用javascript
 webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);  // 设置缓存模式
 webSettings.setDomStorageEnabled(true);  // 开启DOM缓存
 webSettings.setJavaScriptCanOpenWindowsAutomatically(true);  // 允许加载新窗口
 webSettings.setAllowFileAccess(true);  // 允许访问文件数据
1.2 设置UserAgent

UserAgent即用户代理,简称UA,是http协议的一部分,声明了浏览器用于http请求的用户代理头的值,例如:Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1 。通过这个标识,前端可以统计访问H5的具体是哪种设备。
在部分情况下,多个APP共同使用一个前端页面,前端需要区分打开此页面的具体是哪个APP,这个时候就需要客户端同学对UA进行修改,在UA末尾添加和前端约定好的字符串来区分。

webSettings.setUserAgentString(webSettings.getUserAgentString() + getCustomUserAgentString());  // 设置user-agent

定义一个抽象方法,在继承WebView基类的activity中实现此方法,从而达到修改UA的目的。

/**
 * 额外添加的userAgent
*/
abstract String getCustomUserAgentString();
1.3 设置native与js交互相关的类及别名

对接的H5页面不同,js的别名和方法也可能不同,所以交互部分的代码不在基类中展示,只提供抽象方法,具体实现由继承基类的activity自己实现。

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
     if (null != getInterfaceObject() && null != getInterfaceName())
         mWebView.addJavascriptInterface(getInterfaceObject(), getInterfaceName());
}

抽象方法如下:

 /**
  * 管理native与js交互代码的类
  */
 abstract Object getInterfaceObject();

 /**
  * js调用native时的别名
  */
 abstract String getInterfaceName();
1.4 加载url
 mWebView.loadUrl(getUrl());  // 加载url

抽象方法如下:

 /**
  * 需加载的url
  */
 abstract String getUrl();
1.5 重写WebChromeClient

WebChromeClient是WebView中用来处理Javascript的对话框、图标、标题等。下边只罗列了WebChromeClient中的部分方法,需要重写的时候可结合实际情况实现。

    /**
     * 重写WebChromeClient--处理js的对话框、图标、title、加载进度等
     */
     private WebChromeClient getWebChromeClient() {
        return new WebChromeClient() {
            @Override  // 接收文档标题
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
            }

            @Override  // 显示Alert对话框
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }

            @Override  // 显示confirm对话框
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                return super.onJsConfirm(view, url, message, result);
            }

            @Override  // 显示prompt对话框
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }

            @Override  // 显示文件选择器
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
            }
        };

    }
1.6 重写WebViewClient

WebViewClient处理各种通知、请求事件

    /**
     * 重写WebViewClient--处理各种通知、请求事件
     */
    private WebViewClient getWebViewClient() {
        return new WebViewClient(){

            @Override  // url开始加载
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            @Override  // 废弃于API23,加载资源时出错
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                super.onReceivedError(view, errorCode, description, failingUrl);
            }

            @TargetApi(Build.VERSION_CODES.M)
            @Override  // 在API23添加,加载资源时出错
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                super.onReceivedError(view, request, error);
            }

            @Override  // 加载资源时出现http错误
            public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
                super.onReceivedHttpError(view, request, errorResponse);
            }

            @Override  // url加载完成
            public void onPageFinished(WebView view, String url) {
                mOtherActionListener.otherAction(url);
                super.onPageFinished(view, url);
            }

            @Override  // 在API24被废弃,拦截页面加载,返回true表示拦截并处理点击事件,返回false则为超链接会在当前webview中加载
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return super.shouldOverrideUrlLoading(view, url);
            }

            @TargetApi(Build.VERSION_CODES.N)
            @Override  // 在API24添加,拦截页面加载,返回true表示拦截并处理点击事件,返回false则为超链接会在当前webview中加载
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return super.shouldOverrideUrlLoading(view, request);
            }
        };
    }
1.7 其他额外操作

在继承此基类的子类中,还可能会有其他不同的额外操作需要执行,比如:url加载完成后弹出toast提示等,我们采用listener来监听

   private OtherActionListener mOtherActionListener = null;
   /**
     * 其他额外操作用listener来实现
     */
    public void setOtherActionListener(OtherActionListener otherActionListener) {
        this.mOtherActionListener = otherActionListener;
    }

    interface OtherActionListener {
        void otherAction(String str);
    }

在需要加载完url后弹出toast提示的子类中实现otherAction方法

 @Override
    public void otherAction(String str) {
        Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
    }

2 详细源码

2.1 layout文件
 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/base_web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>
2.2 BaseWebViewActivity基类
/**
 * WebView基类
 */
public abstract class BaseWebViewActivity extends AppCompatActivity {

    private WebView mWebView = null;
    private OtherActionListener mOtherActionListener = null;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base_webview);

        mWebView = (WebView) findViewById(R.id.base_web_view);

        initWebSettings();
        mWebView.loadUrl(getUrl());  // 加载url
        mWebView.setWebChromeClient(getWebChromeClient());
        mWebView.setWebViewClient(getWebViewClient());
    }

    /**
     * 设置WebView属性
     */
    @SuppressLint({"SetJavaScriptEnabled", "JavascriptInterface", "AddJavascriptInterface"})
    private void initWebSettings() {
        WebSettings webSettings = mWebView.getSettings();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); // 允许加载混合网路协议内容
        }
        webSettings.setLoadWithOverviewMode(true);  // 适应屏幕
        webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
        webSettings.setJavaScriptEnabled(true); // 允许使用javascript
        webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);  // 设置缓存模式
        webSettings.setDomStorageEnabled(true);  // 开启DOM缓存
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);  // 允许加载新窗口
        webSettings.setAllowFileAccess(true);  // 允许访问文件数据

        webSettings.setUserAgentString(webSettings.getUserAgentString() + getCustomUserAgentString());  // 设置user-agent

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
            if (null != getInterfaceObject() && null != getInterfaceName())
                mWebView.addJavascriptInterface(getInterfaceObject(), getInterfaceName());
        }
    }

    /**
     * 额外添加的userAgent
     */
    abstract String getCustomUserAgentString();

    /**
     * 管理native与js交互代码的类
     */
    abstract Object getInterfaceObject();

    /**
     * js调用native时的别名
     */
    abstract String getInterfaceName();

    /**
     * 需加载的url
     */
    abstract String getUrl();

    /**
     * 重写WebChromeClient--处理js的对话框、图标、title、加载进度等
     */
    private WebChromeClient getWebChromeClient() {
        return new WebChromeClient() {
            @Override  // 接收文档标题
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
            }

            @Override  // 显示Alert对话框
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }

            @Override  // 显示confirm对话框
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                return super.onJsConfirm(view, url, message, result);
            }

            @Override  // 显示prompt对话框
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }

            @Override  // 显示文件选择器
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
            }
        };

    }

    /**
     * 重写WebViewClient--处理各种通知、请求事件
     */
    private WebViewClient getWebViewClient() {
        return new WebViewClient(){

            @Override  // url开始加载
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            @Override  // 废弃于API23,加载资源时出错
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                super.onReceivedError(view, errorCode, description, failingUrl);
            }

            @TargetApi(Build.VERSION_CODES.M)
            @Override  // 在API23添加,加载资源时出错
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                super.onReceivedError(view, request, error);
            }

            @Override  // 加载资源时出现http错误
            public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
                super.onReceivedHttpError(view, request, errorResponse);
            }

            @Override  // url加载完成
            public void onPageFinished(WebView view, String url) {
                mOtherActionListener.otherAction(url);
                super.onPageFinished(view, url);
            }

            @Override  // 在API24被废弃,拦截页面加载,返回true表示拦截并处理点击事件,返回false则为超链接会在当前webview中加载
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return super.shouldOverrideUrlLoading(view, url);
            }

            @TargetApi(Build.VERSION_CODES.N)
            @Override  // 在API24添加,拦截页面加载,返回true表示拦截并处理点击事件,返回false则为超链接会在当前webview中加载
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return super.shouldOverrideUrlLoading(view, request);
            }
        };
    }

    /**
     * 其他额外操作用listener来实现
     */
    public void setOtherActionListener(OtherActionListener otherActionListener) {
        this.mOtherActionListener = otherActionListener;
    }

    interface OtherActionListener {
        void otherAction(String str);
    }
}
2.3 继承此基类的activity
public class MainActivity extends BaseWebViewActivity implements BaseWebViewActivity.OtherActionListener {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setOtherActionListener(this);
    }

    @Override
    String getCustomUserAgentString() {
        return "";
    }

    @Override
    Object getInterfaceObject() {
        return new JsInterface();
    }

    @Override
    String getInterfaceName() {
        return "bridge";
    }

    @Override
    String getUrl() {
        return "file:///android_asset/test1.html";
    }

    @Override
    public void otherAction(String str) {
        Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
    }

    /**
     * js调用java
     */
    public class JsInterface {
        @JavascriptInterface
        public void helloNative(String str) { // 定义js需要调用的方法
            Toast.makeText(MainActivity.this, str, Toast.LENGTH_LONG).show();
        }
    }
}
2.4 html文件
<html>
<script type="text/javascript">
    function callNative() {
        window.bridge.helloNative("js调用Java成功!");
    }
</script>
<button onclick="javascript:callNative();">js调用java</button>
</html>

3 demo下载

可在这里下载抽取WebView基类的demo

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值