欢迎光临
专注android技术,聚焦行业精粹,我们一直在努力

带你解决 WebView 里的常见问题 webview常用代码合集

  1. 较全的webview坑点我们在使用webview时总比想象的要困难很多,涉及到兼容,手机差异,内存泄露等,这里整理了比较全的webview坑点和解决方案
  2. 持续收集,保持最新这里会持续收集,不断更新最新的最全的webview坑点和解决方案

1、前言

通常我们在自己开发的 APP 中打开网页无非两种方法: 一是跳转到系统自带的浏览器,二是使用 WebView 控件加载页面。使用 WebView 控件的好处就是可以通过各种 api 接口来定制各种行为,常用的几个设置地方为 WebSettingsJavaScriptInterfaceWebViewClient 和WebChromeClient。平时出现的问题都可以通过修改这些设置来解决。

2、问题总结

2.1、使用了 WebView 还是跳转到了系统自带的浏览器?

很简单的解决方法,为你的 webview 设置一个新的 WebViewClient。

2.2、获取网页的标题和图标

通过 WebChromeClient 可以获取到这些信息。

但是,这里有个问题,当通过 webView.goBack() 方式返回上一级Web页面的时候不会触发这个方法,因此会导致标题无法跟随历史记录返回上一级页面。所以需要在 onPageFinished() 中对界面标题重新设置。

2.3、返回键实现网页的后退键

在 WebView 中可以通过 goBack() 方法后退到历史记录的上一项。

2.4、设置 WebView 的 header

在 WebView 的 loadUrl() 方法中传入 Header 参数即可。

2.5、设置 WebView 的 User-Agent

不要试图在 Header 里面去修改,而是在 WebSettings 修改

2.6、如何设置 WebView 的缓存

当需要本地缓存网页的时候就需要打开 WebViewSettings 的缓存开关,这样子当下次进到该页面无网络的情况下也能打开页面。

2.7、无法下载文件?

在自己写的 WebView 下是无法直接下载文件,需要自己监听下载事件并对下载的动作进行处理

2.8、无法打开文件选择器?

通过重写 WebChromeClient 来实现点击 <input type='file'> 来打开系统文件选择器。

一个完整的Activity示例

2.9、怎么为 WebView 的加载添加进度条

这里的 onPageFinished() 有个问题,不能在这里监听页面是否加载完毕(我自己测试的时候,好像在重定向和加载完 iframes 时都会调用这个方法)。
把页面加载完毕的判断放在 onProgressChanged() 里可能会更为准确。

2.10、怎样对页面进行 Js 注入?

首先你要在 WebView 开启 JavaScript,然后搭建桥梁

WebAppBridge的代码

简单的说就是向网页注入一段 js, 在这段 js 里面设置回调到java中的方法 getResult(),由 WebAppBridge.getResult 来回收。
其中js的核心代码为:

其中 oauth 这个名称要与 webView.addJavascriptInterface()方法的第二个参数一样。

具体的代码可以参考这个项目中写的 js 注入逻辑 OauthDialog
地址:

https://github.com/cpacm/MoeMusic/blob/master/app/src/main/java/com/cpacm/moemusic/ui/widgets/dialogs/OauthDialog.java

2.11、如何手动添加 Cookie

需要获得 CookieManager 的对象并将 cookie 设置进去。
从服务器的返回头中取出 cookie 根据Http请求的客户端不同,获取 cookie 的方式也不同,请自行获取。

删除 Cookie 的方法

2.12、如何使 HTML5 video 在 WebView 全屏显示

当网页全屏播放视频时会调用 WebChromeClient.onShowCustomView() 方法,所以可以通过将 video 播放的视图全屏达到目的。

但是很多的手机版本在网页视频播放时是不会调用这个方法的,所以这个方法局限性很大。

另外还需要考虑全屏和非全屏时的屏幕方向:如果当前app是竖屏,全屏播放时需要设为屏幕方向为横屏;退出全屏播放时应该恢复为竖屏。如果应用本来就是横屏则可以不切换横竖屏

 

2.13、Android5.0上 WebView中Http和Https混合问题

2.14、如何避免 WebView 的内存泄露问题

  • 可以将 Webview 的 Activity 新起一个进程,结束的时候直接System.exit(0);退出当前进程;
  • 不在xml中定义 WebView,而是在代码中创建,使用 getApplicationgContext() 作为传递的 Conetext;
  • 在 Activity 销毁的时候,将 WebView 置空

方法二:

创建webview的时候把webview放在一个viewGroup里面,在destroy的时候从这个viewGroup里面移除,并通过调用webview的一些清理方法达到清缓存的目的,下面介绍了各个方法的使用和注意事项:

2.15、如何用端接管webview状态

详细参考这篇文章:Android-webview 如何用端接管webview状态

问题背景

  1. 我们用一个webview加载url时,在服务器响应远端数据之前,webview是空白的,我们期望这段时间显示一个端的loading
  2. webview加载出错后,页面展示不够友好,我们期望展示一个端的错误页面,包含“刷新”和“关闭”按钮

技术背景:

webview的生命周期对应以下几种方法:

可以看出webview默认没有我们想要的加载中、加载成功、加载失败的状态,如何接管这些状态呢?

webview提供了”开始加载”的起始点,我们想要拿到加载中,首先必须拿到“加载成功”和“加载失败”这两个状态,其中“加载失败”需要考虑url加载超时的场景。

以上代码示例处理了webview加载成功失败的状态的例子

2.16、页面适配手机分辨率,完整显示

  • setLoadWithOverviewMode(true) 设置WebView是否以概览模式加载页面,即缩小内容以适应屏幕宽度。
  • setUseWideViewPort(true) 如果为true则支持html里面的viewport标签,当设置的值为false时,不支持viewport标签,布局宽度始终设置为与设备无关(CSS)像素中的WebView控件的宽度。

想要支持viewport属性,并可以超屏自动缩放,可以如下配置:

一般情况下前端会在html里面配置viewport为一个适配手机屏幕的viewport值:

2.17、获取webview的UA

2.17.1、UA的作用

1) 在手机端/pc端,可以通过UA来判断不同的设备,从而可以显示不同的排版,进而给用户提供更好的体验
例如:用手机访问百度和pc端访问的页面排版是不一样的,这些就是百度根据访问者的UA来判断的。

2) 通过UA,进行信息统计,主要是用于渠道统计
例如:在之前的工作中碰到过类似情况,在app中接入广告的sdk,当用户点击广告图片时就需要通过webview进行详细广告页面的跳转,这时候就需要在webview中进行UA的自定义设置了,这样后台广告平台的人员就可以通过UA判断是哪个客户端(安卓/苹果),哪个浏览器的客户,进而进行客户端的统计。

2.17.2、UA的结构

2.17.3、UA 获取

如果当前没有可用的webview实例,例如在app启动时就需要拿到webview的ua,此时我们是没有webview实例的,可以构建一个webview实例然后获取,例如:

注意:以上代码处理了4.4的兼容问题,在4.4版本及之后的版本如果直接在非主线程new webview会导致以下的崩溃:

在4.4之后就不能在非主线程new Webview(ctx)了,不过官方文档中提供了处理方法,即使用WebSettings.getDefaultUserAgent(ctx)

If you need to retrieve the user agent but don’t need to store it for your app or do not want to instantiate WebView, you should use the static method, getDefaultUserAgent(). However, if you intend to override the user agent string in your WebView, you may instead want to use getUserAgentString().

原文地址:链接

2.17.4、自定义设置UA

1)在UA尾部增加字段

例如你可以增加这个字符串 “; platform/android; appversion/1.2.3”

2)替换 UA的值

2.18、H5页面卡死问题

遇到过支付宝H5页面卡死,无法滑动、无法输入的情况。有两种可能导致这个问题:

  • 调用了mWebView.pauseTimers()
  • 开启了硬件加速

2.18.1、调用了mWebView.pauseTimers()

该方法面向全局整个应用程序的webview,它会暂停所有webview的layout,parsing,JavaScript Timer。当程序进入后台时,该方法的调用可以降低CPU功耗。需要检查代码里面是否正确的调用了resumeTimers().

2.18.2、开启了硬件加速

webview开启了硬件加速后会有一些奇怪的问题,关闭硬件加速可以解决此问题。如何开启和关闭,参考这篇文章:链接

赞(1) 打赏
未经允许不得转载:花花鞋 » 带你解决 WebView 里的常见问题
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

国内精品Android技术社区

联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏