Ⅰ 安卓WebView详解 (三)--Webview的API及说明
android.view.ViewGroup
↳ android.widget.AbsoluteLayout
↳android.webkit.WebView
用于安卓显示网页内容
一、查找网页中匹配的字符串
1、void findAllAsync ( String find) 查滚悄找网页乱搭中匹配的字符串且高亮显示,此方法为异步方法,对应的结果会在 WebView.FindListener中回调
2、void findNext (boolean forward) 上下查找匹配字符串
3、void addJavascriptInterface ( Object object, String name) 将提供的Java对象注入到此WebView中
4、void autofill( SparseArray < AutofillValue > values) 自动填充该视图中虚拟子级的内容
5、boolean canGoBack () 获取此WebView是否具有后退历史记录项。
6、boolean canGoBackOrForward (int steps) 获取页面是大陪渣否可以前进或后退给定数量的步骤。
7、boolean canGoForward () 获取此WebView是否具有转发历史记录项。
8、void clearCache (boolean includeDiskFiles) 清除缓存
9、void clearClientCertPreferences ( Runnable onCleared) 清除响应于继续/取消客户端证书请求而存储的客户端证书首选项。
10、void clearFormData() 从当前关注的表单字段中删除自动完成弹出窗口(如果存在)。
11、void clearHistory () 告诉此WebView清除其内部后退/前进列表
Ⅱ Android WebView
启用JavaScript
定义Java接口,暴露方法给JavaScript
绑定一个命名为Android的接口给WebView,
在JavaScript中肆返使用这个接口
点击WebView中的链接的默认行为是启动默认浏览器打开这个URL。如果想要在自己的WebView中打开:
复写WebViewClient的shouldOverrideUrlLoading方法:
canGoBack()如果实际存在用户要访问的网页历史记录,则该方法返回true。同样,您可以使用纯搏canGoForward()检查是否存在转发历史记裂裤饥录。如果您不执行此检查,则一旦用户到达历史记录的末尾,goBack()或goForward()什么都不做。
WebSettings用来对WebView做各种设置, 你可以这样获取WebSettings:
<pre><code>
WebSettings webSettings = mWebView .getSettings();
</code></pre>
WebSettings的常见设置如下所示:
WebViewClient用来帮助WebView处理各种通知, 请求事件。我们通过继承WebViewClient并重载它的方法可以实现不同功能的定制。主要方法:
WebChromeClient用来帮助WebView处理JS的对话框、网址图标、网址标题和加载进度等。同样地, 通过继承WebChromeClient并重载它的方法也可以实现不同功能的定制, 如下所示:
Ⅲ Android 5.x 免 Root 升级系统 WebView
Android 的系统碎片化问题可以说是 Android 系统最大的硬伤了,自这个系统诞生以来十几年过去了,依然没能很好的解决,碎片化问题也是每个 Android 开发工程师心中的隐痛😂,每次处理系统碎片化带来的问题时,血压也能分分钟飙升到 200+,为了减轻其他同仁的痛苦以及此后再遇到类似问题能少踩几个坑,就之前的爬坑经历做个记录吧。
有关 WebieView 的重要性和其使用不是本文的重点,但是有几个相关的属性我们必须了解:
在Android4.4(API level 19)系统以前,Android使用了原生自带的Android Webkit内核,这个内核对HTML5的支持不是很好,现在使用4.4以下机子的也不多了,就不对这个内核做过多介绍了,有兴趣可以看下 这篇文章 。
从Android4.4系统开始,Chromium内核取代了Webkit内核,正式地接管了WebView的渲染工作。Chromium是一个开源的浏览器内核项目,基于Chromium开源项目修改实现的浏览器非常多,包括最着名的Chrome浏览器,以及一众国内浏览器(360浏览器、QQ浏览器等)。其中Chromium在Android上面的实现是 Android System WebView ^1 。
从Android5.0系统开始,WebView移植成了一个独立的apk,可以不依赖系统而独立存在和更新,我们可以在 系统->设置->Android System WebView 看到WebView的当前版本。
从Android7.0系统开始,如果系统安装了Chrome (version>51),那么Chrome将会直接为应用的WebView提供渲染,WebView版本会随着Chrome的更新而更新,用户也可以选择WebView的服务提供方(在开发者选项->WebView Implementation里),WebView可以脱离应用,在一个独立的沙盒进程中渲染页面(需要在开发者选项里打开) ^2 。
从Android8.0系统开始,默认开启WebView多进程模式,即WebView运行在独立的沙盒进程中 ^3 。―― 节选自 如何设计一个优雅健壮的Android WebView?(上)
WebView 的包名在 AOSP 中的值是 com.android.webview ,该值是在 AOSP 构建过程中编译的版本,也就是说它是和系统一起被编译出来的,由于大部分的第三方手机制造商都有自己的定制 ROM,所以包名也是不尽相同,比如 MIUI ROM 中它已经被改为 com.mi.webkit.core 。从 WebView 的版本历史中可以看到自 Android 5.0 开始 WebView 移植成了一个独立的 apk,可以不依赖系统而独立存在和更新,这时候起 WebView 的包名就正式改为 com.google.android.webview 了。
所以这就是为什么网上一堆人问为啥升级了一下系统 WebView ,App 内使用到 WebView 的地方或者是内置浏览器一碰就报 PackageManager$NameNotFoundException: com.google.android.webview 或者 PackageManager$NameNotFoundException: com.android.webview 之类的错误,这些问题在 Android 5.0 的机器上非常常见,因为你升级了 WebView 之后 TMD 包名都变了🤣,而 ROM 定制商一般在版本衔接时都很保守,所以即使系统升到了 Android 5.0 ,解决方案未必就是最新的,内置的 WebView 依然可能是硬编码进 ROM 的,所以系统环境引用的包名可能依旧是 com.android.webview ,你升级到 com.google.android.webview 它当然不认识了😂。
通过上面一通废话,你应该知道了,替换的坑就在如果你换上去的 WebView 包名和原内置的 WebView 包名不一致,就无法使用,所以就需要找一个包名一致的高版本 APK 了,还有一种方法是在系统目录某个配置文件里改个什么值,也就是包名引用,这样你就能换成任何包名的 APK 了,这个暂时没仔细研究,后续有结果了再更新。
APKMirror 是一个 APK 镜像站点,在这里可以找到很多 APK 的 release 版本以及历史版本,尤其 Google 全家桶系列的 APK 非常全,我们在这里根据需求直接搜索包名就可以了,我这里需要 com.android.webview ,检索到如下结果,可以看到这些都是从第三方 ROM 里提取出来的。
因为 Google 官方早在 WebView 40 的时候就已经将包名换成 com.google.android.webview 了,最新的是 72.xxx ,我翻了 15 页才找到最早改名并独立出来的那个版本😂。
adb connect 192.168.18.235
adb shell
su
mount -o rw,remount /system
这里原目录下的文件分别有 /webview/webview.apk 和 /webview/lib/arm/libwebviewchromium.so ,备份原目录:
cd /system/app
mv webview/ webview-b/
mkdir -p webview/lib/arm/
这里很简单,文件后缀 .apk 直接改成 .zip 然后解压缩,复制出 libwebviewchromium.so 即可
先上传文件到设备 /sdcard ,然后执行如下命令移动过去,和原路径以及原文件名保持一致即可。
mv /sdcard/xxx.apk /system/app/webview/webview.apk
mv /sdcard/xxx.so /system/app/webview/lib/arm/libwebviewchromium.so
cd /system/app/
chmod 777 webview/*
adb reboot
如上一顿操作,其实也没什么难度,主要的坑就是包名一致的问题,还有一些系统目录访问权限之类的问题,之前网上搜了好多,都说不 root 没法换,或者换了会出问题,root 权限其实就是为了访问和写入系统目录,通过重新挂载就解决了,换了会崩掉的问题其实就是历史遗留问题,从 4.x 过度到 5.0 WebView 独立了,所以包名变了,或者是 ROM 定制方不按套路来导致换上去的 WebView 不被系统识别,只要找到合适的包就解决了。
Ⅳ 如何控制了Android的WebView历史/后退堆栈
您的OnKeyDown应该像这些 @Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
myWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
Ⅳ android webview 有没有获取历史记录集合的方法
有的。mWebView.BackForwardList()这个是集合
mWebView.BackForwardList().getItemAtIndex(position).getUrl();position是int类型。这个是获取url。
我最近在做安卓浏览器,基本不用自带的,基本都是没打开一个网页存在本地数据库,用起来方便。
Ⅵ 如何清除参观一个Android的WebView的历史
1.覆盖和WebViewClient ......妈的这是隐藏的。
其实,我只好掏了一下,找到了这一点。
WebView webView = (WebView)findViewById(R.id.myWebView);
WebChromeClient myWebChromeClient = new WebChromeClient(){
@Override
public void getVisitedHistory(ValueCallback<String[]> callback) {
// called ring webview initialization, original implementation does strictly nothing
// and defaults to the native method WebViewCore.nativeProvideVisitedHistory()
String[] myUserHistory = (userId);
callback.onReceiveValue(myUserHistory);
}
};
WebViewClient myWebViewClient = new WebViewClient(){
@Override
public void doUpdateVisitedHistory(WebView view, String url,
boolean isReload) {
// called whenever there is a new link being visited
(userId);
super(view, url, isReload);
}
}
webView.setWebViewClient(myWebViewClient);
webView.setChromeClient(myWebChromeClient);
webView.getSettings().etc(whatever)...
我想我是“几乎没有”。下面塌链敏是我所管理的一部分:它做什么,到目前为止是完全去除CSS的历史,所以我们已经完成一半了。我不能让浏览器识别URL格式我提供的“myUserHistory”,所以实际上这个代码的唯一函数是重置的CSS历史干脆,但团枝一旦当web视图被实例化它只是调用(或创建的
CodeGo.net,没有检查),所以对于一个真正的经验,你就需要重新创建web视图在每次登录时。
我现在的问题是,我不能管理正常加载urlHistory。我的Xoom的web视图似乎忽略我的数据。
不错啊,我希望它为你工作。只是打电话callback.onReceiveValue(新的String []
{});在getVisitedHistory()就可以了。
编辑:
我只是把20多分钟就唤拿到,我是委托给(mCallbackProxy=
Ⅶ 关于Android WebView的那些事
[TOC]
Webkit是一个开源浏览器项目,其中,对Android开发者来说,或多或少的都有些接触。 在应用层来看,最经常使用无非这么几个类:WebView(Android中最为复杂,也是最为简单的一个View,继承自AbsoluteLayout),WebViewClient、WebChromeClient(作为回调控制类)、WebSettings(进行设置项的配置)等;Webkit内部包含了网络请求、页面渲染、Js引擎等等。在Android4.4之前的版本中,系统使用的是Webkit内核,其后,切换到Google的Chromium内核。本文主要介绍的是在Android中,如何使用Webkit进行H5页面的展现,以及常见问题的分析手段。
下面的内容抄自网络 & 乱七八糟的地方,简单了解一下。
<b><i>前面都是吹牛逼的信息,如何使用Webkit来更好的搬砖? 且听如下分解</i></b>
XML布局中丢一个 <WebView> 标签,然后再 Activity 或者 Fragment 中 findViewById ,进而 loadUrl ,一般也没人这么简单的用,除非写Demo。很简单,它就是一个Layout,提供了一个调用加载页面的接口,不写范例了,能看到这篇文章的都看过Google的API说明。
主要涉及到WebView和WebSettings两个类。
例如:
其实就是WebView的父类ViewGroup和View的方法,不多说了。不过需要注意的是,不是所有的View或ViewGroup的方法对WebView都生效。
列举几类常用的,几乎所有App的 WebView 都会设置的属性:
</br>
如何处理页面跳转以及特殊 Scheme
这个回调可以说是最容易出问题的一个回调,表示什么? 字面意思,让你重写这个URL 的loading,比如点击html打电话的一个 <a href=“tel:110”> 标签,作为一个有节操、有责任心的浏览器,你需要处理 H5常用的几个Scheme :
除此之外,还有各个应用自定义的scheme ,举个例子,支付宝的支付Scheme : alipay: 。 这里的返回值,就代表你有没有能力处理这个url,没有的话Webkit就默认处理了。
需要注意的是,这个回调的触发的绝大多数情况是点击页面的 <a href="xxxx"> a标签,在Android中 loadUrl("http://www..com") ,是不会回调的,为什么不会回调,各位自行理解吧。
超链接 <a> 标签怎么写: 点我
特别说下窗口常见的两种打开方式:
针对单页模式的WebView框架(所有的html窗口均使用同一个WebView实例),不需要关注target的。
如果作为一个成熟的浏览器框架的话,是需要支持Html、JavaScript使用新窗口打开页面,需要实现如下回调:
还有一个相关设置项: WebSettings.
此时,系统将不会再回调 shouldOverrideUrlLoading 。新窗口逻辑的具体实现机制,可以参考系统browser实现逻辑。
<b> 这里有个坑 </b>
Android 4.4版本 ,如果实现了onCreateWindow,也就是说页面 <a> 标签是这么写的: <a href="http://www..com" target="_blank"> ,点击此链接打开的新WebView窗口,此窗口中的url点击,是不会触发 shouldOverrideUrlLoading 。 这是刚替换成Chrominum内核出的一个bug。本人并没在新版本上验证是否已经修复。
另外,根据不同的Rom,底层实现是不一样的,有的ROM会帮你处理各种调起scheme,也就是startActivity,有的ROM点一个url,就会抛一个intent出来,让用户选择系统浏览器进行加载。
系统默认,提供了一个接口:
有什么安全隐患呢?
戳这里
如果不知道Js怎么写, 请戳我
用PC的截图意思一下,看出区别了吧。 这里确定、取消点击以后就得调用 JsResult、JsPromptResult 的 confirm或者cancel。
因为安全问题,大一些的App Native与Js通信都不再用 WebView.addJavascriptInterface(Object) 了,都改用JsPrompt,因为JsPrompt中有message、有JsPromptResult可以返回给Js一些信息,所以桥选中了JsPrompt,另一个备选方案是JsConsole。
大体有这么几种方式进行传递
具体方案实现时,多方面考虑使用何种方式。
还有一个比较牛逼的
系统源码中均有方法注释,怎么用自己看吧。
那么问题来了
查了下,只有这两个相关的:
WebBackForwardList BackForwardList()
void clearHistory()
系统提供的关于历史记录的操作并不多,因为,不支持单条删除啊,啊啊啊!
WebViewClient中,还有一个相关callback,当系统更新历史记录时回调:
void doUpdateVisitedHistory(WebView view, String url, boolean isReload)
<b>相关问题分析法:历史栈回退错误的定位</b>
绝大多数回退错误是由于接口调用、回调中逻辑执行时序错误。
定位方法:利用 BackForwardList , doUpdateVisitedHistory 两个接口在 loadUrl、onPageStart、onPageFinish 以及逻辑相关的地方调用,打log,查看历史栈,这里注意下由于loarl是异步的,需要考虑是否加延迟等等保证调用时机的准确。
本人曾经遇到一个问题:在WebChromeClient中的 JsPrompt回调中,直接进行WebView.goBack操作,结果发现WebView确实回退到上一个页面,但是BackFowardList当前页面的index未更新的问题,具体见另一个篇blog。
网上有很多关于WebView内存泄露的讨论,据传,老版本的WebView在展示大量图片的时候,即使 WebView.destory() WebView=null ,也不会销毁。
在新版本上,实际测试结果:compileSDKVersion 23 不会泄露。
一般,我们如何销毁WebView比较保险?
这个问题好大。。。
暂时不介绍,另起blog进行说明。
解决方案:
实现回调 void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
首先,提几个需要注意的点:
个人归纳总结几点:
step1 进入开发者模式,勾选“显示布局边界”;
step 2,回到你想查看的界面; step 3 假如内容区只有一层基本就是H5 WebView的,多个层级,就是Native。
看到左右图的差异了吧。
还有另一种方法,RD屌丝们看这里,特别说明,这种方法不太适合浏览器。 (自有内核,可能会不准确)
好了,就介绍到这里,零零散散的几年前写的文章,第一篇blog,如有不对的地方,还恳请大家指正。