一级a做囗爰片免费网站,wordpress手机端导航栏,开发大型网站的流程,厦门市规划建设局网站一、简介 WebView是一个基于webkit引擎、展现web页面的控件。Android的Webview在低版本和高版本采用了不同的webkit版本内核#xff0c;4.4后直接使用了Chrome。 二、重要类 以WebView类为基础#xff0c;WebSettings、WebViewClient、WebChromeClient为辅助共同完成安卓段加…
一、简介 WebView是一个基于webkit引擎、展现web页面的控件。Android的Webview在低版本和高版本采用了不同的webkit版本内核4.4后直接使用了Chrome。 二、重要类 以WebView类为基础WebSettings、WebViewClient、WebChromeClient为辅助共同完成安卓段加载网页的操作。 1、WebView //1、加载网页相关//直接加载服务器网页my_web_view.loadUrl(https://www.baidu.com)//直接加载本地网页file:///android_asset/为固定写法my_web_view.loadUrl(file:///android_asset/1.html) // 缓存历史清理//Clears the resource cache. Note that the cache is per-application,// so this will clear the cache for all WebViews used.my_web_view.clearCache(true)// 清空历史本webView浏览的my_web_view.clearHistory()// 结合工具类my_web_view.webViewClient object : WebViewClient() // 设置webViewClientmy_web_view.webChromeClient object : WebChromeClient()// 设置WebChromeClient/*** 返回键处理网页中可返回上一页不处理返回键直接退出App* */override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {//when user press back code and canGoBackif (keyCode KeyEvent.KEYCODE_BACK my_web_view.canGoBack()) {my_web_view.goBack()return true}return super.onKeyDown(keyCode, event)}2、WebSettings /*** WebSettings类对webView 进行配置管理* */SuppressLint(SetJavaScriptEnabled, ObsoleteSdkInt)private fun webViewSettings() {val webSettings my_web_view.settings// js交互控制//支持js交互动画等操作会造成cpu、电量消耗可在activity、 fragment的onResume、onStop进行开关控制webSettings.javaScriptEnabled true // 适配webSettings.useWideViewPort true//自适应屏幕-自动将图片调整到自适应webView 大小webSettings.loadWithOverviewMode true//自适应屏幕-缩放到屏幕大小//缩放webSettings.setSupportZoom(true)//支持缩放默认为true。webSettings.builtInZoomControls true//设置是否展示内置的缩放控件默认为falsewebSettings.displayZoomControls true//显示原生的缩放控件//其他webSettings.allowFileAccess true // 可访问文件webSettings.javaScriptCanOpenWindowsAutomatically true // 支持js 自动打开新窗口webSettings.loadsImagesAutomatically true // 支持自动加载图片webSettings.defaultTextEncodingName UTF-8 // 默认值也是UTF-8//缓存控制webSettings.domStorageEnabled true // 开启dom缓存功能webSettings.databaseEnabled true // 开启数据库缓存功能webSettings.setAppCacheEnabled(true)// 开启application 缓存功能webSettings.cacheMode WebSettings.LOAD_CACHE_ELSE_NETWORK //设置缓存模式 LOAD_CACHE_ELSE_NETWORK有缓存时加载缓存即使缓存过期没有时从网络加载webSettings.setAppCachePath() // 设置app缓存目录api已弃用。// 5.1以上默认禁止了https和http混用,开启如下if (Build.VERSION.SDK_INT Build.VERSION_CODES.LOLLIPOP_MR1) {webSettings.mixedContentMode WebSettings.MIXED_CONTENT_ALWAYS_ALLOW}}3、WebViewClient 协助WebView工作有一些列回调方法用于处理各种通知 请求事件等。 my_web_view.webViewClient object : WebViewClient() {//加载url、返回false 代表使用webView 加载url 不使用系统浏览器。override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {// 如下loadUrlreturn true 这种也代表不使用系统浏览器。但是官方建议直接 return false// view?.loadUrl(https://www.baidu.com)// return truereturn false// 直接return false即可}// 页面加载时回调override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {super.onPageStarted(view, url, favicon)}// 页面加载完成时回调override fun onPageFinished(view: WebView?, url: String?) {super.onPageFinished(view, url)}// 加载页面资源时调用如页面上有好多图片没加载一张就会回调一次override fun onLoadResource(view: WebView?, url: String?) {super.onLoadResource(view, url)}// 加载页面时服务器出现错误例如404override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {super.onReceivedError(view, request, error)// todo 展示自定义html页面提示错误。}// 处理https请求override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {// 不要使用super否则有些手机访问不了因为包含了一条 handler.cancel()// super.onReceivedSslError(view, handler, error);// 接受所有网站的证书忽略SSL错误执行访问网页。这种方式在发生ssl不会影响网页加载。// 但是google play 认为这是不安全的操作。会给你警告。handler?.proceed() // handler?.cancel() // 发生ssl时挂起连接表现为白屏默认方式。}}4、WebChromeClient /*** WebChromeClient类辅助webView 处理js dialog、网站icon、网站title。* js的各种dialog事件触发时可由webChromeClient的响应方法回调到。* */private fun webChromeClient() {my_web_view.webChromeClient object : WebChromeClient() {// 获得网页进度时回调override fun onProgressChanged(view: WebView?, newProgress: Int) {super.onProgressChanged(view, newProgress)}// 获取网页的标题时回调override fun onReceivedTitle(view: WebView?, title: String?) {super.onReceivedTitle(view, title)}// 是否由客户端处理js Alert 事件true 代表客户端处理false 代表客户端不处理。// 一般客户端处理时客户端 展示对话框让用户进行选择override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {AlertDialog.Builder(mContext).setTitle(Title).setMessage(message).setPositiveButton(确定) { dialog, which -result?.confirm()}.setCancelable(false).show()return true}// js Confirm 对话框拦截true代表点击确定false 代表点击取消。override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {return super.onJsConfirm(view, url, message, result)}// 输入框拦截true 代表返回输入框的值false 代表返回nulloverride fun onJsPrompt(view: WebView?,url: String?,message: String?,defaultValue: String?,result: JsPromptResult?): Boolean {return super.onJsPrompt(view, url, message, defaultValue, result)}}}三、Android 调用 JS 代码
方式
webView的loadUrl( javascript:js方法())webView的evaluateJavascript
html
headmeta charsetUTF-8titleSunnyDay/title!--内部引入法--scriptfunction showAlertDialog(result){alert(i am js alert dialogi am js method!result)return i am js method!}/script
/head
bodyh3i am a simple html page/h3
/body
/html如上准备个1.html文件 1、webView#loadUrl 加载原理及其代码 借助webChromeClient 的各种回调处理。一般为js的各种dialog 方法触发时被安卓webViewClient的各种回调监听方法拦截消费。 webSettings web_view.settingswebSettings.javaScriptEnabled true//允许启用js功能webSettings.javaScriptCanOpenWindowsAutomatically true // 允许js弹窗// 加载Assets下html文件这时js代码也就载入了//加载assets文件夹下的html文件时使用固定格式语法即可file:///android_asset/文件名.htmlweb_view.loadUrl(file:///android_asset/1.html) web_view.webViewClient object : WebViewClient(){}callByLoadUrl()//webView只是载体内容的渲染需要使用webViewChromeClient类去实现,所以在这里写回调处理。web_view.webChromeClient object : WebChromeClient() {// 此方法可回调到alert警告框的信息。override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {val build AlertDialog.Builder(mContext).setTitle(Js showAlertDialog Method).setMessage(message).setPositiveButton(确定) { dialog, which -result?.confirm()}.setCancelable(false)build.create().show()return true}}/*** 方式1webView的loadUrl()* */private fun callByLoadUrl() {// 点击安卓按钮加载js方法btn_call_js_method.setOnClickListener {// 调用js时要保证网页加载完成否则js代码调用失败。因为html中也是页面加载完成才响应的js。web_view.loadUrl(javascript:showAlertDialog(\result\))}}2webView#evaluateJavascript webSettings web_view.settingswebSettings.javaScriptEnabled true//允许启用js功能webSettings.javaScriptCanOpenWindowsAutomatically true // 允许js弹窗// 加载Assets下html文件这时js代码也就载入了web_view.loadUrl(file:///android_asset/1.html)//加载assets文件夹下的html文件时使用固定格式语 法即可file:///android_asset/文件名.htmlweb_view.webViewClient object : WebViewClient(){}callByEvaluateJavascript()/***方式2webView的evaluateJavascript* js 方法无返回值时it为 null*/private fun callByEvaluateJavascript() {btn_call_js_method.setOnClickListener {web_view.evaluateJavascript(javascript:showAlertDialog()) {Log.d(AndroidCallJsActivity, it)//AndroidCallJsActivityi am js method!}}}3总结
/*** Android call js method practice* 两种方式* 1、webView的loadUri( javascript:js方法())* 这种方式一般调用的为js的dialog方法使用安卓的WebChromeClient 对应回调方法进行拦截处理。* 2、webView的evaluateJavascript* 直接调用js的方法还可以获得js方法返回值回调* js方法结果回调为String 类型值* js方法无返回值这里回调为null** 建议以这种方式既可快捷获得返回值又可通过1中的dialog回调处理。** 小结Android call js method* 安卓调用js方法后可以在安卓端获得结果回调处理。* */调用方式优点缺点适用场景loadUrl方便简洁效率低获取返回值麻烦不需要获取返回值时evaluateJavascript效率高安卓4.4以上才能使用安卓4.4以上
四、Js调用安卓代码
方式
通过webView的addJavascriptInterface方法通过重写webViewClient的shouldOverrideUrlLoading方法筛选url调用通过 WebChromeClient 的dialog 回调判断筛选url调用
html
headmeta charsetUTF-8titleSunnyDay/title!--内部引入法--script//方式1对象映射方式function callAndroid(){// 调用安卓的hello方法由于安卓中添加了对象映射test.hello()就相当于安卓的 //JsInterface().hello()test.hello( i am js code );}//方式2重写shouldOverrideUrlLoading 进行拦截function callAndroid2(){document.location js://webview?arg1111arg2222;}//方式3WebChromeClient 的 onJsAlert、onJsConfirm、onJsPrompt 方法回调拦截 JS 对话框function callAndroid3(){//1、首先搞个输入框触发时安卓可获得回调//2、收到回调后安卓处理点击确定返回输入框值点击取消返回nullvar resultprompt(js://demo?arg1111arg2222);alert(demo result);}/script
/head
body
h3i am a simple html page/h3
//方式1
button typebutton idbtn onclickcallAndroid()点我即可调用Android的hello方法/button
//方式2
button typebutton idbtn2 onclickcallAndroid2()方式2/button
//方式3
button typebutton idbutton3 onclickcallAndroid3()方式3/button/body
/html1、addJavascriptInterface
1定义对象映射方法 /*** 1、自定义对象用于对象映射* 2、自定义方法映射后供js对象使用* 3、方法必须加JavascriptInterface注解*/
class JsInterface {JavascriptInterfacefun hello(msg: String) {Log.d(JsCallAndroidActivity, android method hello is called:$msg)}
}2映射 //js调用安卓方法方式1webSettings web_view_th.settingswebSettings.javaScriptEnabled true//允许启用js功能webSettings.javaScriptCanOpenWindowsAutomatically true // 允许js弹窗web_view_th.loadUrl(file:///android_asset/2.html)// 定义对象映射把自定义的JsInterface映射给test,供js对象使用。web_view_th.addJavascriptInterface(JsInterface(), test)// 一行代码十分简单2、重写webViewClient的shouldOverrideUrlLoading方法 webSettings web_view_th.settingswebSettings.javaScriptEnabled true//允许启用js功能webSettings.javaScriptCanOpenWindowsAutomatically true // 允许js弹窗web_view_th.loadUrl(file:///android_asset/2.html)web_view_th.webViewClient object : WebViewClient() {override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {//view?.url //file:///android_asset/2.html //注意这里的两个url不相同 get的url为 webViewLoad的request的为动态定义的val requestUrl request?.urlLog.i(JsCallAndroidActivity, requestUrl) //js://webview?arg1111arg2222return if (requestUrl.toString() js://webview?arg1111arg2222) {// 符合筛选调用安卓方法。printLog()true} else {super.shouldOverrideUrlLoading(view, request)}}}private fun printLog() {Log.i(JsCallAndroidActivity, android methodprint log )}3、通过 WebChromeClient 的dialog 回调判断筛选url调用 webSettings web_view_th.settingswebSettings.javaScriptEnabled true//允许启用js功能webSettings.javaScriptCanOpenWindowsAutomatically true // 允许js弹窗web_view_th.loadUrl(file:///android_asset/2.html)web_view_th.webChromeClient object : WebChromeClient() {override fun onJsPrompt(view: WebView?,url: String?,message: String?,defaultValue: String?,result: JsPromptResult?): Boolean {val uri Uri.parse(message)if (js uri.scheme) {if (demo uri.authority) {result?.confirm(JS 调用了 Android 的方法)// 符合筛选调用安卓方法。printLog()}return true}return super.onJsPrompt(view, url, message, defaultValue, result)}}4、小结
/*** js call android method practise* 1、webView的addJavascriptInterface自定义对象“映射给的自定义字符串对象”* 这种方式最简单自定义对象内部定义一系列方法供js调用。js拿到映射对象即可调用安卓自定义的对象方法** 2、重写webViewClient的shouldOverrideUrlLoading方法筛选请求的url是否为js规定的url是规定的则调用安卓的相应方法。** 3、通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt方法回调拦截JS对话框alert()、confirm()、prompt原理与2一致。* */调用方式优点缺点适用场景WebView.addJavascriptInterface 对象映射方便简洁Android 4.2 一下存在漏洞Android 4.2 以上相对简单的应用场景WebViewClient.shouldOverrideUrlLoading 回调拦截不存在漏洞使用复杂需要协议约束不需要返回值情况下WebChormeClient.onJsAlert / onJsConfirm / onJsPrompt 方法回调拦截不存在漏洞使用复杂需要协议约束能满足大多数场景
五、Android 内嵌网页时登录状态同步方案
1、使用 WebView 和 Cookie 同步
Android 的 WebView 是一种能在应用中显示网页的组件。WebView 会自动处理 Cookies但为了确保登录状态的同步可能需要手动同步应用和 WebView 的 Cookies。
(1) 获取应用中的 Cookie
如果你的应用在登录后保存了 Cookie可以通过 CookieManager 来获取这些 Cookie。
(2) 将 Cookie 注入 WebView
在加载网页前将这些 Cookie 注入 WebView 的 CookieManager。
CookieManager cookieManager CookieManager.getInstance();
cookieManager.setAcceptCookie(true);// 获取应用的 Cookie假设名为 appCookie
String appCookie keyvalue; domainyourdomain.com;
cookieManager.setCookie(yourdomain.com, appCookie);// 加载网页
webView.loadUrl(https://yourdomain.com);(3) 确保同步 在 WebView 加载新页面时确保 Cookie 同步。
webView.setWebViewClient(new WebViewClient() {Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);CookieManager.getInstance().flush();}
});2、使用 Shared Preferences 和 JavaScript Bridge
这种方法可以通过 JavaScript 与 Android 应用交互保持登录状态同步。
(1)保存登录状态 登录后将登录状态例如 token保存到 Shared Preferences。
SharedPreferences sharedPref getSharedPreferences(MyApp, Context.MODE_PRIVATE);
SharedPreferences.Editor editor sharedPref.edit();
editor.putString(token, your_token);
editor.apply();
(2)设置 JavaScript 接口 在 WebView 中设置 JavaScript 接口用于获取登录状态。
webView.addJavascriptInterface(new Object() {JavascriptInterfacepublic String getToken() {SharedPreferences sharedPref getSharedPreferences(MyApp, Context.MODE_PRIVATE);return sharedPref.getString(token, );}
}, Android);(3)在网页中使用 在网页的 JavaScript 中调用这个接口获取登录状态。
function getToken() {return Android.getToken();
}// 在需要时调用 getToken()例如页面加载完成后
document.addEventListener(DOMContentLoaded, function() {var token getToken();if (token) {// 使用 token 做进一步处理}
});
3、使用 OAuth 进行单点登录SSO
如果你的应用和网页都支持 OAuth可以使用 OAuth 进行单点登录。
1在应用中获取 OAuth Token 用户在应用中登录后获取 OAuth Token 并保存。
2WebView 加载网页时附加 Token 在加载网页时将 Token 附加在 URL 或请求头中。
String url https://yourdomain.com?token oauthToken;
webView.loadUrl(url);// 或者设置请求头
webView.setWebViewClient(new WebViewClient() {Overridepublic WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {MapString, String headers new HashMap();headers.put(Authorization, Bearer oauthToken);request.setRequestHeaders(headers);return super.shouldInterceptRequest(view, request);}
});
4、使用统一的身份认证系统
如果你的应用和网页都使用统一的身份认证系统如 Firebase Authentication可以通过相同的身份认证机制同步登录状态。
1应用中登录 使用统一的身份认证系统登录并获取认证信息。
2WebView 中共享认证信息 通过与身份认证系统的集成在 WebView 中实现自动登录。
FirebaseAuth mAuth FirebaseAuth.getInstance();
FirebaseUser currentUser mAuth.getCurrentUser();if (currentUser ! null) {String idToken currentUser.getIdToken(false).getResult().getToken();String url https://yourdomain.com?token idToken;webView.loadUrl(url);
}
六、WebView相关优化建议
1、给 WebView 加一个加载进度条 为了友好展示重写 WebChromeClient 的 onProgressChanged 方法。未加载完成时展示loading进度条 2、提高 HTML 网页加载速度等页面 finsh 在加载图片
public void load () {if(Build.VERSION.SDK_INT 19) {webView.getSettings().setLoadsImagesAutomatically(true);} else {webView.getSettings().setLoadsImagesAutomatically(false);}
}3、onReceivedError 时加载自定义界面 web的error 页面比较丑我们可以在加载失败时展示安卓自定义的错误展示页。 4、动画、银屏、视频 合适加载释放 动画、银屏、视频 加载会造成cpu、电量消耗可在activity、 fragment的onResume、onStop进行开关控制。 七、收获
1、明文传输控制 Android P 阻止加载任何 http 的请求,在清单文件application节点 添加android:usesCleartextTraffic“true” 2、Android 5.0 之后 WebView 禁止加载 http 与 https 混合内容 。这样会造成某些资源加载失败。
if (Build.VERSION.SDK_INTBuild.VERSION_CODES.LOLLIPOP){webview.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);}/*例如https://www.aaa.com.cn/a/b/c/d/e/index.html?uid0011URLhttp://www.bbb.com.cn/1.png 这个url1、实际页面为https://www.aaa.com.cn/a/b/c/d/e/index.html 后面追加了一些参数2、h5页面上src标签加载http://www.bbb.com.cn/1.png此时你使用webview.loadUrl(https://www.aaa.com.cn/a/b/c/d/e/index.html?uid0011URLhttp://www.bbb.com.cn/1.png) 就会出现h5 图片显示失败。解决方案开启MixedContentMode*/3、硬件加速开启导致问题 比如不能打开 PDF播放视频花屏等等。关闭硬件加速。 4、重写webViewClient的shouldOverrideUrlLoading 否则系统不知道你是想用webview打开url 还是使用系统浏览器。 5、WebView白屏问题 原因页面进度不到100%时显示的就是白屏进度到100时开始加载网页资源。 解决:网上方案较多这里提示一种进度不到100时展示加载提示。 The end
官方文档
练习