WebView学习笔记
WebView学习笔记,参考最全面、最易懂的Webview使用详解
基本用法
加载内容
1 | webView.loadUrl("http://www.google.com/"); |
加载一个网址
1 | WebView.loadData(String data, String mimeType, String encoding) |
加载一段网络内容,参数1是内容,参数2是内容类型,参数3是编码方式
避免内存泄漏
不在xml中定义,而是需要时创建,使用Application的Context
销毁的时候,先加载空内容,然后移除View,最后销毁
1 | webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null); |
WebView调用destroy()时仍绑定在Activity上,所以要先移除WebView,然后在摧毁
后退
不做处理时,按Back键会使WebView结束掉,所以需要在按键中处理
1 | public boolean onKeyDown(int keyCode, KeyEvent event) { |
常用类
WebSettings
对WebView进行配置管理
1 | WebSettings webSettings = webView.getSettings(); |
如果加载的HTML里有JS在执行动画等操作,会造成资源浪费,在onStop()和onStart()里分别把setJavaScriptEnabled()给设置成false和true即可
WebViewClient
处理各种通知/事件
1 | public boolean shouldOverrideUrlLoading(WebView view, String url) { |
载入Url之前可以在这里获得控制进行处理,不提供时,由系统选择如何处理Url(在浏览器中打开),返回false则由系统处理,返回true 由应用处理
1 | webView.setWebViewClient(new WebViewClient(){ |
以上是在本WebView显示而不打开新的浏览器
1 | // 开始载入页面 |
WebChromeClient
辅助处理JS,图标,标题等
1 | public void onProgressChanged(WebView view, int newProgress) {} |
JS和Android代码的交互
Android调用JS
loadUrl()
1 | mWebView.loadUrl("javascript:callJS()"); |
调用JavaScript中的callJS()方法
JS代码调用一定要在onPageFinished()回调之后才能调用,否则不会调用
evaluateJavascript()
1 | mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() { |
这个方法不会刷新页面,所以比较高效,可以处理返回值,4.4以上才可以用
JS调用Android
addJavascriptInterface()对象映射
定义映射关系类,把JS需要调用的方法用@JavascriptInterface注释,代码中用addJavascriptInterface()添加映射
Android2JS.java
1 | public class Android2JS extends Object { |
1 | mWebView.addJavascriptInterface(new Android2JS(), "android2js"); |
1 | <script> |
这样就可以通过JS调用原生代码
JS拿到Android对象后,可以调用对象中的所有方法,是严重的安全漏洞
对象可以通过
getClass()获得当前类Class,通过Class.forName()可以加载类,如果加载了Runtime类,便可以执行本地命令,比如访问文件APP通过扫描等打开外部网页,可能运行到恶意攻击代码
4.2之后可以通过加@JavascriptInterface注释
4.2之前通过拦截prompt()修复(不很理解,感觉跟下面的差不多)
shouldOverrideUrlLoading()方法回调拦截
1 | <script> |
JS里面的函数修改location,然后通过shouldOverrideUrlLoading()拦截URL路由
1 |
|
只能通过加载执行JS代码返回值,比较麻烦
1 | mWebView.loadUrl("javascript:returnResult(" + result + ")"); |
拦截JS对话框alert()、confirm()、prompt()消息
跟拦截URL差不多,而且使用输入框可以方便的返回值
1 |
|
漏洞
任意代码执行漏洞
addJavascriptInterface()
searchBoxJavaBridge_
3.0以下,系统默认添加映射对象searchBoxJavaBridge_,可能被利用,用removeJavascriptInterface() 删除该方法就好了
accessibility和accessibilityTraversal
同上
密码明文存储
WebView默认开启密码保存,并明文保存到本地数据库,通过WebSettings.setSavePassword(false)关闭密码保存
域控制不严格
A应用可以通过B应用导出的Activity让B应用加载一个恶意的file协议的URL,从而可以获取B应用的内部私有文件,从而带来数据泄露威胁
使用file域加载的JS代码能够使用进行同源策略跨域访问,从而导致隐私信息泄露
通过WebSettings.setAllowFileAccess(true)禁止访问文件,缺点是这样就不能加载本地网页,可以对使用file 协议的URL禁止使用JS
通过WebSettings.setAllowFileAccessFromFileURLs(false)禁止file协议加载的JS访问本地文件
通过WebSettings.setAllowUniversalAccessFromFileURLs(false)禁止file协议加载的JS访问其他Http源等
总之对不需要file 协议的禁用file协议,需要用的禁用JS