Android开发之WebView详细总结

转载请注明出处:http://blog.csdn.net/li0978/article/details/52792162

前言

WebView是android开发中专门用来加载网页的一种控件,它采用WebKit渲染引擎来显示网页包括控制网页的前进、后退、放大、缩小、执行文本、搜索等功能。WebKit是一种让网页浏览器绘制网页的排版引擎,被用于Apple Safari,其分支也用于基于Chromuim的网页浏览器,详细了解可移步于https://zh.wikipedia.org/zh/WebKit。WebView在开发项目中使用的频率非常高,尤其是H5的发展,开发模式也由原生开发逐步被混合开发所替代。

注册

WebView使用时一般情况下要远程加载,必须在AndroidManifest文件中注册网络权限:

<uses-permission android:name="android.permission.INTERNET" />

如果还要涉及到定位,还要注册定位权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

加载方式

//加载一个网页
webView.loadUrl(“http://www.google.com/“);
//加载项目中的一个html页面
webView.loadUrl(“file:///android_asset/test.html”);
//加载手机本地的一个html页面的方法
webView.loadUrl(“content://com.android.htmlfileprovider/sdcard/test.html”);
//加载一段Html代码
loadData(String data, String mimeType, String encoding);
loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl);
例:webView.loadDataWithBaseURL(null, htmlContent, “text/html”, “UTF-8”,null);
区别:loadDataWithBaseURL()比loadData()多两个参数,可以指定HTML代码片段中相关资源的相对根路径,也可以指定历史Url。两个方法的其余三个参数相同。但是loadData()中的html data中不能包含’#’, ‘%’, ‘\’, ‘?’四中特殊字符,使用时我们需要用UrlEncoder编码为%23, %25, %27, %3f 。

WebSettings

WebSettings类主要针对webview做一些相关的设置,包括自适应屏幕、缩放设置、js脚本控制、网页数据缓存等。

WebSettings webSettings = webView.getSettings();
// 设置自适应屏幕
webSettings.setUseWideViewPort(true);           //设置成webview推荐使用的窗口,可任意比例缩放
webSettings.setLoadWithOverviewMode(true);      //设置成webview加载的页面大小的模式,
// 设置缩放网页
webSettings.setSupportZoom(true);               //是否支持屏幕双击缩放,但是下边的是前提
webSettings.setBuiltInZoomControls(true);       //是否支持内置按钮缩放和手势“捏”缩放,如果设为false则webview不支持缩放功能
webSettings.setDisplayZoomControls(false);      //是否隐藏原生的缩放控件
// 设置可以执行Javascript脚本
webSettings.setJavaScriptEnabled(true);
// 设置缓存网页数据
webSettings.setDomStorageEnabled(true);         //开启 DOM storage API 功能
webSettings.setDatabaseEnabled(true);           //开启 database storage API 功能
webSettings.setAppCacheEnabled(true);           //开启 Application Caches 功能
// 设置支持多窗口,要复写 WebChromeClient的onCreateWindow方法
webSettings.setSupportMultipleWindows(true);    //支持多窗口
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);  //支持js打开新窗口
// 支持自动加载图片
webSettings.setLoadsImagesAutomatically(true);
// 设置编码格式
webSettings.setDefaultTextEncodingName("utf-8");

缓存设置

webview中的缓存模式有四种:

  • LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
  • LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
  • LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
  • LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。

根据网络合理加载网络数据:

if (NetStatusUtil.isConnected(getApplicationContext())) {
    webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//有网,根据cache-control决定是否从网络上取数据。
} else {
    webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //没网,则从本地获取,即离线加载
}
String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath();
webSettings.setAppCachePath(appCachePath);      //设置缓存数据目录

字体大小控制

Android版本4.0之前WebView支持字体大小分为5中:

  • SMALLEST(50%),
  • SMALLER(75%),
  • NORMAL(100%),
  • LARGER(150%),
  • LARGEST(200%);

设定字体大小:

webSettings.setTextSize(TextSize.SMALLER);

Android4.0之后WebView使用起来更加灵活,可采用setTextZoom(int)设置字体大小,参数默认是100。上边的方法已经舍弃。

WebViewClient

主要展示webview网页加载的一个过程,用于帮助webview处理一些请求事件和通知。

WebViewClient webViewClient = new WebViewClient(){

    //超链接加载,打开网页时不调用系统浏览器,而是在本WebView中显示。也可捕获超链接url,做相关操作
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;    //返回true表示在当前浏览器中加载
    }

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

    //网页加载结束
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
    }

    //网页加载失败
    @Override
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        super.onReceivedError(view, request, error);
    }

    //对Https的支持
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed();
    }

    //针对页面中每一个资源都会调用一次,用于捕获页面资源
    @Override
    public void onLoadResource(WebView view, String url) {
        super.onLoadResource(view, url);
    }
};

WebView调用:

webView.setWebViewClient(webViewClient);

WebChromeClient

WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等。

WebChromeClient webChromeClient = new WebChromeClient(){

    //获取网页加载进度
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        if (newProgress < 100) {
            String progress = newProgress + "%";
        } else {
        }
        super.onProgressChanged(view, newProgress);
    }

    //=========捕获网页标题信息==========================================================
    //获取标题
    @Override
    public void onReceivedTitle(WebView view, String title) {
        super.onReceivedTitle(view, title);
    }
    //获取标题ICON
    @Override
    public void onReceivedIcon(WebView view, Bitmap icon) {
        super.onReceivedIcon(view, icon);
    }

    //=========捕获弹框信息==========================================================
    //警告框
    @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        if(message!=null){
            //TODO
            //捕获网页中弹框信息
            Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
        }
        result.cancel();   //
        return true;       //表示确认进行捕获
    }

    //确认框,会返回布尔值类型,通过这个值可判断点击时是确定还是取消,确定为true,取消为false
    @Override
    public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
        return super.onJsConfirm(view, url, message, result);
    }

    //输入框,会返回输入框中的值,点击取消返回null
    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
        return super.onJsPrompt(view, url, message, defaultValue, result);
    }

    //=========HTML5定位==========================================================
    //需要先加入权限
    //<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    //<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    @Override
    public void onGeolocationPermissionsHidePrompt() {
        super.onGeolocationPermissionsHidePrompt();
    }

    @Override
    public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);  //注意个函数,第二个参数就是是否同意定位权限,第三个是是否希望内核记住
        super.onGeolocationPermissionsShowPrompt(origin, callback);
    }

    //=========HTML5多窗口=========================================================
    //WebSettings要支持多窗口
    @Override
    public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
        WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
        transport.setWebView(webView);
        resultMsg.sendToTarget();
        return true;
    }
    @Override
    public void onCloseWindow(WebView window) {
        super.onCloseWindow(window);
    }
};

WebView调用:

webView.setWebChromeClient(webChromeClient);

支持文件下载

DownloadListener downloadListener = new DownloadListener() {
    @Override
    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
        Uri uri = Uri.parse(url);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        startActivity(intent);
    }
};

WebView调用:

webView.setDownloadListener(downloadListener);

JS交互

js交互说白了就两种形式,一种是由webview中的java方法去调用html中的js方法。另一种是html调用webview中java方法。注意在android4.2之前webview有一个漏洞,外部可通过反射来获取手机的联系方式等隐私,4.2以上官方已经修复,可在每个交互方法上添加一个注解“@JavascriptInterface”便可解决,漏洞详情可参阅:http://blog.csdn.net/leehong2005/article/details/11808557

webview设置对js的支持:

webSettings.setJavaScriptEnabled(true);

webview添加js交互接口:

webView.addJavascriptInterface(new JSInterface(),"jsinterface");

封装js交互类:

class JSInterface {

        //js中可以通过:window.jsinterface.JS2Java();调用java无参方法。
        @JavascriptInterface
        public void JS2Java(){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(WebViewActivity.this,"js调用java无参方法。",Toast.LENGTH_SHORT).show();
                }
            });
        }

        //js中可以通过:window.jsinterface.JS2Java('hello java');调用java有参方法,并传参'hello java'。
        @JavascriptInterface
        public void JS2Java(final String str){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(WebViewActivity.this,"js调用java有参方法,js传递的参数是:"+str,Toast.LENGTH_SHORT).show();
                }
            });
        }

        //Java调用JS中的无参方法
        @JavascriptInterface
        public void Java2JS(){
            webView.loadUrl("javascript: fromJS1()");
            Log.e("TAG","java调用js中的无参方法");
        }

        //Java调用JS中的有参方法,并传参数给js
        @JavascriptInterface
        public void Java2JS(final String str){
            webView.loadUrl("javascript: fromJS2('"+str+"')");
            Log.e("TAG","java调用js中的有参方法");
        }
    }

webview调用js中的方法:

//调用js有参方法
        js_has_args_bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new JSInterface().Java2JS("hello js");
            }
        });

WebView相关方法

  • 前进,后退
    goBack() //后退
    goForward() //前进
    goBackOrForward(intsteps) //以当前的index为起始点前进或者后退到历史记录中指定的steps,如果steps为负数则为后退,正数则为前进
    canGoForward() //是否可以前进
    canGoBack() //是否可以后退
  • 清除缓存
    clearCache(true) //清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
    clearHistory() //清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
    clearFormData() //清除自动完成填充的表单数据,不会清除WebView存储到本地的数据。
  • WebView状态
    onResume() //激活WebView为活跃状态,能正常执行网页的响应
    onPause() //WebView处于暂停状态,onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
    pauseTimers() //暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
    resumeTimers() //恢复pauseTimers时的动作。
    destroy() //销毁,关闭了Activity时,音乐或视频,还在播放。就必须销毁。
  • 重新加载网页
    reload()
    重新加载网页将会重新调用WebClient类中的方法。
  • 判断WebView滚动到顶端还是低端
// 已经处于底端
if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
}
// 处于顶端
if(webView.getScrollY() == 0){
}
  • 退到后台关闭暂停音乐视频播放
public void onPause() {
       super.onPause();
       webView.onPause();
   }

public void onResume() {
       super.onResume();
       webView.onResume();
   }
  • 设置手机返回按键监听
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
        webView.goBack();
        return true;
    }
    finish();
    return super.onKeyDown(keyCode, event);
}
  • Activity退出销毁WebView
    这一步主要防止内存溢出,webview调用destory时,自定义webview仍绑定在Activity上.这是由于自定义webview构建时传入了该Activity的context对象,因此需要先从父容器中移除webview,然后再销毁webview。
@Override
protected void onDestroy() {
    if (webView != null) {
        webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
        webView.clearHistory();

        ((ViewGroup) webView.getParent()).removeView(webView);
        webView.destroy();
        webView = null;
    }
    super.onDestroy();
}

以上是个人总结WebView掌握的知识点,其他细节请移步官方文档查阅清楚,另外在系统级别4.4以上有一个开源引擎crosswalk对H5支持很好,可参阅crosswalk官方文档https://crosswalk-project.org/进行学习。

猜你喜欢

转载自blog.csdn.net/li0978/article/details/52792162