Android之WebView/WebViewClient/WebChromeClient 使用样例 【二】

老早之前就想总结下Webview相关的知识点了,因为互联网大潮中,很多APP都会使用到Webview,像那些不计其数的电商APP,无一例外的使用Webview;或者一些非电商APP中的像广告页面,注册协议页面都会用到;最后因为一些事情拖到现在才做,感觉事情真不能拖,越往后推越做不了,罪过罪过。

怎么总结Webview呢

1.简单介绍

2.WebView/WebViewClient/WebChromeClient api介绍

3.简单使用

4.JS调用Android本地

5.Android调用JS方法

6.缓存处理及性能优化

7.webview使用注意点


webview系列文章

Android之WebView/WebViewClient/WebChromeClient简介 API详述 【一】

Android之WebView/WebViewClient/WebChromeClient 使用样例 【二】

Android之WebView Android调用JS方法 JS调用Android方法 【三】

Android之WebView 缓存处理 性能优化【四】

Android之WebView 使用注意点 JS注入漏洞问题 内存优化【五】


3.简单使用

在xml中添加

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

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

</LinearLayout>

然后在代码中

private void initWebview() {
        /**
         * webview相关设置的管理类,就像你家的大管家一样
         */
        mSetting = mWebview.getSettings();
        /**
         * 处于安全性考虑,android默认不支持js
         * 如果页面有js操作,一定要设置
         */
        mSetting.setJavaScriptEnabled(true);
        //设置允许js弹框
        mSetting.setJavaScriptCanOpenWindowsAutomatically(true);

        //在webview中启用或禁用内容URL访问,默认启用,可以通过Content provider去访问资源
        mSetting.setAllowContentAccess(true);
        //在webview中禁用或启用文件访问,默认启用,这里针对的是手机内存的文件,assets和res目录下的不受影响
        mSetting.setAllowFileAccess(true);

        //设置缓存模式
        mSetting.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        //设置缓存路径
        //Android 私有缓存存储,如果你不调用setAppCachePath方法,WebView将不会产生这个目录。
        mSetting.setAppCachePath(MyApplication.getInstance().getCacheDir().getAbsolutePath());
        //设置是否启用缓存,不过需要先设置好缓存路径,默认false
        mSetting.setAppCacheEnabled(true);

        //设置是否阻止加载网络图片 默认false
//        mSetting.setBlockNetworkImage(false);
        //设置是否自动加载图片 默认true
//        mSetting.setLoadsImagesAutomatically(true);
        //设置是否阻止加载所有网络资源 默认false
//        mSetting.setBlockNetworkLoads(false);

        //设置webview是否应使用其内置的缩放机制
        mSetting.setBuiltInZoomControls(true);
        //设置webview在使用内置缩放控件的时候是否显示屏幕缩放控件
        mSetting.setDisplayZoomControls(false);
        //设置是否启用DOM存储
        mSetting.setDomStorageEnabled(true);
        //设置webview是否能以概貌模式加载页面,即当页面内容宽度大于webview控件的宽度时
        mSetting.setLoadWithOverviewMode(true);
        // 设置 UserAgent 属性
        mSetting.setUserAgentString("");

        mWebViewClient = new MyWebViewClient();
        mWebview.setWebViewClient(mWebViewClient);
//        mChromeClient = new MyWebChromeClient();
//        mWebview.setWebChromeClient(mChromeClient);

        mWebview.setOnKeyListener(this);

        //加载网络页面
        mWebview.loadUrl("https://www.baidu.com");
        //加载assets文件夹下的html
//        mWebview.loadUrl("file:///android_asset/html/index.html");
        //加载手机本地的html页面
//        mWebview.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        //点击返回键的时候如果有上一页就返回上一页,避免直接退出
        if(keyCode == KeyEvent.KEYCODE_BACK && mWebview.canGoBack()){
            mWebview.goBack();
            return true;
        }
        return false;
    }
public class MyWebChromeClient extends WebChromeClient{

    private String TAG = "MyWebChromeClient";

    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);
        Log.e(TAG,"onProgressChanged newProgress="+newProgress);
    }


    @Override
    public void onReceivedTitle(WebView view, String title) {
        super.onReceivedTitle(view, title);
        Log.e(TAG,"onReceivedTitle title="+title);
    }

    @Override
    public void onReceivedIcon(WebView view, Bitmap icon) {
        super.onReceivedIcon(view, icon);
        Log.e(TAG,"onReceivedTitle icon="+icon.getByteCount());
    }

    /**
     * htmlzhong <video/> 控件在未播放时,会展示成一张图片,html中可以通过poster属性来指定
     * 如果没有指定poster属性,我们可以通过这个方法提供一个默认的海报图
     * @return
     */
    @Override
    public Bitmap getDefaultVideoPoster() {
        Log.e(TAG,"getDefaultVideoPoster");
        return super.getDefaultVideoPoster();
    }

    /**
     * 当全屏的视频正在缓冲时,通过此方法返回一个view
     * @return
     */
    @Override
    public View getVideoLoadingProgressView() {
        Log.e(TAG,"getVideoLoadingProgressView");
        return super.getVideoLoadingProgressView();
    }

    @Override
    public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
        Log.e(TAG,"onCreateWindow");
        return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg);
    }

    @Override
    public void onCloseWindow(WebView window) {
        super.onCloseWindow(window);
        Log.e(TAG,"onCloseWindow");
    }

    /**
     *  接收js控制台消息
     * @param consoleMessage
     * @return
     */
    @Override
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
        Log.e(TAG,"onConsoleMessage");
        return super.onConsoleMessage(consoleMessage);
    }

    /**
     * 网页内容请求定位
     * @param origin
     * @param callback
     */
    @Override
    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        super.onGeolocationPermissionsShowPrompt(origin, callback);
        Log.e(TAG,"onGeolocationPermissionsShowPrompt");
    }

    /**
     * 请求定位取消了
     */
    @Override
    public void onGeolocationPermissionsHidePrompt() {
        super.onGeolocationPermissionsHidePrompt();
        Log.e(TAG,"onGeolocationPermissionsHidePrompt");
    }

    /**
     * 当前页面进入了全屏模式,此时应用必须显示一个包含网页内容的自定义view
     * @param view
     * @param callback
     */
    @Override
    public void onShowCustomView(View view, CustomViewCallback callback) {
        super.onShowCustomView(view, callback);
        Log.e(TAG,"onShowCustomView");
    }

    /**
     * 当前页面已退出全屏模式,但应用程序必须隐藏自定义view
     */
    @Override
    public void onHideCustomView() {
        super.onHideCustomView();
        Log.e(TAG,"onHideCustomView");
    }

    /**
     * JS通知android显示一个警告对话框
     * @param view
     * @param url
     * @param message
     * @param result
     * @return 返回true才有效 下面方法同理
     */
    @Override
    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
        Log.e(TAG,"onJsAlert");
        if (!TextUtils.isEmpty(message)) {
            //模拟显示一个对话框
            Toast.makeText(MyApplication.getInstance(),message,Toast.LENGTH_SHORT).show();
            AlertDialog.Builder build = new AlertDialog.Builder(MyApplication.getInstance());
            build.setTitle(message);
            build.setMessage(message);
            build.setCancelable(true);
            build.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    result.confirm();
                }
            });
            build.create().show();
        }
        result.cancel();//调用这个方法,否则可能无效
        return true;
    }

    /**
     * JS通知android显示一个确认对话框
     * @param view
     * @param url
     * @param message
     * @param result
     * @return
     */
    @Override
    public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
        Log.e(TAG,"onJsConfirm");
        return super.onJsConfirm(view, url, message, result);
    }

    /**
     * JS通知android显示一个对话框让用户选择是否离开当前页面
     * @param view
     * @param url
     * @param message
     * @param result
     * @return
     */
    @Override
    public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) {
        Log.e(TAG,"onJsBeforeUnload");
        return super.onJsBeforeUnload(view, url, message, result);
    }

    /**
     * JS通知android显示一个提示信息
     * @param view
     * @param url
     * @param message
     * @param defaultValue
     * @param result
     * @return
     */
    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
        Log.e(TAG,"onJsPrompt");
        return super.onJsPrompt(view, url, message, defaultValue, result);
    }


    /**
     *当页面内容请求本地资源需要请求权限时回调,前提是该权限未被授权或取消
     * @param request
     */
    @Override
    public void onPermissionRequest(PermissionRequest request) {
        super.onPermissionRequest(request);
        Log.e(TAG,"onPermissionRequest");
    }

    /**
     * 申请权限被取消
     * @param request
     */
    @Override
    public void onPermissionRequestCanceled(PermissionRequest request) {
        super.onPermissionRequestCanceled(request);
        Log.e(TAG,"onPermissionRequestCanceled");
    }

    /**
     * 为 html <input type="file"> 显示文件选择器,返回false使用默认处理
     * @param webView
     * @param filePathCallback
     * @param fileChooserParams
     * @return
     */
    @Override
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        Log.e(TAG,"onShowFileChooser");
        return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
    }
}

/**
 * @Description TODO(处理webview的通知和请求)
 * @author cxy
 * @Date 2018/6/11 15:10
 */
public class MyWebViewClient extends WebViewClient {

    private String TAG = "MyWebViewClient";

    /**
     * 设置不用系统浏览器打开,直接显示在当前Webview
     * 在点击请求的是连接是才会调用
     * 重写此方法返回true表明点击网页里面的链接还是在当前的webView里跳转,不跳到浏览器里边
     * @param view
     * @param request
     * @return
     */
    /*@Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        Log.i(TAG,"shouldOverrideUrlLoading Title="+view.getTitle()+""+request.getUrl().toString());
        return true;
    }*/

    /**
     * 这个方法在api24即7.0以后废弃了,上面那个方法在24后添加
     * @param view
     * @param url
     * @return
     */
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        Log.i(TAG,"shouldOverrideUrlLoading Title="+view.getTitle()+",url="+url);
        return true;
    }

    /**
     * 页面开始加载时会回调 一次Frame加载对应一次回调
     * 可以在这里显示加载动画,避免长时间的空白画面
     * @param view
     * @param url
     * @param favicon
     */
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        Log.i(TAG,"onPageStarted url="+url);
    }

    /**
     * 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
     * @param view
     * @param url
     */
    @Override
    public void onLoadResource(WebView view, String url) {
        super.onLoadResource(view, url);
//        Log.i(TAG,"onLoadResource url="+url);
    }

    /**
     * 页面加载结束会回调
     * @param view
     * @param url
     */
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        Log.i(TAG,"onPageFinished url="+url);
    }


    /**
     * 从服务器收到HTTP错误,错误的状态码大于等于400,任何资源的错误都会回调这个方法
     * 比如遇到了404,我们可以设置显示一个本地的错误提示页面,要不然显示404页面对用户不友好
     * @param view
     * @param request
     * @param errorResponse
     */
    @Override
    public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
        super.onReceivedHttpError(view, request, errorResponse);
        Log.i(TAG,"onReceivedHttpError errorResponse="+errorResponse.getStatusCode());
    }

    /**
     * 加载网页时发生ssl错误
     * webview默认不处理https请求
     * 重写此方法可以让webView处理https请求
     * @param view
     * @param handler
     * @param error
     */
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        super.onReceivedSslError(view, handler, error);
        Log.i(TAG,"onReceivedSslError error="+error.getPrimaryError());
        //表示等待正式响应 该决定会用于以后来响应SSL错误
        handler.proceed();
        //表示挂起连接,为默认方式
//      handler.cancel();
    }

    /**
     * 处理按键事件
     * 系统按键或者shouldoverridekeyevent返回true 不回调此方法
     * @param view
     * @param event
     */
    @Override
    public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
        super.onUnhandledKeyEvent(view, event);
        Log.i(TAG,"onUnhandledKeyEvent event="+event.getKeyCode());
    }

    /**
     * 重写此方法才能够处理在浏览器中的按键事件
     * 给应用一个机会处理按键事件,如果返回true,webview不处理该事件,
     * 否则webview会一直处理,默认返回false
     * @param view
     * @param event
     * @return
     */
    @Override
    public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
        Log.i(TAG,"shouldOverrideKeyEvent event="+event.getKeyCode());
        return super.shouldOverrideKeyEvent(view,event);
    }

    /**
     * WebView 可以拦截某一次的 request 来返回我们自己加载的数据,这个方法在后面缓存会有很大作用。
     *
     * @param view    WebView
     * @param request 当前产生 request 请求
     * @return WebResourceResponse
     */
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {

        return super.shouldInterceptRequest(view, request);
    }
}


静待更新

后续篇章请前往Android之WebView/WebViewClient/WebChromeClient使用解析及Android与JS相互调用 【三】

猜你喜欢

转载自blog.csdn.net/qq_30993595/article/details/80647465