加载本地
加载HTML文本
加载网页数据和本地文件合并后显示
src=>main=>assets
目录下创建news_top.html
和news_bottom.html
news_top.html
1 |
|
news_bottom.html
1 | </body> |
XML
1 | <WebView |
Activity
1 | fun initWebView(html: String) { |
中文乱码
使用 loadData
方法官方推荐的写法在部分手机上会中文乱码,即使指定utf-8
、gbk
、gb2312
也一样。
1 | webView.loadData(data, "text/html", "UTF -8"); |
解决方法
1 | webView.getSettings().setDefaultTextEncodingName("UTF -8");//设置默认为utf-8 |
官方真是坑啊!!!
Utils
1 | public class ZJFileUtils { |
加载本地HTML文件
xieyi.html
放在 src=>main=>assets
目录下
1 | fun initWebView() { |
加载URL
权限
application同级添加
1 | <uses-permission android:name="android.permission.INTERNET"/> |
application属性添加下面代码来允许http请求
1 | android:usesCleartextTraffic="true" |
模板
1 | <WebView |
加载网址
1 |
|
原生WebView
页面
1 |
|
Activity
引用
1 | import android.webkit.* |
代码
1 | import android.annotation.SuppressLint |
注意几点
拦截弹窗
1 | mWebView.webChromeClient = object : WebChromeClient() { |
拦截请求
1 | mWebView.webViewClient = object : WebViewClient() { |
加载中Dialog
1 | mWebView.webChromeClient = object : WebChromeClient() { |
注意
不建议在
onPageFinished
中调用,这个方法调用时页面未必加载完毕,并且可能被回调多次。建议在
onProgressChanged
回调中,并且进度为100的时候调用,进度100同样会被调用多次,所以我们要进行判断,保证加载中弹窗唯一。注入JS的时候尽管我们在JS执行返回的时候调用Webview显示,但仍会出现看到注入前的页面样式,所以这里延迟显示了。
Dialog不能通过当前页面的
onBackPressed
事件中取消,只能在dialog上进行监听事件。
显示进度条
1 | fun showProgress() { |
点击外部不隐藏
1 | progressDialog?.setCanceledOnTouchOutside(false) |
处理返回按键
1 | private var exitTime: Long = 0 |
返回首页
为了让返回按钮控制WebView“返回某一个指定页”,我处理了按钮消息并加入相关逻辑。
我需要在特定的时候调用WebView.clearHistory()
,不料clearHistory()
并未起作用。
原因是clearHistory()
只清除当前页之前的历史记录。
假设当前页面为A,我调用WebView.clearHistory()
然后loadUrl(B)
,接着回退还是会退到A。
所以正确的调用时机是在B完全载入之后再调用WebView.clearHistory()
1 | home_btn.setOnClickListener { |
刷新
1 | refresh_btn.setOnClickListener { |
注入脚本
隐藏元素
1 | function hide_dom(){ |
删除
1 | var remove_arr = [ |
其它
1 | var dom7 = document.querySelector(".comm-content-left"); |
注意
有时我们发现有些页面的跳转,虽然URL发生变化了,但是Android回调没有触发,这是因为页面内使用的hash跳转,这时候就只能使用JS监听了。
示例
1 | window.onhashchange = function () { |
禁用复制事件
1 | document.oncontextmenu = function (ev) { |
集成TBS
自带的webview使用起来很多网页不兼容,有很多坑,这里推荐使用TBS
https://x5.tencent.com/tbs/sdk.html
接入文档:https://x5.tencent.com/docs/access.html
SDK接入
jar包方式集成 您可将官网下载的jar包复制到您的App的libs目录,并且通过Add As Library的方式集成TBS SDK
Gradle方式集成 您可以在使用SDK的模块的dependencies中添加引用进行集成:
1 | api 'com.tencent.tbs:tbssdk:44085' |
添加权限
在您的AndroidManifest.xml增加如下权限:
1 | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> |
首次初始化冷启动优化
1 | import android.app.Activity; |
也可以在没有自定义UA的情况下,使用您的app打开网页
1 | http://soft.imtt.qq.com/browser/tes/feedback.html |
显示000000
表示加载的是系统内核,显示大于零的数字表示加载了x5内核(该数字是x5内核版本号)
增加Service声明
在AndroidManifest.xml中增加内核首次加载时优化Service声明。
该Service仅在TBS内核首次Dex加载时触发并执行dex2oat任务,任务完成后自动结束。
1
2
3
4
5<service
android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
android:label="dexopt"
android:process=":dexopt" >
</service>
替换
包名替换
将源码和XML里的系统包和类替换为SDK里的包和类,具体对应如下:
系统内核 | SDK内核 |
---|---|
android.webkit.ConsoleMessage | com.tencent.smtt.export.external.interfaces.ConsoleMessage |
android.webkit.CacheManager | com.tencent.smtt.sdk.CacheManager(deprecated) |
android.webkit.CookieManager | com.tencent.smtt.sdk.CookieManager |
android.webkit.CookieSyncManager | com.tencent.smtt.sdk.CookieSyncManager |
android.webkit.CustomViewCallback | com.tencent.smtt.export.external.interfaces.IX5WebChromeClient.CustomViewCallback |
android.webkit.DownloadListener | com.tencent.smtt.sdk.DownloadListener |
android.webkit.GeolocationPermissions | com.tencent.smtt.export.external.interfaces.GeolocationPermissionsCallback |
android.webkit.HttpAuthHandler | com.tencent.smtt.export.external.interfaces.HttpAuthHandler |
android.webkit.JsPromptResult | com.tencent.smtt.export.external.interfaces.JsPromptResult |
android.webkit.JsResult | com.tencent.smtt.export.external.interfaces.JsResult |
android.webkit.SslErrorHandler | com.tencent.smtt.export.external.interfaces.SslErrorHandler |
android.webkit.ValueCallback | com.tencent.smtt.sdk.ValueCallback |
android.webkit.WebBackForwardList | com.tencent.smtt.sdk.WebBackForwardList |
android.webkit.WebChromeClient | com.tencent.smtt.sdk.WebChromeClient |
android.webkit.WebHistoryItem | com.tencent.smtt.sdk.WebHistoryItem |
android.webkit.WebIconDatabase | com.tencent.smtt.sdk.WebIconDatabase |
android.webkit.WebResourceResponse | com.tencent.smtt.export.external.interfaces.WebResourceResponse |
android.webkit.WebSettings | com.tencent.smtt.sdk.WebSettings |
android.webkit.WebSettings.LayoutAlgorithm | com.tencent.smtt.sdk.WebSettings.LayoutAlgorithm |
android.webkit.WebStorage | com.tencent.smtt.sdk.WebStorage |
android.webkit.WebView | com.tencent.smtt.sdk.WebView |
android.webkit.WebViewClient | com.tencent.smtt.sdk.WebViewClient |
模板替换
布局xml里的声明也需要替换,例如:
1 | <com.tencent.smtt.sdk.WebView |
调用
1 |
|
JS注入
src/main
下添加assets
文件夹
添加m_inject.js文件
1 | var dom = document.getElementById("menu-btn"); |
工具类
1 | import android.content.Context; |
调用
1 | val jsstr = AndroidFileUtil.getFromAssets(this, "m_inject.js") |
我们可以在下面的回调中调用注入方法
1 | mWebView.setWebChromeClient(object : WebChromeClient() { |
返回上一页
1 | override fun onBackPressed() { |
申请权限
1 | private val REQUEST_EXTERNAL_STORAGE = 1 |