Android中WebView的基本配置与填坑记录大全

前言

在应用程序开发过程中,经常会采用webview来展现某些界面,这样就可以不受发布版本控制,实时更新,遇到问题可以快速修复。

但是在Android开发中,由于Android版本分化严重,每一个版本针对webview都有部分更改,因此在开发过程中会遇到各种各样的坑,下面这篇就来给大家介绍关于Android中WebView的基本配置与填坑记录,话不多说了,来一起看看详细的介绍吧。

基本配置

// 硬件加速
getActivity().getWindow().setFlags(
 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
// WebView 配置
WebSettings webSettings = mWebView.getSettings();
// 生命周期
mWebView.onPause(); // 通过 onPause 动作通知内核暂停所有的动作,如 DOM 的解析、plugin 的执行、JavaScript 执行等
mWebView.onResume(); // 恢复 WebView,能正常执行网页的响应
((ViewGroup) mWebView.getParent()).removeView(mWebView);
mWebView.destroy(); // 当 Activity 要 destroy 时,应先将 WebView 移除,再 destroy 掉
// 前进后退
if (mWebView.canGoBack()) {
 mWebView.goBack();
}
if (mWebView.canGoForward()) {
 mWebView.goForward();
}
// 缓存相关
mWebView.clearCache(true); // 清除缓存
mWebView.clearHistory(); // 清除历史
mWebView.clearFormData(); // 清除表单数据
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);// 设置缓存模式
// 缓存模式
LOAD_DEFAULT: 默认,根据 cache-control 决定是否从网络上取数据
LOAD_NORMAL: API level 17 中已经废弃, 从API level 11开始作用同 LOAD_DEFAULT 模式
LOAD_CACHE_ELSE_NETWORK: 只要本地有,无论是否过期,或者 no-cache,都使用缓存中的数据
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据
LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
// js 相关
webSettings.setJavaScriptEnabled(true); // 支持 js。如果碰到后台无法释放 js 导致耗电,应在 onStop 和 onResume 里分别设成 false 和 true
mWebView.addJavascriptInterface(new WebAppInterface(this), "android"); // js 接口
webSettings.setPluginsEnabled(true); // 支持插件
// 设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true); // 将图片调整到适合 WebView 的大小
webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
// 缩放操作
webSettings.setSupportZoom(true); // 支持缩放,默认为 true
webSettings.setBuiltInZoomControls(true); // 设置内置的缩放控件,若为 false,则该 WebView 不可缩放
webSettings.setDisplayZoomControls(false); // 隐藏原生的缩放控件

填坑记录

1、WebViewClient 类常用方法

mWebView.setWebViewClient(new MyWebViewClient());

shouldOverrideUrlLoading()

在网页上的所有加载都经过这个方法,这个函数我们可以做很多操作。

onPageStarted()

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

onPageFinished()

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

onLoadResource()

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

onReceivedError()

加载页面出现错误时调用。

2、WebChromeClient 类常用方法

mWebView.setWebChromeClient(new MyWebChromeClient());

onProgressChanged()

获得网页的加载进度并显示。

onReceivedTitle()

获取 Web 页中的标题。

onJsAlert()

支持 javascript 的警告框。

onJsConfirm()

支持 javascript 的确认框。

onJsPrompt()

支持 javascript 输入框。

3、 Https 和 Http 混合模式

从 Android 5.0 开始,WebView 默认不支持同时加载 Https 和 Http 资源。

解决方法:在webview加载页面之前,设置加载模式为 MIXED_CONTENT_ALWAYS_ALLOW

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
 webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}

4、安全问题

addJavascriptInterface

Android 4.2 以前,要采用拦截 prompt() 的方式进行漏洞修复;Android 4.2 以后,只需要对被调用的函数以 @JavascriptInterface 进行注解。

searchBoxJavaBridge_、accessibility、accessibilityTraversal

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
 mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
 mWebView.removeJavascriptInterface("accessibility");
 mWebView.removeJavascriptInterface("accessibilityTraversal");
}

密码明文存储漏洞

webSettings.setSavePassword(false);

5、替换 WebView 的加载错误页面

@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
 super.onReceivedError(view, errorCode, description, failingUrl);
 showCustErrorPage();
}
private View mErrorView;
protected void showCustErrorPage() {
 // 移除WebView
 ViewGroup webParentView = (ViewGroup) mWebViewInstance.getParent();
 while (webParentView.getChildCount() > 0) {
 webParentView.removeViewAt(0);
 }
 // 生成自定义错误页面
 if (mErrorView == null) {
 mErrorView = View.inflate(mContext, R.layout.webview_error, null);
 mErrorView.setOnClickListener(new View.OnClickListener() {
  public void onClick(View v) {
  showWebViewPage();
  mWebViewInstance.reload();
  }
 });
 }
 // 替换为错误页面
 ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
  ViewPager.LayoutParams.FILL_PARENT, ViewPager.LayoutParams.FILL_PARENT);
 webParentView.addView(mErrorView, 0, lp);
}
protected void showWebViewPage() {
 // 移除自定义错误页面
 ViewGroup webParentView = (ViewGroup) mErrorView.getParent();
 while (webParentView.getChildCount() > 0) {
 webParentView.removeViewAt(0);
 }
 // 替换为WebView
 ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
  ViewPager.LayoutParams.FILL_PARENT, ViewPager.LayoutParams.FILL_PARENT);
 webParentView.addView(mWebViewInstance, 0, lp);
}

6、WebView的内存泄露。

关于这个问题,我很难给你一个清晰的描述,你在谷歌里搜 webview lead memory 能搜到很多结果 甚至还有给谷歌提交的issue 哈哈,我也无法给出一个清晰的答案 在什么时候 什么版本那些手机上一定会出现内存泄露,

但是根据我自己的monkey结果来看,有时,webview内存泄露的情况还是很严重的,尤其是当你加载的页面比较庞大的时候。解决方案 我查了很多也用了很多,但是都不太理想,最后看了下微信和qq的做法,试了一下是目前效果最好的,

就是 当你要用webview的时候,记得最好 另外单独开一个进程 去使用webview 并且当这个 进程结束时,请手动调用System.exit(0)。

这是目前对于webview 内存泄露 最好的解决方案。使用此方法 所有因为webview引发的 资源无法释放等问题 全部可以解决。

7、getSettings().setBuiltInZoomControls(true) 引发的crush。

这个方法调用以后 如果你触摸屏幕 弹出那个提示框还没消失的时候 你如果activity结束了 就会报错了。3.0以上 4.4以下很多手机会出现这种情况

所以为了规避他,我们通常是在activity的onDestroy方法里手动的将webiew设置成 setVisibility(View.GONE)

8、onPageFinished 函数到底有用没有?

多数开发者都是参考的http://stackoverflow.com/questions/3149216/how-to-listen-for-a-webview-finishing-loading-a-url-in-android 这个上面的高票答案。

但其实根据我自己观察,这个函数并没有什么卵用,有的时候是提前结束,有的时候就迟迟无法结束,你信这个函数 还不如信上帝,甚至于onProgressChanged这个函数

都比onPageFinished 要准一些。如果你的产品经理坚持你一定要实现这种功能的话,我建议你 提早结束他,否则卡在那用户迟迟动不了 这种体验不好。

有空的同学可以跟一下源码,onPageFinished 在不同的内核里 调用的时机都不一样。说实话 我也很醉。。。这个问题 有完美解决方案的 请知会我一下。。。

9、后台无法释放js 导致耗电。

这个可能很少有人知道,我也是被投诉过 才了解,在有的手机里,你如果webview加载的html里 有一些js 一直在执行比如动画之类的东西,如果此刻webview 挂在了后台

这些资源是不会被释放 用户也无法感知。。。导致一直占有cpu 耗电特别快,所以大家记住了,如果遇到这种情况 请在onstop和onresume里分别把setJavaScriptEnabled();

给设置成false和true。

10、如果实在不想用开额外进程的方式解决webview 内存泄露的问题,那么下面的方法很大程度上可以避免这种情况

public void releaseAllWebViewCallback() {
  if (android.os.Build.VERSION.SDK_INT < 16) {
   try {
    Field field = WebView.class.getDeclaredField("mWebViewCore");
    field = field.getType().getDeclaredField("mBrowserFrame");
    field = field.getType().getDeclaredField("sConfigCallback");
    field.setAccessible(true);
    field.set(null, null);
   } catch (NoSuchFieldException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   } catch (IllegalAccessException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   }
  } else {
   try {
    Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");
    if (sConfigCallback != null) {
     sConfigCallback.setAccessible(true);
     sConfigCallback.set(null, null);
    }
   } catch (NoSuchFieldException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   } catch (ClassNotFoundException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   } catch (IllegalAccessException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   }
  }
 }

在webview的 destroy方法里 调用这个方法就行了。

11、另外很多人 不知道webview 实际上有自己一套完整的cookie机制的,利用好这个 可以大大增加对客户端的访问速度。

实际上cookie就是存放在这个表里的。

很多人都想要一个效果:网页更新cookie 设置完cookie以后 不刷新页面即可生效。这个在2.3以下和2.3以上要实现的方法不太一样,所以要做一次兼容

public void updateCookies(String url, String value) {
  if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { // 2.3及以下
   CookieSyncManager.createInstance(getContext().getApplicationContext());
  }
  CookieManager cookieManager = CookieManager.getInstance();
  cookieManager.setAcceptCookie(true);
  cookieManager.setCookie(url, value);
  if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
   CookieSyncManager.getInstance().sync();
  }
 }

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Android开发之WebView组件的使用解析

    在 Android 手机中内置了一款高性能 webkit 内核浏览器, SDK 中封装为一个叫做 WebView 组件. WebView 类是 WebKit 模块 Java 层的视图类,( 所有需要使用 Web 浏览功能的Android应用程序都要创建该视图对象显示和处理请求的网络资源.目前,WebKit 模块支持 HTTP.HTTPS.FTP 以及 javascript 请求. WebView 作为应用程序的 UI 接口,为用户提供了一系 列的网页浏览.用户交互接口,客户程序通过这些接口访问

  • Android中WebView图片实现自适应的方法

    本文实例讲述了Android中WebView图片实现自适应的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: WebSettings ws = tv.getSettings(); 加上这个属性后,html的图片就会以单列显示就不会变形占了别的位置 ws.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //让缩放显示的最小值为起始 webView.setInitialScale(5); // 设置支持缩放 webSettin

  • Android WebView使用的技巧与一些坑

    随着手机性能的提高,以及iOS和Android两个平台的普及,更多的App都会选择两个平台的App都进行开发,在有些时候,为了更加快速的开发,我们会采用hybird方式开发,这个时候我们需要使用webview并且自己进行一些配置.Android的webview在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了chrome,因此问题很多,这里分享一些我使用过程的一些技巧和遇到的坑. ###webview配置### mWebview.getSettings().setJavaScr

  • Android的webview支持HTML5的离线应用功能详细配置

    HTML5的离线应用功能可以使得WebApp即使在网络断开的情况下仍能正常使用,这是个非常有用的功能.近来工作中也要用到HTML5离线应用功能,由于是在Android平台上做,所以自然而然的选择Webview来解析网页.但如何使Webivew支持HTML5离线应用功能呢,经过反复摸索和上网查找资料,反复做试验终于成功了. 首先需配置webview的的一些属性,假设activity中已经有了一个Webview的实例对象,名为m_webview,然后增加以下代码: 复制代码 代码如下: WebSet

  • Android实现WebView删除缓存的方法

    本文实例讲述了Android实现WebView删除缓存的方法.分享给大家供大家参考.具体如下: 删除保存于手机上的缓存: // clear the cache before time numDays private int clearCacheFolder(File dir, long numDays) { int deletedFiles = 0; if (dir!= null && dir.isDirectory()) { try { for (File child:dir.listF

  • Android WebView那些坑之上传文件示例

    最近公司项目需要在WebView上调用手机系统相册来上传图片,开发过程中发现在很多机器上无法正常唤起系统相册来选择图片. 解决问题之前我们先来说说WebView上传文件的逻辑:当我们在Web页面上点击选择文件的控件(<input type="file">)时,会回调WebChromeClient下的openFileChooser()(5.0及以上系统回调onShowFileChooser()).这个时候我们在openFileChooser方法中通过Intent打开系统相册或

  • Android中WebView的基本配置与填坑记录大全

    前言 在应用程序开发过程中,经常会采用webview来展现某些界面,这样就可以不受发布版本控制,实时更新,遇到问题可以快速修复. 但是在Android开发中,由于Android版本分化严重,每一个版本针对webview都有部分更改,因此在开发过程中会遇到各种各样的坑,下面这篇就来给大家介绍关于Android中WebView的基本配置与填坑记录,话不多说了,来一起看看详细的介绍吧. 基本配置 // 硬件加速 getActivity().getWindow().setFlags( WindowMan

  • android中webview定位问题示例详解

    前言 现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝.京东.聚划算等等 京东首页 那么这种该如何实现呢?其实这是Android里一个叫WebView的组件实现的. 最近在做安卓的网页开发.有一个页面需要用到定位,但是一直定位获取失败.很难过.网上教程也很多,但是无一例外全部失败.最后老夫花了3天时间,呕心沥血,终于研制出了解决方案. 三步走战略: 一.获取权限 android 6.0 以后,需要动态的获取位置或者存储权限,按照各自的爱好放置位置.我是应用开启

  • Android中WebView控件支持地理位置定位方法

    Android WebView从assets中加载html5页面,实现地理位置定位,有需要的朋友可以参考下. 今天调研一个html5页面的定位问题,发现在手机浏览器上html5是可以实现定位的,但是在webview中就无法定位了.而我居然以为html5的地理定位在webview中不可行. html5页面内容如下: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.o

  • Android中WebView加载网页设置进度条

    本文实例为大家分享了Android中WebView加载网页设置进度条的具体代码,供大家参考,具体内容如下 效果: xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" a

  • Android中WebView用法实例分析

    本文实例讲述了Android中WebView用法.分享给大家供大家参考,具体如下: WebView相当于一个迷你浏览器,采用WebKit内核,因此完美支持html,javascript,css等. 在开发过程中应该注意几点: 1.AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错误. 2.如果访问的页面中有Javascript,则webview必须设置支持Javascri

  • Android中WebView的一些简单用法

    Android中WebView的一些简单用法 一直想写一个关于 WebView 控件的 一些简单运用,都没什么时间,这次也是挤出时间写的,里面的一些基础知识就等有时间再更新讲解一下,今天就先把项目出来做一些简单介绍,过多的内容可以看我的源码,都传到github上了. 下面是项目的效果图: 应用用到的是 MVP 设计模式,对这种模式还不太了解的可以先自行google一下,不然项目估计会看的晕,虽然我的代码都很简洁的. 对于MVP 可以带着一个思路看源码,那就是 activity(或其他组件)通过

  • Android中WebView与Js交互的实现方法

    获取WebView对象 调用WebView对象的getSettings()方法,获取WebSettings对象 调用WebSettings对象的setJavaScriptEnabled()方法,设置js可用,参数:布尔值 在判断是否支持js的时候,不要用alert(),默认不起作用,可以先用document.write()测试 调用WebView对象的addJavascriptInterface(obj, interfaceName)方法,添加js接口,参数:Object对象,String接口名

  • Android中webview与JS交互、互调方法实例详解

    Android中webview与JS交互.互调方法实例详解 前言: 对于试水的功能,一般公司都会采用H5的方式来开发,可以用很少的资源与很短的项目工期来完成. 但许多情况下,H5页面会需要一些原生持有的一些如用户信息之类的数据,一些交互也需要调用原生的,如toast之类要保持同一个手机风格一致的交互行为.这个时候就需要能够让JS主动调用原生的方法来进行操作或者获取数据.或者是原生调用JS的方法在H5加载的时候传递一些参数. 对于原生调用JS的方法 我们需要实现一个WebViewClient,在这

  • android中Webview实现截屏三种方式小结

    本人最近学习了android中Webview实现截屏三种方式,下面我来记录一下,有需要了解的朋友可参考.希望此文章对各位有所帮助. 第一种方式 通过调用webview.capturePicture(),得到一个picture对象,根据图像的宽和高创建一个Bitmap,再创建一个canvas,绑定bitmap,最后用picture去绘制. //获取Picture对象 Picture picture = wv_capture.capturePicture(); //得到图片的宽和高(没有reflec

随机推荐