Android使用WebView开发常见的坑
Android WebView开发常见的坑
现在的App基本上都会使用Native+H5的方式来开发的,例如网易新闻详情页面,微信公号详情页面都会使用WebView开发。这样可以很容易实现图文排版的需求,而且混合开发的好处也是显而易见的。
AC在开发项目的时候也经常使用WebView这个控件,这个控件使用很方便,但却也有诸多问题。以下是AC在开发过程中踩过的坑,希望对使用这个控件的小伙伴们有用。
1、WebView无法显示html中的alert和confirm对话框
WebView要显示html中的alert和confirm对话框,需要实现WebViewChromClient接口。WebView只是一个承载体,各种内容的渲染需要使用WebviewChromClient去实现,所以set一个默认的基类WebChromeClient就行
mWebView.setWebChromeClient(new WebChromeClient());
用于弹起alert等,如果要定制alert,confirm对话框就必需重写onAlert和onConfirm方法
2、WebView中实现的JS方法无法调用
在实现WebView与JS交互的过程中,如果遇到点击后JS方法无响应,应该注意以下问题:
(1)WebView.addJavascriptInterface(new AndroidClick(), "app");这个方法的别名android是否与JS中的对象名称一致如
<div style="text-align:center;"><a onclick="window.app.onclick('www.115.com')" >内容已自动优化阅读,点击查看原文</a></div>
(2)如果是H5通过alert方法来提示对话框的信息的时候,WebView需要实现注册这个回调函数
mWebView.setWebChromeClient(new CustomWebChromeClient());
并实现以下alert回调方法,并可以实现自定义的对话框样式。
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
//return super.onJsAlert(view, url, message, result);
showConfirmDialog(view.getContext(), message, result, false);
return true;
}
类似的还有onJsConfirm方法等。
(3)如果发布的APP有进行混淆,那么AndroidClick这个JS 与 JAVA交互的类需要proguard.cfg文件忽略这个类的混淆,否则混淆后JS将执行不了。
-keepclassmembers class net.angrycode.js2java.AndroidClick{ *; }
(4)JS调用Native方法时,如果前端执行一些比较耗时的操作,前端代码就有可能会跑在线程里,这时候如果JS方法调用Native方法做一些逻辑操作,调用就会有问题,虽然不会Crash但是会报错。参考解决方法是(mJSInterface是通过addJavaInterface注入到WebView中的对象)
/**
* 提交创建申请单数据
*/
mJSInterface.setOnPutApplyListener(json -> {
mWebView.post(() -> {
//确保是在主线程中访问Native相关控件
});
});
3、快速打开和关闭WebView页面发生了控件空指针异常问题
这个问题可能有很多原因,但WebView加载过程中如果关闭了页面控件被回收而加载线程还在继续跑,那么数据返回时页面就有可能发生空指针异常。这个时候可以在WebViewClient以及WebViewChrome接口中的onPageStart以及onPageFinish,onProgressChange这几个回调方法中判断当前页面是否存在,若不存在则直接返回。
@Override
public void onPageFinished(WebView view, String url) {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
super.onPageFinished(view, url);
//...
}
4、WebView与JS交互引起的安全问题
4.2以下系统这里推荐一个开源项目https://github.com/pedant/safe-java-js-webview-bridge
当然WebView的安全不止这个,可以自行百度或者Google脑部相关姿势。AC也会在之后的文章中专门整理这个问题。
同时此问题在官方4.2(API Level 17)以上手机已经得到修复,使用@JavascriptInterface 注解声明addJavascriptInterface注入的方法。即只有使用@JavascriptInterface的方法才会被注入到WebView中。
5、WebView长按弹出ActionMode菜单样式问题
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDQzA1MTVGNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDQzA1MTYwNkE2MjExRTRBRjEzODVCM0Q0NEVFMjFBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkNDMDUxNUQ2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkNDMDUxNUU2QTYyMTFFNEFGMTM4NUIzRDQ0RUUyMUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6p+a6fAAAAD0lEQVR42mJ89/Y1QIABAAWXAsgVS/hWAAAAAElFTkSuQmCC" alt="" data-s="300,640" data-type="jpeg" data-src="http://mmbiz.qpic.cn/mmbiz_jpg/fWlPm6r6Bgm9rAXIB6iaictVOn62LJq6ykLddYf6JeBu3YFlk6Svzq9W0rhfmc4vrZMO8ZLZ9iamuRpoQo79afhiag/0?wx_fmt=jpeg" data-ratio="0.99125" data-w="800" />
三星手机WebView弹出的菜单样式有可能会出现此问题,解决方法可以继承WebView重写startActionMode()方法,然后修改menu的菜单样式。
@Override
public ActionMode startActionMode(ActionMode.Callback callback) {
return super.startActionMode(new CustomCallback(getContext(), callback));
} public static class CustomCallback implements ActionMode.Callback {
private ActionMode.Callback callback;
private Context context; public CustomCallback(Context context, ActionMode.Callback callback) {
this.callback = callback;
this.context = context;
} @Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return callback.onCreateActionMode(mode, menu);
} @Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
int size = menu.size();
for (int i = 0; i < size; i++) {
MenuItem menuItem = menu.getItem(i);
final Drawable moreMenuDrawable = menuItem.getIcon(); if (moreMenuDrawable != null) { menuItem.setIcon(DrawableUtil.getThemeDrawable(context, moreMenuDrawable)); }
}
return true;
} @Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return callback.onActionItemClicked(mode, item);
} @Override
public void onDestroyActionMode(ActionMode mode) {
callback.onDestroyActionMode(mode);
context = null;
}
}
当然如果不需要长按事件,可以注册WebView的长按事件
mWebView.setOnLongClickListener(v -> {
return true;
});
6、硬件加速问题
一般情况下,使用WebView开发都会使用硬件加速来提高WebView的渲染速度。可以在AndroidManifest.xml文件中设置
android:hardwareAccelerated="true"
也可以在页面中使用
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
但是简单的使用以上两种方法,开启硬件加速以及不开启硬件加速在一些手机上都会出现这样或者那样的问题,例如,如果一直开启了硬件加速,某些手机有可能会出现屏幕花屏的问题;还有WebView在不同厂商的手机中依然可能会出现Crash问题。而Crash的问题一般是报了WebView底层的错误。可以参考以下处理方式:
在onPageStart中开启硬件加速,在onPageFinish中关闭硬件加速。
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
if (getActivity() == null || getActivity().isFinishing()) {
return;
}
view.setLayerType(View.LAYER_TYPE_NONE, null);
super.onPageFinished(view, url);
}
7、使用独立进程跑WebView
有一定使用WebView经验的老司机可能都把项目中的WebView模块抽取出来,并跑在独立的进程中去。例如在manifest文件中使用属性process指定独立的进程。
<!-- Web 页面 -->
<activity
android:name=".UI.CommonUI.Activity.WebBrowserActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:hardwareAccelerated="true"
android:label=""
android:process=":web"
android:screenOrientation="portrait" />
这样做的是因为WebView在以前的版本的底层实现中会发生内存泄漏,导致页面关闭但是依然没有释放内存,而在独立进程中的WebView模块就可以很好解决此问题,在关闭WebView的时候就关闭进程,这样就可以释放相关的内存了。
但是使用多进程架构,进程间数据共享就是一个问题了。例如进程A设置了cookie,同样我也要在进程B共享这个cookie。目前AC认为可行的解决方案是使用ContentProvider来共享数据。此问题AC没有写相应的Demo,希望有老司机可以带路。
8、WebView生命周期回调
WebView也有生命周期回调方法,这些方法需要在Activity或Fragment相应的生命方法中回调。主要是onResume(),onPasuse()和onDestory()(或者onDestoryView())这几个方法的回调实现。
@Override
public void onResume() {
if (mWebView != null) {
mWebView.resumeTimers();
mWebView.onResume();
}
super.onResume();
} @Override
public void onPause() {
if (mWebView != null) {
mWebView.pauseTimers();
mWebView.onPause();
}
super.onPause();
}
@Override
public void onDestroyView() {
if (mWebView != null) {
mWebView.stopLoading();
((ViewGroup) mWebView.getParent()).removeView(mWebView);
mWebView.removeAllViews();
mWebView.setWebChromeClient(null);
mWebView.setWebViewClient(null);
unregisterForContextMenu(mWebView);
mWebView.destroy();
}
super.onDestroyView();
}
这几个方法的回调实现有利无弊,可以很好地避免翻车。例如WebView中播放声音在页面关闭之后还声音的问题,WebView页面跳转其他页面后返回显示空白不刷新的问题等等。
以上便是AngryCode在使用WebView开发过程中踩过的坑,相应解决方案纯粹是经验参考,因为使用环境以及能力的局限,如果文章出现错误,欢迎老司机留言指出。
Android使用WebView开发常见的坑的更多相关文章
- 微信浏览器H5开发常见的坑
ios端兼容input光标高度 问题详情描述: input输入框光标,在安卓手机上显示没有问题,但是在苹果手机上 当点击输入的时候,光标的高度和父盒子的高度一样.例如下图,左图是正常所期待的输入框光标 ...
- Android 之 WebView开发问题及优化
WebView 在现在的项目中使用的频率应该还是非常高的,WebView 主要用来加载一些容易改变的频繁交互的应用App.目前 HTML5 是一种趋势.在开发中会遇到一些开发问题及优化问题,如下所记. ...
- Android的WebView有哪些坑?
今天逛知乎的时候,看到一个有关Android应用开发中,WebView 的问题,算是开发中比较常见的问题了吧,而且赞同数比较多的答案,确实回答得还不错,这里小编就整理了一下,分享出来大家借鉴借鉴,避免 ...
- Android WebView编程的那些坑(一)
最大的坑是ROM不同,webkit不同,差异性很大.再加上google的坑,真是坑上加坑.比如js注入问题,比如client回调接口时序问题, 比如内存回收问题,etc 1.内存泄漏问题,尤其注意An ...
- Android中常见的坑有哪些?
对于安卓开发入门级程序猿而言,由于不熟悉代码.工具等等,掉进一些坑中是难免的,今天小编在网上看到一位大神总结的Android开发中比较常见的坑及其原因和解决办法,赶脚还不错,分享出来,给大家提个醒. ...
- (转载)android开发常见编程错误总结
首页 › 安卓开发 › android开发 android开发常见编程错误总结 泡在网上的日子 / 文 发表于2013-09-07 13:07 第771次阅读 android,异常 0 编辑推荐:稀 ...
- Android应用安全开发之浅谈加密算法的坑
<Android应用安全开发之浅谈加密算法的坑> 作者:阿里移动安全@伊樵,@舟海 阿里聚安全,一站式解决应用开发安全问题 Android开发中,难免会遇到需要加解密一些数据内 ...
- android webview开发问题及优化汇总
我们在native与网页相结合开发的过程中,难免会遇到关于WebView一些共通的问题.就我目前开发过程中遇到的问题以及最后得到的优化方案都将在这里列举出来.有些是老生常谈,有些则是个人摸索得出解决方 ...
- Android开发 |常见的内存泄漏问题及解决办法
在Android开发中,内存泄漏是比较常见的问题,有过一些Android编程经历的童鞋应该都遇到过,但为什么会出现内存泄漏呢?内存泄漏又有什么影响呢? 在Android程序开发中,当一个对象已经不需要 ...
随机推荐
- [转载]nginx负载均衡+keepalived三主(多主)配置
nginx负载均衡+keepalived三主(多主)配置 1.实验环境,实现目标三台主机分别配置nginx负载均衡对后端多台主机做转发,同时配置keepalived实现HA,保证任意主机出现故障时其他 ...
- windbg 配置符号路径
(转)WINDBG的符号下载与符号路径问题 安装与配置 windbg 的 symbol (符号) 本篇是新手自己写的一点心得.建议新手看看.同时希望前辈多多指教. 写这篇的动机:在网上找了一上午的 w ...
- 小埋的Dancing Line之旅:比赛题解&热身题题解
答疑帖: 赞助团队:UMR IT Team和洛谷大佬栖息地 赛后题解:更新了那两道练手题的题解 赛时公告,不过一些通知也可能在团队宣言里发出 如果各位发现重题,请将你认为重复的题目链接连同这次比赛的题 ...
- python 2.7 - 3.5 升级之路 (二) : 语法与类库升级
背景 在上一篇博文中,我们为升级python 2 -> 3已经做了一些准备.在这篇中,我们将针对语法与类库这两个方面进行讨论. 关于语法 1. print 在python3中, print 已经 ...
- 查询表格——建立动态表格,使用ajax输入查询条件将后台数据查询出来以表格的形式展示出来
建立动态表格,使用ajax将前台查询条件传给后台,并将查询结果以表格的形式展示出来. 页面的展示效果如下图所示: 第一步:查询条件的部分: 代码如下: <div class="text ...
- [剑指offer] 6. 旋转数组的最小数字
题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋 ...
- IOCP Input/Output Completion Port IO完成端口
I/O completion ports provide an efficient threading model for processing multiple asynchronous I/O r ...
- 【杂谈】如何对Redis进行原子操作
什么时候需要进行需要原子操作? 很常见的例子,就是利用Redis实现分布式锁. 实现锁需要哪些条件? 我们知道要实现锁,就需要一个改变锁状态的方法.这个方法能原子地对锁的状态进行检查并修改.如果修改成 ...
- Jenkins-slave分布式环境构建与并行WebUi自动化测试项目
前言 之前搭建过selenium grid的分布式环境,今天我们再来搭建一次Jenkins的分布式环境:jenkins-slave Jenkins的Master-Slave分布式架构主要是为了解决Je ...
- rabbitMQ_workQueue(二)
生产者发送多个消息到队列,由多个消费者消费. 如果一个消费者需要处理一个耗时的任务,那么队列中其他的任务将被迫等待这个消费者处理完成,所以为了避免这样的情况,可以建立对个消费者进行工作. 本例中使 ...