文章大纲

一、webview基本介绍
1.什么是webview
2.为什么要使用webview
3.webview基本操作

二、webview高级使用
1.WebView状态
2.资源加载
3.WebView加载优化
4.数据缓存
5.Android 和 JavaScript 交互
6.网页前进与后退
7.内存管理
8.Cookie操作
9.页面监听与拦截
10.定位设置
11.常见问题处理

三、参考文章

 

webview基本介绍

1.什么是webview

  WebView是Android中的原生UI控件,主要用于在app应用中方便地访问远程网页或本地html资源。同时,WebView也在Android中充当Java代码和JS代码之间交互的桥梁。实际上,也可以将WebView看做一个功能最小化的浏览器。

2.为什么要使用webview

  目前很多公司的 App 使用一个 WebView 作为网页加载, App 中的所有网页内容使用 HTML5 进行展示,这样只需要写一次 HTML5 代码,就可以在 Android 和 iOS 平台上运行,这就是所谓的跨平台 。随着 HTML5 的普及,很多 App 都会内嵌 WebView 来加载 HTML5 页面,即 原生和HTML5 共存,这就是当下最流行的「 混合开发 」。HTML5 最大的优势是迭代方便, 只需要修改服务端的 HTML5 页面,App 会同步更新,无论是做活动推广 App 还是及时修复 Bug 都带来的极大的便利。不过 HTML5 劣势也很明显,当网速不尽如人意时候,加载速度会很慢(不知道5G出现后结果会带来什么变革),也就是HTML5 加载受限于网络,没有原生控件流畅,用户体验相对较差, 所以目前完全使用 HTML5 开发 App 并没有成为主流。

3.webview基本操作

添加网络权限
在AndroidManifest.xml中添加以下内容

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

新建webview_simple.xml布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <WebView
  6. android:id="@+id/webview"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent" />
  9. </LinearLayout>

在AndroidManifest.xml中注册WebViewActivity

  1. <activity android:name=".WebViewActivity"></activity>

WebViewActivity中代码如下:

  1. import android.app.Activity;
  2. import android.os.Bundle;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.webkit.WebView;
  5. public class WebViewActivity extends AppCompatActivity {
  6. WebView webView;
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.webview_simple);
  11. webView = (WebView) findViewById(R.id.webview);
  12. //加载网页链接
  13. webView.loadUrl("https://www.baidu.com");
  14. }
  15. }

主页面跳转代码如下:

  1. import android.content.Intent;
  2. import android.os.Bundle;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.view.View;
  5. import android.widget.Button;
  6. import butterknife.BindView;
  7. import butterknife.ButterKnife;
  8. import butterknife.OnClick;
  9. public class MainActivity extends AppCompatActivity {
  10. @BindView(R.id.button)
  11. Button button;
  12. @Override
  13. protected void onCreate(Bundle savedInstanceState) {
  14. super.onCreate(savedInstanceState);
  15. setContentView(R.layout.activity_main);
  16. ButterKnife.bind(this);
  17. }
  18. @OnClick({R.id.button, R.id.button2})
  19. public void onViewClicked(View view) {
  20. switch (view.getId()) {
  21. //简单webview加载
  22. case R.id.button:
  23. startActivity(new Intent(MainActivity.this, WebViewActivity.class));
  24. break;
  25. }
  26. }
  27. }

运行截图如下所示:

 
 

网页弹窗

  1. //message:alert弹出窗口中的提示信息(提示或警告信息对话框,仅一个确认按钮)
  2. //result:向网页中的Javascript代码反馈本次操作结果(result.confirm代表点击了确定按钮,result.cancel代表点击了取消按钮)
  3. public boolean onJsAlert(WebView view, String url, String message,JsResult result)
  4. ///message:confirm弹出窗口中的提示信息(确认对话框,有确认、取消两个按钮)
  5. //result:向网页中的Javascript代码反馈本次操作结果(result.confirm代表点击了确定按钮,result.cancel代表点击了取消按钮)
  6. public boolean onJsConfirm(WebView view, String url, String message,JsResult result)
  7. //message:prompt弹出窗口中的提示信息(输入信息对话框,有一个输入框,还有确认、取消两个按钮)
  8. //defaultValue:输入框中的默认信息
  9. //result:向网页中的Javascript代码反馈本次操作结果(result.confirm代表点击了确定按钮,result.cancel代表点击了取消按钮)
  10. public boolean onJsPrompt(WebView view, String url, String message,String defaultValue, JsPromptResult result)

下面给出一个简单的处理方案,可以作为参考:

  1. @Override
  2. public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
  3. new AlertDialog.Builder(MainActivity.this)
  4. .setTitle("JsAlert")
  5. .setMessage(message)
  6. .setPositiveButton("确定", new DialogInterface.OnClickListener() {
  7. @Override
  8. public void onClick(DialogInterface dialog, int which) {
  9. result.confirm();
  10. }
  11. })
  12. .setCancelable(false)
  13. .show();
  14. return true;
  15. }
  16. @Override
  17. public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
  18. new AlertDialog.Builder(MainActivity.this)
  19. .setTitle("JsConfirm")
  20. .setMessage(message)
  21. .setPositiveButton("确定", new DialogInterface.OnClickListener() {
  22. @Override
  23. public void onClick(DialogInterface dialog, int which) {
  24. result.confirm();
  25. }
  26. })
  27. .setNegativeButton("取消", new DialogInterface.OnClickListener() {
  28. @Override
  29. public void onClick(DialogInterface dialog, int which) {
  30. result.cancel();
  31. }
  32. })
  33. .setCancelable(false)
  34. .show();
  35. return true;
  36. }
  37. @Override
  38. public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {
  39. final EditText editText=new EditText(MainActivity.this);
  40. editText.setText("默认数据");//设置默认数据
  41. new AlertDialog.Builder(MainActivity.this)
  42. .setTitle("JsPromt")
  43. .setView(editText)//为弹出窗口设置输入框
  44. .setPositiveButton("确定", new DialogInterface.OnClickListener() {
  45. @Override
  46. public void onClick(DialogInterface dialog, int which) {
  47. result.confirm(editText.getText().toString());//向Javascript传递输入值
  48. }
  49. })
  50. .setNegativeButton("取消", new DialogInterface.OnClickListener() {
  51. @Override
  52. public void onClick(DialogInterface dialog, int which) {
  53. result.cancel();
  54. }
  55. })
  56. .setCancelable(false)
  57. .show();
  58. return true;
  59. }

二、webview高级使用

1.WebView状态

  1. //激活WebView为活跃状态,能正常执行网页的响应
  2. webView.onResume()
  3. //当页面被失去焦点被切换到后台不可见状态,需要执行onPause
  4. //通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
  5. webView.onPause();
  6. //当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
  7. //它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
  8. webView.pauseTimers()
  9. //恢复pauseTimers状态
  10. webView.resumeTimers();
  11. //销毁Webview
  12. //在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
  13. //但是注意:webview调用destory时,webview仍绑定在Activity上
  14. //这是由于自定义webview构建时传入了该Activity的context对象
  15. //因此需要先从父容器中移除webview,然后再销毁webview:
  16. rootLayout.removeView(webView);
  17. webView.destroy();

2.资源加载

  WebView可以加载多种资源,包括本地资源和远程资源,同时也有多种用于加载资源的方法。
加载assets中的资源

  新建assets文件夹,再新建.html文件

 

在Activity中添加以下代码:

  1. webView.loadUrl("file:///android_asset/test.html");//加载本地assets文件夹下的资源

加载res中的资源

  1. webView.loadUrl(``"[file:///android_res/mipmap/ic_launcher.png](file:///android_res/mipmap/ic_launcher.png)"``);//加载本地res文件夹下的图片
  2. webView.loadUrl(``"[file:///android_res/raw/ic_launcher.png](file:///android_res/raw/ic_launcher.png)"``);//加载本地res文件夹下raw文件夹下的图片
  3. webView.loadUrl(``"[file:///android_res/raw/test.html](file:///android_res/raw/test.html)"``);//加载本地res文件夹下raw文件夹下的html文件

加载sdcard中的资源

  1. webView.loadUrl(``"file:/sdcard/test.html");//加载本地sdcard下的资源
  2. webView.loadUrl(``"[file:///sdcard/test.html](file:///sdcard/test.html)");//加载本地sdcard下的资源
  3. webView.loadUrl(``"[content://com.android.htmlfileprovider/sdcard/test.html

请求远程网页方式
loadData(以字符串形式加载html片段)

  1. //data:html片段
  2. //mimeType:数据类型,如"text/html"
  3. //encoding:数据编码,有两种可选值("base64"和其他任何值),分别代表base64编码和URL编码
  4. public void loadData(String data, String mimeType, String encoding)

loadUrlWithBaseURL(以字符串形式加载html片段)

  1. //baseUrl:基础url,传入null相当于传入了"about:blank"
  2. //data:html片段
  3. //mimeType:数据类型,如"text/html"
  4. //encoding:数据编码,有两种可选值("base64"和其他任何值),分别代表base64编码和URL编码
  5. //historyUrl:历史url
  6. public void loadDataWithBaseURL(String baseUrl, String data,String mimeType, String encoding, String historyUrl)

postUrl(以post请求的形式访问url)

  1. //postData:本次post请求携带的数据,必须是application/x-www-form-urlencoded编码
  2. //如果传入的url不是一个远程网页地址,那么最终将通过loadUrl方法加载这个url,同时postData参数会被忽略。
  3. public void postUrl(String url, byte[] postData)

3.WebView加载优化

设置页面自适应屏幕

  1. webSettings.setUseWideViewPort(true);
  2. webSettings.setLoadWithOverviewMode(true);

缩放功能

  1. webSettings.setSupportZoom(true);//启用缩放功能
  2. webSettings.setBuiltInZoomControls(true);//使用WebView内置的缩放功能
  3. webSettings.setDisplayZoomControls(false);//隐藏屏幕中的虚拟缩放按钮

温馨提示:setDisplayZoomControls(true)在某些系统版本中可能会导致应用出现意外崩溃。

若加载的 html 里有JS 在执行动画等操作,会造成资源浪费(CPU、电量)
在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可

页面加载过程优化
处理各种通知 & 请求事件

  1. //步骤1. 定义Webview组件
  2. Webview webview = (WebView) findViewById(R.id.webView1);
  3. //步骤2. 选择加载方式
  4. //方式1. 加载一个网页:
  5. webView.loadUrl("http://www.google.com/");
  6. //步骤3. 复写shouldOverrideUrlLoading()方法,使得打开网页时不调用系统浏览器, 而是在本WebView中显示
  7. webView.setWebViewClient(new WebViewClient(){
  8. @Override
  9. public boolean shouldOverrideUrlLoading(WebView view, String url) {
  10. view.loadUrl(url);
  11. return true;
  12. }
  13. });

onPageStarted()
作用:开始载入页面调用的,我们可以设定一个loading的页面,告诉用户程序在等待网络响应。

  1. webView.setWebViewClient(new WebViewClient(){
  2. @Override
  3. public void onPageStarted(WebView view, String url, Bitmap favicon) {
  4. //设定加载开始的操作
  5. }
  6. });

onPageFinished()
作用:在页面加载结束时调用。我们可以关闭loading 条,切换程序动作。

  1. webView.setWebViewClient(new WebViewClient(){
  2. @Override
  3. public void onPageFinished(WebView view, String url) {
  4. //设定加载结束的操作
  5. }
  6. });

onLoadResource()
作用:在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。

  1. webView.setWebViewClient(new WebViewClient(){
  2. @Override
  3. public boolean onLoadResource(WebView view, String url) {
  4. //设定加载资源的操作
  5. }});

onReceivedError()
作用:加载页面的服务器出现错误时(如404)调用。App里面使用webview控件的时候遇到了诸如404这类的错误的时候,若也显示浏览器里面的那种错误提示页面就显得很丑陋了,那么这个时候我们的app就需要加载一个本地的错误提示页面,即webview如何加载一个本地的页面

  1. //步骤1:写一个html文件(error_handle.html),用于出错时展示给用户看的提示页面
  2. //步骤2:将该html文件放置到代码根目录的assets文件夹下
  3. //步骤3:复写WebViewClient的onRecievedError方法
  4. //该方法传回了错误码,根据错误类型可以进行不同的错误分类处理
  5. webView.setWebViewClient(new WebViewClient(){
  6. @Override
  7. public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
  8. switch(errorCode)
  9. {
  10. case HttpStatus.SC_NOT_FOUND:
  11. view.loadUrl("file:///android_assets/error_handle.html");
  12. break;
  13. } }
  14. });

onReceivedSslError()
作用:处理https请求,webView默认是不处理https请求的,页面显示空白,需要进行如下设置:

  1. webView.setWebViewClient(new WebViewClient() {
  2. @Override
  3. public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
  4. handler.proceed(); //表示等待证书响应
  5. // handler.cancel(); //表示挂起连接,为默认方式
  6. // handler.handleMessage(null); //可做其他处理
  7. }
  8. });

4.数据缓存

当加载 html 页面时,WebView会在/data/data/包名目录下生成 database 与 cache 两个文件夹
请求的 URL记录保存在 WebViewCache.db,而 URL的内容是保存在 WebViewCache 文件夹下,设置是否启动缓存方法如下:

  1. WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
  2. 缓存模式如下:
  3. // LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
  4. // LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
  5. // LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
  6. // LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
  7. //WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);不使用缓存

结合使用(离线加载)

  1. if (NetStatusUtil.isConnected(getApplicationContext())) {
  2. webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//根据cache-control决定是否从网络上取数据。
  3. } else {
  4. webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//没网,则从本地获取,即离线加载
  5. }
  6. webSettings.setDomStorageEnabled(true); // 开启 DOM storage API 功能
  7. webSettings.setDatabaseEnabled(true); //开启 database storage API 功能
  8. webSettings.setAppCacheEnabled(true);//开启 Application Caches 功能
  9. String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
  10. webSettings.setAppCachePath(cacheDirPath); //设置 Application Caches 缓存目录
  11. //注意: 每个 Application 只调用一次 WebSettings.setAppCachePath(),WebSettings.setAppCacheMaxSize()

清理缓存

  1. //清除网页访问留下的缓存
  2. //由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
  3. webView.clearCache(true);
  4. //清除当前webview访问的历史记录
  5. //只会webview访问历史记录里的所有记录除了当前访问记录
  6. webView.clearHistory();
  7. //这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据
  8. webView.clearFormData();
  9. 另外一种方式:
  10. //删除缓存文件夹
  11. File file = CacheManager.getCacheFileBaseDir();
  12. if (file != null && file.exists() && file.isDirectory()) {
  13. for (File item : file.listFiles()) {
  14. item.delete();
  15. }
  16. file.delete();
  17. }
  18. //删除缓存数据库
  19. context.deleteDatabase("webview.db");
  20. context.deleteDatabase("webviewCache.db");

5.Android 和 JavaScript 交互

安卓代码

  1. WebSettings settings = mWebView.getSettings();
  2. settings.setJavaScriptEnabled(true);//开启JavaScript
  3. mWebView.loadUrl("file:///android_asset/keithxiaoy.html");//加载本地网页
  4. mWebView.setWebChromeClient(new WebChromeClient());//此行代码可以保证JavaScript的Alert弹窗正常弹出
  5. //核心方法, 用于处理JavaScript被执行后的回调
  6. mWebView.addJavascriptInterface(new JsCallback() {
  7. @JavascriptInterface//注意:此处一定要加该注解,否则在4.1+系统上运行失败
  8. @Override
  9. public void onJsCallback() {
  10. System.out.println("JavaScript调用Android啦");
  11. }
  12. }, "keithxiaoy");//参1是回调接口的实现;参2是JavaScript回调对象的名称
  13. //定义回调接口
  14. public interface JsCallback {
  15. public void onJsCallback();
  16. }

Android 调用 JavaScript

  1. //直接使用webview加载js就可以了
  2. mWebView.loadUrl("javascript:wave()");

html代码如下

  1. <head>
  2. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  3. </head>
  4. <script language="javascript">
  5. /* This function is invoked by the activity */
  6. function wave() {
  7. alert("Android调用JavaScript");
  8. }
  9. </script>
  10. <body>
  11. <!-- JavaScript调用Android代码 -->
  12. <a onClick="window.demo.onJsCallback()"><div style="width:80px;
  13. margin:0px auto;
  14. padding:10px;
  15. text-align:center;
  16. border:2px solid #202020;" >
  17. ![](android_normal.png)<br>
  18. Click me!
  19. </div></a>
  20. </body>
  21. </html>

注意:
  JavaScript 回调的方法的书写格式: onClick="window.demo.onJsCallback()格式是: Windows.js 回调对象的名称(要和 Java 代码中设置的一致)。回调方法名称(要和 Java 代码中设置的一致)
  JavaScript 调用 Android 的方式具有版本兼容问题。经测试,在 2.2、4.0+ 系统上运行稳定,可以正常调用,但是在 2.3 系统上运行时出现崩溃。原因是底层进行 JNI 调用时,把一个 Java 中的 String 对象当数组来访问了,最终导致虚拟机崩溃。基本算是一个比较严重的 Bug,没办法解决。所以如果说用 WebView 组件想在 JavaScript 和 Java 互调就没办法适配所有机型。

6.网页前进与后退

在安卓手机中,Back 键控制网页后退,会关闭整个webview,解决方法是在当前 Activity 中处理获取Back键,改造成网络的返回上一步

  1. webView.goBack();//跳到上个页面
  2. webView.goForward();//跳到下个页面
  3. webView.canGoBack();//是否可以跳到上一页(如果返回false,说明已经是第一页)
  4. webView.canGoForward();//是否可以跳到下一页(如果返回false,说明已经是最后一页)

7.内存管理

  直接 new WebView 并传入 application context 代替在 XML 里面声明以防止 activity 引用被滥用,能解决90+%的 WebView 内存泄漏。

  1. vWeb = new WebView(getContext().getApplicationContext());
  2. container.addView(vWeb);

销毁 WebView

  1. if (vWeb != null) {
  2. vWeb.setWebViewClient(null);
  3. vWeb.setWebChromeClient(null);
  4. vWeb.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
  5. vWeb.clearHistory();
  6. ((ViewGroup) vWeb.getParent()).removeView(vWeb);
  7. vWeb.destroy();
  8. vWeb = null;
  9. }

8.Cookie操作
Cookie 设置

  1. CookieSyncManager.createInstance(this);
  2. CookieManager cookieManager = CookieManager.getInstance();
  3. cookieManager.setAcceptCookie(true);
  4. String cookie = "name=xxx;age=18";
  5. cookieManager.setCookie(URL, cookie);
  6. CookieSyncManager.getInstance().sync();

获取 Cookie

  1. CookieManager cookieManager = CookieManager.getInstance();
  2. String cookie = cookieManager.getCookie(URL);

清除 Cookie

  1. CookieSyncManager.createInstance(context);
  2. CookieManager cookieManager = CookieManager.getInstance();
  3. cookieManager.removeAllCookie();
  4. CookieSyncManager.getInstance().sync();

9.页面监听与拦截

监听网页加载进度

  1. public void onProgressChanged(WebView view, int newProgress)

  onProgressChanged会在网页加载过程中多次触发。当newProgress的值为100时,可以认为当前网页已经加载完毕。因此,通过这个方法判断页面是否加载完成比使用上文提到的onPageFinished方法更准确。同时,由于这个方法在回调中会不断获得最新的加载进度,因此我们可以借助这个方法实现自定义的加载进度条。
  这里给出一个简单的思路:在WebView的上方添加一个ProgressBar控件,并默认隐藏。在onPageStarted方法中显示ProgressBar,并在onProgressChanged方法回调时更新ProgressBar的进度值。当onProgressChanged方法中的newProgress达到100时,就隐藏这个ProgressBar。需要注意,为了在页面加载出错时也能正确隐藏进度条,也应该在onReceivedError方法中隐藏ProgressBar。

10.定位设置

  1. webSettings.setGeolocationEnabled(true);//允许网页执行定位操作

如果要禁用网页的定位功能,传入false作为参数即可。需要注意,这个方法只是允许网页执行定位操作,但是最终定位操作的实现还是会委托给Android应用处理。因此,为了保证定位功能正常执行,需要满足以下两点:
Android应用需要获取定位权限。需要在AndroidManifest文件中声明android.Manifest.permission.ACCESS_COARSE_LOCATION和android.Manifest.permission.ACCESS_FINE_LOCATION两个权限。 需要为WebView设置WebChromeClient,并重写WebChromeClient的onGeolocationPermissionsShowPrompt方法。这个方法会在网页中的Javascript代码执行定位操作时触发。需要注意,Android6.0及以上引入了运行时权限的概念。定位属于危险权限,需要在使用时手动获取。因此我们可以在这个回调方法中弹出一个请求定位的提示对话框(AlertDialog),在用户选择确定后获得相应权限。

11.常见问题处理

loadData加载中文数据出现乱码
  问题描述:使用loadData方法加载含有中文的数据时,中文显示为乱码。
  解决方案:使用loadDataWithBaseURL方法代替loadData加载数据,不会出现乱码问题。 为loadData的mimeType参数传入“text/html;charset=UTF-8”,也可以解决乱码问题。

密码明文存储问题
  问题描述:在Android 4.3(API 18)以前,用户在WebView加载的网页中输入密码后,系统会弹出对话框询问用户是否需要保存密码。如果用户选择保存,那么密码将会以明文的形式保存在本地,显然这是一个巨大的安全隐患。
  解决方案:WebView是否保存密码是由WebSettings的setSavePassword方法决定的。因此,我们只要调用这个方法并传入false,就可以避免明文储存的安全问题了。在Android 4.3及以上的版本,setSavePassword方法已经被弃用,WebView也不会默认保存密码,因此不再需要进行修复。

WeView出现OOM影响主进程
  问题描述:由于WebView默认运行在应用进程中,如果WebView加载的数据过大(例如加载大图片),就可能导致OOM问题,从而影响应用主进程。
  解决方案:为了避免WebView影响主进程,可以尝试将WebView所在的Activity运行在独立进程中。这样即使WebView出现了OOM问题,应用主进程也不会受到影响。具体做法也很简单,只要在AndroidManifest文件中为相应的Activity设置process属性即可。

WebView后台耗电问题
  问题描述:在某些情况下,即使Activity已经退出,WebView依旧占据着内存空间,这会导致设备耗电量增加。
  解决方案:在上文提到过将WebView运行在独立进程中,然后只要在Activity的onDestroy方法中调用System.exit(0)退出虚拟机,就可以避免WebView继续占据内存空间.

视频或音频在退出Activity后继续播放的问题
  问题描述:在WebView加载的网页中播放音乐或视频,然而当前应用进入后台后音乐或视频还在继续播放。
  解决方案:在Activity的onPause方法中暂停WebView,然后在onResume方法中恢复WebView。

  1. protected void onPause() {
  2. if(webView!=null){//暂停WebView
  3. webView.onPause();
  4. webView.pauseTimers();
  5. }
  6. super.onPause();
  7. }
  8. @Override
  9. protected void onResume() {
  10. if(webView!=null){//恢复WebView
  11. webView.onResume();
  12. webView.resumeTimers();
  13. }
  14. super.onResume();
  15. }
  16. &emsp;&emsp;

开启硬件加速导致的闪烁问题
  问题描述:在应用开启硬件加速后,WebView可能在加载过程出现闪烁现象。
  解决方案:为WebView关闭硬件加速功能。

  1. webView.setLayerType(View.LAYER_TYPE_SOFTWARE,null);

https请求失败的解决方案
  问题描述:在使用WebView加载https协议的网页或资源时,如果该网站的安全证书不被Android认可,就会出现无法成功加载的问题。
  解决方案:重写WebViewClient的onReceivedSslError方法,设置其接受所有网站的安全证书。

  1. public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
  2. handler.proceed();//接受所有网站证书
  3. }

WebView中http和https混合使用的问题
  问题描述:在Android 5.0及以上,WebView可能在加载混合使用http和https的网页时出现异常。比如在一个https的安全网页中加载使用http协议的资源将会失败。
  解决方案:在Android 5.0后利用WebSettings设置WebView支持http和https混合内容模式。

  1. //方式1
  2. webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
  3. //方式2
  4. webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

  需要注意,MIXED_CONTENT_ALWAYS_ALLOW这个模式是不安全的,建议先使用MIXED_CONTENT_COMPATIBILITY_MODE模式。这个模式会尝试以安全的方式加载部分http资源,另一部分http资源则不会被加载。资源是否能被加载的判断依据可能会随着版本的不同而改变,因此需要根据实际情况决定是否采用这一模式。

setDisplayZoomControls引起的崩溃问题
  问题描述:我们知道,setDisplayZoomControls(true)方法会允许显示系统缩放按钮,这个缩放按钮会在每次出现后的几秒内逐渐消失。但是在部分系统版本中,如果在缩放按钮消失前退出了Activity,就可能引起应用崩溃。
  解决方案:调用setDisplayZoomControls(false)方法不显示系统缩放按钮,反正使用手势捏合动作就可以实现网页的缩放功能了。如果确实需要使用缩放按钮,就需要在Activity的onDestroy方法中隐藏WebView。

  1. webView.setVisibility(View.GONE);

三、参考文章

  1. https://www.jianshu.com/p/4564be81a108
  2. https://www.jianshu.com/p/daf6d72268a4
  3. https://www.2cto.com/kf/201712/706339.html

Android之webview详解的更多相关文章

  1. 最全面的Android Webview详解

    转自:最全面的Android Webview详解 前言 现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图  那么这种该如何实现呢?其实这是 ...

  2. android:ToolBar详解

    android:ToolBar详解(手把手教程) 泡在网上的日子 发表于 2014-11-18 12:49 第 124857 次阅读 ToolBar 42 来源 http://blog.mosil.b ...

  3. Android之canvas详解

    首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, y ...

  4. 【转】Android Canvas绘图详解(图文)

    转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android Canvas绘图详解(图文) 泡 ...

  5. Android 核心分析 之八Android 启动过程详解

    Android 启动过程详解 Android从Linux系统启动有4个步骤: (1) init进程启动 (2) Native服务启动 (3) System Server,Android服务启动 (4) ...

  6. Android GLSurfaceView用法详解(二)

    输入如何处理       若是开发一个交互型的应用(如游戏),通常需要子类化 GLSurfaceView,由此可以获取输入事件.下面有个例子: java代码: package eoe.ClearTes ...

  7. Android编译过程详解(一)

    Android编译过程详解(一) 注:本文转载自Android编译过程详解(一):http://www.cnblogs.com/mr-raptor/archive/2012/06/07/2540359 ...

  8. android屏幕适配详解

    android屏幕适配详解 官方地址:http://developer.android.com/guide/practices/screens_support.html 一.关于布局适配建议 1.不要 ...

  9. Android.mk文件详解(转)

    源:Android.mk文件详解 从对Makefile一无所知开始,折腾了一个多星期,终于对Android.mk有了一个全面些的了解.了解了标准的Makefile后,发现Android.mk其实是把真 ...

随机推荐

  1. Spring中的循环依赖

    循环依赖 在使用Spring时,如果主要采用基于构造器的依赖注入方式,则可能会遇到循环依赖的情况,简而言之就是Bean A的构造器依赖于Bean B,Bean B的构造器又依赖于Bean A.在这种情 ...

  2. Series

    Series是一种类似于一维数组的对象,是由一维数据(各种Numpy数据类型)以及一组与之相关的数据标签(即索引)组成. In [1]: from pandas import Series In [2 ...

  3. markdown中如何插入公式

    转自 :https://www.tuicool.com/articles/qqIrUbN 我是如何在Markdown文档里插入公式的 时间 2016-08-07 21:05:33 异步社区 原文  h ...

  4. BITE

    <Google软件测试之道> 读后感言: p147 提到的BITE实在是太让人心动了, 一个简单的动作即可提交一个信息齐全的bug,连非专业测试人员也能轻松做到.身边很多人也都碰到过提交b ...

  5. 【BZOJ 2673】[Wf2011]Chips Challenge

    题目大意: 传送门 $n*n$的棋盘,有一些位置可以放棋子,有一些已经放了棋子,有一些什么都没有,也不能放,要求放置以后满足:第i行和第i列的棋子数相同,同时每行的棋子数占总数比例小于$\frac{A ...

  6. BZOJ_1433_[ZJOI2009]假期的宿舍_二分图匹配

    BZOJ_1433_[ZJOI2009]假期的宿舍_二分图匹配 题意: 学校放假了······有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如A 和B都是学校的学生,A要回 ...

  7. BZOJ2751 [HAOI2012]容易题

    Description 为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下: 有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取 ...

  8. [NOIP2002]字串变换 T2 双向BFS

    题目描述 已知有两个字串  A,B  及一组字串变换的规则(至多6个规则): A1−>B1 A2−>B2 规则的含义为:在  A$中的子串  A1可以变换为可以变换为B1.A2可以变换为可 ...

  9. linux重置密码的方法和用户切换

    由于好久没有用本地的vmware了,本地虚拟机的密码都忘光了,这个不常遇见的问题碰到了,百度了一下解决了 学习源头:https://www.cnblogs.com/lippor/p/5537931.h ...

  10. privoxy自动请求转发到多个网络

    有些时候我们需要通过不同的代理访问不同资源,比如某些ip或域名走本地网络,某些ip或域名走不可描述的代理等.当然这只是举个栗子! 我要解决的问题是:我的内网机器没有internet访问权限,但是我的应 ...