知识点汇总:
前言
结合H5页面开发的App日渐多了起来,而WebView正是Html与Native的纽带,今天就借着一个新的项目需求顺便做一下WebView的知识总结,如有错漏,恳请大家指点指点。(项目需求:将适配好的网页打包成App,并能够调用系统摄像头进行二维码识别、拍照或是选择本地图片上传、获取用户位置等)
WebView 小科普
官方文档
Class Overview
A View that displays web pages. This class is the basis upon which you can roll
your own web browser or simply display some online content within your Activity.
It uses the WebKit rendering engine to display web pages and includes methods
to navigate forward and backward through a history, zoom in and out, perform text searches and more.
理解:WebView是一个显示网页的一个View,基本应用于浏览器或是Activity中网页的简单显示。使用了WebKit渲染引擎实现一系列神奇的功能。Basic usage
By default, a WebView provides no browser-like widgets, does not enable JavaScript and web page errors are ignored.
理解:默认情况,WebView并没有开启对JavaScript的支持,仅起展示作用,因此,我们需要进一步配置WebView才能满足各种各样的需求。
WebView基本使用
- 在 AndroidManifest.xml 中添加联网权限(如果webView需要联网的话,仅加载本地html、js文件则不需要添加联网权限)
|
|
- 一些 WebSettings 常用配置(其实还有许多没有列出来,大家可以利用IDE,点击进入方法,查看源码继续发掘)
|
|
|
|
- 加载网页、本地、assets中的html页面基本方式
|
|
WebViewClient 与 WebChromeClient
WebViewClient与WebChromeClient的区别
- WebViewClient 用于帮助WebView处理各种通知、请求事件
WebViewClient 常用方法 | 说明 |
---|---|
shouldOverrideUrlLoading | 加载时调用,可捕获url |
onPageStart | 开始加载时调用(可以设置加载中提示) |
onPageFinish | 加载完成时调用(无法打开也是完成的一种,在这里取消加载提示显示) |
onReceiveError | 接收到错误信息时调用(通常在该方法中处理404之类的加载错误,但这里有点坑,API23中,在低于API23的设备上运行时,该方法失效,不调用我猜原因可能是: 新版的onReceiveError不再接收网页连接的错误,而是接收WebView自身运行出现的错误,另外有onReceivedHttpError方法来接收(然而在我的测试中,该方法还是未能接收到404错误)。可暂时用API23过时的方法“onReceivedError(WebView view, int errorCode, String description, String failingUrl)”替代新版本中的“onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)”;)传送门:stackoverflow Q&A |
- WebChromeClient 用于辅助 WebView处理Javascript的对话框,网站图标、Title、位置、加载进度等信息
WebChromeClient 常用方法 | 说明 |
---|---|
onProgressChanged | 加载进度 |
onReceivedTitle、onReceivedIcon | 获取网页标题、图标 |
onGeolocationPermissionsShowPrompt | 页面发起GEO定位请求时调用 |
… | WebChromeClient源码中对各种方法都有详细解析,需要用到的时候查一下即可 |
- 两者用法都是简单的set方法12mWebView.setWebViewClient(mWebViewClient);mWebView.setChromeClient(mWebChromeClient);
WebView与Javascript交互
- 前提条件:setJavaScriptEnabled(true)
- 调用js方法
mWebView.loadUrl("javascript: 方法名('"+参数+"')");
- js调用android中方法
4.2及之前版本该方法存在漏洞:Android WebView的Js对象注入漏洞解决方案、JS与WebView交互存在的一些问题引用”漏洞描述”:
1,WebView添加了JavaScript对象,并且当前应用具有读写SDCard的权限,也就是:android.permission.WRITE_EXTERNAL_STORAGE
2,JS中可以遍历window对象,找到存在“getClass”方法的对象的对象,然后再通过反射的机制,得到Runtime对象,然后调用静态方法来执行一些命令,比如访问文件的命令.
3,再从执行命令后返回的输入流中得到字符串,就可以得到文件名的信息了。然后想干什么就干什么,好危险。1234567891011121314151617181920212223242526/*** This method can be used to allow JavaScript to control the host* application. This is a powerful feature, but also presents a security* risk for apps targeting{@link android.os.Build.VERSION_CODES#JELLY_BEAN}* or earlier.* ///理解:该方法可以让js控制app,很强势,但在API17(4.2)及之前的版本存在安全问题addJavascriptInterface(Object object, String name);//使用方法mWebView.addJavascriptInterface(MethodObject,"name");//还需要写一个方法类class MethodObject extends Object {//无参函数,js中通过:var str = window.name.HtmlcallJava(); 获取到@JavascriptInterfacepublic String HtmlcallJava() {return "Html call Java";}//有参函数,js中通过:window.jsObj.HtmlcallJava2("IT-homer blog");@JavascriptInterfacepublic String HtmlcallJava2(final String param) {return "Html call Java : " + param;}}
WebView小技巧
- 捕获Url
- 重定向问题,推荐WebView加载重定向url影响goBack()解决方案、重定向影响goBack()
|
|
|
|
|
|
WebView 进阶
WebView 内存泄漏问题
WebView解析网页时会申请Native堆内存用于保存页面元素,当页面较复杂时会有很大的内存占用。如果页面包含图片,内存占用会更严重。并且打开新页面时,为了能快速回退,之前页面占用的内存也不会释放。有时浏览十几个网页,都会占用几百兆的内存。这样加载网页较多时,会导致系统不堪重负,最终强制关闭应用,也就是出现应用闪退或重启。
由于占用的都是Native堆内存,所以实际占用的内存大小不会显示在常用的DDMS Heap工具中(这里看到的只是Java虚拟机分配的内存,一般即使Native堆内存已经占用了几百兆,这里显示的还只是几兆或十几兆)。只有使用adb shell中的一些命令比如dumpsys meminfo 包名,或者在程序中使用Debug.getNativeHeapSize()才能看到。
据说由于WebView的一个BUG,即使它所在的Activity(或者Service)结束也就是onDestroy()之后,或者直接调用WebView.destroy()之后,它所占用这些内存也不会被释放。
解决这个问题最直接的方法是:把使用了WebView的Activity(或者Service)放在单独的进程里。然后在检测到应用占用内存过大有可能被系统干掉或者它所在的Activity(或者Service)结束后,调用System.exit(0),主动Kill掉进程。由于系统的内存分配是以进程为准的,进程关闭后,系统会自动回收所有内存。
WebView 缓存机制
推荐文章Android WebView缓存机制详解、深入探究webView的缓存机制
经过一番搜索得来的结果:
1. WebView缓存分为:页面缓存和数据缓存。页面缓存指加载网页时,对页面或资源数据的缓存。一般使用RE管理器进入目录: “/data/data/(packageName)/cache/org.chromium.android_webview“可看到;
数据缓存又分为 AppCache 与 DOM Storage 。AppCache可以有选择地缓存我们所想要缓存的东西;DOM Storage 则是HTML5的一个缓存机制,常用于存储简单的表单数据,关于DOM Storage,详情可学习参考下 “浅谈HTML5 的DOM Storage机制” 一文。
2. webView的缓存模式:
LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
LOAD_DEFAULT: 根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
- 将缓存路径转移到外置sd卡
查看 Context 类API 发现这样一个方法,重写该方法即可(注意赋予相关权限,但Android 4.4 上权限限制,会使该方法失效)
另外趁机附上:Android 外部存储权限分析(译)、Android存储访问及目录
|
|
|
|
结束语
本文主要是对自己学习WebView的过程、应用WebView遇到的一些问题,结合强大的网络资源总结而来,如果错漏,恳请指教,希望能给大家提供小小的帮助,在分享技术过程中,提升、成长!(有很长一段时间没有发布过博客,贵在坚持,贵在坚持!)