Android中webview学习

news/2024/7/21 11:56:48 标签: android, 学习, harmonyos

1、什么是webview

WebView是Android中的原生UI控件,主要用于在app应用中方便地访问远程网页或本地html资源。同时,WebView也在Android中充当Java代码和JS代码之间交互的桥梁。实际上,也可以将WebView看做一个功能最小化的浏览器。WebView这个控件又包含四大部分:WebSettings、WebViewClient、WebChromeClient、JavascriptInterface。通过四个类,我们可以为WebView设置基础功能和监听。

2、webview的基本使用

添加网络权限
在AndroidManifest.xml中添加以下内容

<uses-permission android:name="android.permission.INTERNET" />

添加layout的xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

WebView一些常用的API,如加载url、前进后退、清理缓存、状态管理更新

      // 加载url:
      webView.loadUrl(url)

      // 往请求头header增加参数
      val hashMap: HashMap<String, String> = HashMap()
      hashMap["name"] = "zhangsan"
      webView.loadUrl(url, hashMap)

      // 加载 HTML 页面的一小段内容
      webView.loadData("", "text/html", "utf-8")
      webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null)

      // 后退、前进:
      webView.canGoBack() //是否可以后退
      webView.goBack() //后退一页面
      webView.canGoForward() //是否可以前进
      webView.goForward() //前进一页面
      webView.goBackOrForward(-1) //后退或前进多少步,正前负退

      //清除缓存数据:
      // 清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
      webView.clearCache(true)
      // 清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
      webView.clearHistory()
      // 这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据。
      webView.clearFormData()

      //WebView的状态
      webView.onResume() // 可见状态
      webView.onPause() // 页面失去焦点变成不可见状态
      webView.pauseTimers() // 页面失去焦点变成不可见状态,对整个应用的webview起作用
      webView.resumeTimers() //恢复pauseTimers时的动作
      webView.destroy() //销毁

接下来进入到最基本的使用

webView = (WebView) findViewById(R.id.webview);
//加载网页链接
webView.loadUrl("https://www.baidu.com");

3、webview的WebSettings

WebSettings类的主要作用是为H5设置一些配置功能,如常用设置是否支持JSjavaScriptEnabled、设置缓存cacheMode。

      webSetting = webView.settings

      // 告诉WebView启用JavaScript执行。
      webSetting?.javaScriptEnabled = true

      //缓存
      //缓存模式
      webSetting?.cacheMode = WebSettings.LOAD_DEFAULT
      // 开启 DOM storage API 功能
      webSetting?.domStorageEnabled = true
      //开启 database storage API 功能
      webSetting?.databaseEnabled = true
      //开启 Application Caches 功能,还需要设置路径
      webSetting?.setAppCacheEnabled(true)
      webSetting?.setAppCachePath("")

      //设置WebView是否应使用其屏幕上的缩放控件和手势支持缩放。
      //可以使用{@link #setBuiltInZoomControls}设置应使用的特定缩放机制。
      //此设置不会影响使用{@link WebView#zoomIn()}和{@link WebView#zoomOut()}方法执行的缩放。默认值为{@code true}。
      webSetting?.setSupportZoom(true)
      //设置WebView是否应使用其内置的缩放机制。内置的缩放机制包括屏幕缩放控件(显示在WebView的内容上)以及使用捏合手势控制缩放。可以使用{@link #setDisplayZoomControls}设置是否显示这些屏幕上的控件。默认值为{@code false}
      webSetting?.builtInZoomControls = false

      // 是否支持ViewPort的meta tag属性,
      // 如果页面有ViewPort meta tag 指定的宽度,则使用meta tag指定的值,否则默认使用宽屏的视图窗口
      webSetting?.useWideViewPort = true
      // 设置WebView是否以概述模式加载页面,即缩小内容以适合屏幕宽度。
      // 当内容宽度大于WebView控件的宽度时,例如{@link #getUseWideViewPort} 已启用。默认值为{@code false}
      webSetting?.loadWithOverviewMode = true

      //设置渲染线程的优先级。与其他设置不同,此设置每个过程仅需要调用一次。默认值为{@link RenderPriority#NORMAL}。
      webSetting?.setRenderPriority(WebSettings.RenderPriority.HIGH)

      // 设置基础布局算法。这将导致WebView的重新布局。默认值为{@link LayoutAlgorithm#NARROW_COLUMNS}。
      webSetting?.layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL
 
      //启用或禁用WebView中的文件访问。
      //请注意,这仅启用或禁用文件系统访问。仍然可以使用file:/// android_asset和file:/// android_res访问资产和资源。
      webSetting?.allowFileAccess = true

      //告诉WebView在调用{@link WebView#requestFocus(int,android.graphics.Rect)}时是否需要将节点设置为具有焦点。默认值为{@code true}。
      webSetting?.setNeedInitialFocus(true)

      //告诉JavaScript自动打开窗口。
      // 这适用于JavaScript函数{@code window.open()}。默认值为{@code false}
      webSetting?.javaScriptCanOpenWindowsAutomatically = true

      //支持自动加载图片
      webSetting?.loadsImagesAutomatically = true

      //设置解码html页面时使用的默认文本编码名称。 *默认值为“ UTF-8”。
      webSetting?.defaultTextEncodingName = "utf-8"

      // 设置默认字体大小。默认值为16。
      webSetting?.defaultFontSize = 16

      //设置最小字体大小。预设值为8。
      webSetting?.minimumFontSize = 8

      /**
       *  Webview在安卓5.0之前默认允许其加载混合网络协议内容
       *  在安卓5.0之后,默认不允许加载http与https混合内容,需要设置webview允许其加载混合网络协议内容
       */
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
          webSetting?.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
      }

      //获取WebView是否支持多个窗口。
      webSetting?.supportMultipleWindows()

4、webview的WebViewClient

WebViewClient的作用是处理各种通知和请求事件。比较常用的方法有shouldOverrideUrlLoading、onPageStarted、onPageFinished。

class BaseWebViewClient : WebViewClient {

  override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
      //在网页上的所有加载都经过这个方法
      //比如在本地WebView加载H5,而不是浏览器
      return super.shouldOverrideUrlLoading(view, request)
  }

  override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
      super.onPageStarted(view, url, favicon)
      //这个事件就是开始载入页面调用的,我们可以设定一个loading的页面,告诉用户程序在等待网络响应。
  }

  override fun onPageFinished(view: WebView?, url: String?) {
      super.onPageFinished(view, url)
      //在页面加载结束时调用。同样道理,我们可以关闭loading 条,切换程序动作。
  }

  override fun onReceivedError(
      view: WebView?,
      request: WebResourceRequest?,
      error: WebResourceError?
  ) {
      super.onReceivedError(view, request, error)
      // (报告错误信息,当加载出错的时候会回调此方法)
  }

  override fun shouldInterceptRequest(
      view: WebView?,
      request: WebResourceRequest?
  ): WebResourceResponse? {
      // 拦截替换网络请求数据
      return super.shouldInterceptRequest(view, request)
  }

  override fun shouldOverrideKeyEvent(view: WebView?, event: KeyEvent?): Boolean {
      //重写此方法才能够处理在浏览器中的按键事件。
      return super.shouldOverrideKeyEvent(view, event)
  }

  override fun onLoadResource(view: WebView?, url: String?) {
      super.onLoadResource(view, url)
      // 在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
  }

  override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
      super.doUpdateVisitedHistory(view, url, isReload)
      //(更新历史记录)
  }

  override fun onFormResubmission(view: WebView?, dontResend: Message?, resend: Message?) {
      super.onFormResubmission(view, dontResend, resend)
      //(应用程序重新请求网页数据)
  }

  override fun onReceivedHttpAuthRequest(
      view: WebView?,
      handler: HttpAuthHandler?,
      host: String?,
      realm: String?
  ) {
      super.onReceivedHttpAuthRequest(view, handler, host, realm)
      //(通知主机应用程序WebView收到HTTP身份验证请求。主机应用程序可以使用提供的* {@link HttpAuthHandler}设置WebView对请求的响应。 *默认行为是取消请求
  }

  override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
      super.onReceivedSslError(view, handler, error)
      //SSL过程发生错误,重写此方法可以让webview处理https请求。
  }

  override fun onScaleChanged(view: WebView?, oldScale: Float, newScale: Float) {
      super.onScaleChanged(view, oldScale, newScale)
      // (WebView缩放大小发生改变时调用)
  }

  override fun onUnhandledKeyEvent(view: WebView?, event: KeyEvent?) {
      super.onUnhandledKeyEvent(view, event)
      //(Key事件未被加载时调用)
  }

}

5、webview的WebChromeClient

WebChromeClient是内核处理类,主要用于网站的加载进度、标题、图片文件选择、JS弹窗

class BaseWebChromeClient : WebChromeClient {

  override fun onProgressChanged(view: WebView?, newProgress: Int) {
      super.onProgressChanged(view, newProgress)
      //当前网页加载的进度
  }

  override fun onReceivedTitle(view: WebView?, title: String?) {
      super.onReceivedTitle(view, title)
      //网页title标题
  }

  override fun onReceivedIcon(view: WebView?, icon: Bitmap?) {
      super.onReceivedIcon(view, icon)
      //网页图标
  }

  override fun onShowFileChooser(
      webView: WebView?,
      filePathCallback: ValueCallback<Array<Uri>>?,
      fileChooserParams: FileChooserParams?
  ): Boolean {
      //告诉客户端显示文件选择器。响应于用户按下“选择文件”按钮,调用它来处理具有“文件”输入类型的HTML表单。
      // 要取消请求,请调用<code> filePathCallback.onReceiveValue(null)</ code>并返回{@code true}。
      return super.onShowFileChooser(webView, filePathCallback, fileChooserParams)
  }

  override fun onShowCustomView(view: View?, callback: CustomViewCallback?) {
      super.onShowCustomView(view, callback)
      // 通知主机应用程序当前页面已进入全屏模式。调用之后,Web内容将不再在WebView中呈现,而是在{@code view}中呈现。
      // 主机应用程序应将此视图添加到配置了{@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN}标志的窗口中,以便实际全屏显示此Web内容。
  }

  override fun onHideCustomView() {
      super.onHideCustomView()
      // 通知主机应用程序当前页面已退出全屏模式。
      // 宿主应用程序必须隐藏自定义视图(以前传递给{@link #onShowCustomView(View,CustomViewCallback)onShowCustomView()}的视图)。调用之后,Web内容将再次在原始WebView中呈现
  }

  override fun getDefaultVideoPoster(): Bitmap? {
      //webview视频未播放时默认显示占位图
      return super.getDefaultVideoPoster()
  }

  //通知主机应用程序该网页要显示JavaScript {@code alert()}对话框。
  //<p>如果此方法返回{@code false}或未被覆盖,则默认行为是显示一个包含警报消息的对话框并挂起JavaScript的执行,直到关闭对话框为止。
  //<p>要显示自定义对话框,应用应通过此方法返回{@code true},在这种情况下,默认对话框将不会显示,并且JavaScript 执行将被暂停。
  // 该应调用{@code JsResult.confirm()}(关闭自定义对话框时),以便可以恢复执行JavaScript。
  //<p>要取消显示对话框并允许JavaScript执行继续,请立即调用{@code JsResult.confirm()},然后返回{@code true}。
  //<p>请注意,如果将{@link WebChromeClient}设置为{@code null},或者根本没有设置{@link WebChromeClient},则默认对话框将被取消,并且Javascript将立即继续执行。
  //<p>请注意,默认对话框不会从父窗口继承{@link android.view.Display#FLAG_SECURE}标志。
  override fun onJsAlert(
      view: WebView?,
      url: String?,
      message: String?,
      result: JsResult?
  ): Boolean {
      return super.onJsAlert(view, url, message, result)
  }

  // 通知主机应用程序该网页要显示JavaScript {@code Confirm()}对话框。
  //<p>如果此方法返回{@code false}或未重写,则默认行为是显示一个包含该消息的对话框并暂停JavaScript执行,直到该对话框被关闭为止。
  // 当用户按下“确认”按钮时,默认对话框将返回{@code true}到JavaScript {@code Confirm()}代码,而当用户按下“ cancel”时将返回{@code false}到JavaScript代码。 '按钮或关闭对话框。
  //<p>要显示自定义对话框,应用应通过此方法返回{@code true},在这种情况下,默认对话框将不会显示,并且JavaScript
  //执行将被暂停。该应用应调用 自定义对话框关闭时,{@ code JsResult.confirm()}或{@code JsResult.cancel()}。
  // <p>要取消显示对话框并允许JavaScript执行继续,请立即调用{@code JsResult.confirm()}或{@code JsResult.cancel()},然后返回{@code true}。
  //<p>请注意,如果将{@link WebChromeClient}设置为{@code null},或者根本没有设置{@link WebChromeClient},则会取消默认对话框,而默认值{@code false }将立即返回到JavaScript代码。
  //<p>请注意,默认对话框不会从父窗口继承{@link android.view.Display#FLAG_SECURE}标志。
  override fun onJsConfirm(
      view: WebView?,
      url: String?,
      message: String?,
      result: JsResult?
  ): Boolean {
      return super.onJsConfirm(view, url, message, result)
  }

  // 通知主机应用程序该网页要显示JavaScript {@code hint()}对话框。
  // <p>如果此方法返回{@code false}或未被覆盖,则默认行为是显示一个包含该消息的对话框并暂停JavaScript执行,直到该对话框被关闭为止。
  // 取消该对话框后,JavaScript {@code hint()}将返回用户键入的字符串,如果用户按下“取消”按钮,则返回null。
  //<p>要显示自定义对话框,应用应通过此方法返回{@code true},在这种情况下,默认对话框将不会显示,并且JavaScript 执行将被暂停。
  // 该应用应调用 取消自定义对话框后,{@ code JsPromptResult.confirm(result)}。
  //<p>要取消显示对话框并允许JavaScript执行继续,请立即调用{@code JsPromptResult.confirm(result)},然后返回{@code true}。
  //<p>请注意,如果将{@link WebChromeClient}设置为{@code null},或者根本没有设置{@link WebChromeClient},则默认对话框将被取消,并且将返回{@code null}立即添加到JavaScript代码。
  //<p>请注意,默认对话框不会从父窗口继承{@link android.view.Display#FLAG_SECURE}标志。
  override fun onJsPrompt(
      view: WebView?,
      url: String?,
      message: String?,
      defaultValue: String?,
      result: JsPromptResult?
  ): Boolean {
      return super.onJsPrompt(view, url, message, defaultValue, result)
  }

}

6、webview的JavascriptInterface

可以通过addJavascriptInterface()设置JavascriptInterface,从而使JS可以直接调用JavascriptInterface设置好的方法,比如H5想要跳转Activity、打开原生视频等都可以通知App。

  webView?.addJavascriptInterface(CommonWebJsInterface(), "className")

  val MSG_OPEN_ACTIVITY = 1

  var UIHandler: UIHandle = UIHandle()

  class UIHandle : Handler() {

      private var commonWebViewActivity: CommonWebViewActivity? = null

      private var jsonStr: String? = null

      fun setJsonStr(jsonStr: String?) {
          this.jsonStr = jsonStr
      }

      override fun handleMessage(msg: Message) {
          if (commonWebViewActivity == null || commonWebViewActivity?.isFinishing == true) {
              removeCallbacksAndMessages(null)
              return
          }
          commonWebViewActivity?.wrapHandleMessage(msg,jsonStr)
      }
  }

  private fun wrapHandleMessage(msg: Message?, jsonStr: String?) {
      msg ?: return
      if (msg.what == MSG_OPEN_ACTIVITY) {
          startActivity(Intent(this, WebViewActivity::class.java))
      }
  }

  inner class CommonWebJsInterface : WebJsInterface {

      // JS调用方法跳转Activity
      @JavascriptInterface
      override fun openActivity(jsonStr: String?) {
          UIHandler.setJsonStr(jsonStr)
          val msg = Message.obtain()
          msg.what = MSG_OPEN_ACTIVITY
          UIHandler.sendMessage(msg)
      }

      // JS调用方法播放视频
      @JavascriptInterface
      override fun playVideo(jsonStr: String?) {

      }

  }

  private interface WebJsInterface {

      @JavascriptInterface
      fun openActivity(jsonStr: String?)

      @JavascriptInterface
      fun playVideo(jsonStr: String?)

  }

7、最基本整合

  webView?.isEmpty() ?: return

  val webSettings = webView.settings

  webSettings.javaScriptEnabled = true //支持JS

  webSettings.useWideViewPort =
    true // 如果页面有ViewPort meta tag 指定的宽度,则使用meta tag指定的值,否则默认使用宽屏的视图窗口
  webSettings.loadWithOverviewMode =
    true //即缩小内容以适合屏幕宽度。当内容宽度大于WebView控件的宽度时,例如{@link #getUseWideViewPort} 已启用
  webView?.webViewClient = CommonWebViewClient(this)
  private class CommonWebViewClient(val context: Context) : WebViewClient() {

  override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
    url ?: return false
    try {
  	  if (!url.startsWith("http://") && !url.startsWith("https://")) {
  		  val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
  		  context.startActivity(intent)
  	  }
    } catch (e: Exception) {
  	  return true
    }
    return super.shouldOverrideUrlLoading(view, url)
  }

  webView?.webChromeClient = CommonWebChromeClient()
  private inner class CommonWebChromeClient : WebChromeClient() {

  // 网页加载的进度
  override fun onProgressChanged(view: WebView?, newProgress: Int) {
    if (newProgress >= 100) {
  	  // 隐藏Loading页面
    }
  }
  webView?.addJavascriptInterface(CommonWebJsInterface(), "className")

8、借鉴文章

https://www.jianshu.com/p/04025fc50d02
https://www.jianshu.com/p/170bce5ab83b


http://www.niftyadmin.cn/n/5337092.html

相关文章

编程笔记 html5cssjs 040 CSS盒子模型

编程笔记 html5&css&js 040 CSS盒子模型 一、CSS 盒子模型二、元素的宽度和高度三、最终元素的总宽度四、元素的总高度五、练习小结 网页是靠分成不同的块&#xff0c;再赋予这些块各不相同的属性来布局的。所以这个“块”是一个基础。先看块本身的构造。 一、CSS 盒子…

C++力扣题目435-无重叠区间 763--划分字母区间

435. 无重叠区间 力扣题目链接(opens new window) 给定一个区间的集合&#xff0c;找到需要移除区间的最小数量&#xff0c;使剩余区间互不重叠。 注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”&#xff0c;但没有相互重叠。 示例 1…

我在提交代码的时候突然发现别人刚才提交了一点代码,我没有拉取导致问题,请问怎么解决

问: 回答: 问: 我跟随输入git pull ,然后又以下提示: Merge branch systemPower_dev of https://xxxx.com into xxxx_dev # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. …

【2023我的编程之旅】七次不同的计算机二级考试经历分享

目录 我报考过的科目 第一次报考MS Office 第二次报考Web语言&#xff0c;C语言&#xff0c;C语言 第三次报考C语言&#xff0c;C语言&#xff0c;Java语言 分享一些备考二级的方法 一些需要注意的细节 结语 2023年的CSDN征文活动已经进入了尾声&#xff0c;在这最后我…

Hive添加第三方Jar包方式总结

一、在 Hive Shell中加入—add jar hdfs dfs -put HelloUDF-1.0.jar /tmp beeline -u "jdbc:hive2://test.bigdata.com:10000" -n "song" -p "" add jar hdfs:///tmp/HelloUDF-1.0.jar; create function HelloUDF as org.example.HelloUDF USIN…

golang二分查找算法实现

前言 项目中使用到有序数组查找特定元素&#xff0c;简单记录下Golang中二分查找算法。 目录 前言二分查找算法简介二分查找算法简单实现二分查找算法进阶使用1. 查找第一个或最后一个等于目标值的元素&#xff1a;2. 查找第一个大于或等于目标值的元素&#xff1a;3. 查找最后…

高级架构师是如何设计一个系统的?

架构师如何设计系统&#xff1f; 系统拆分 通过DDD领域模型&#xff0c;对服务进行拆分&#xff0c;将一个系统拆分为多个子系统&#xff0c;做成SpringCloud的微服务。微服务设计时要尽可能做到少扇出&#xff0c;多扇入&#xff0c;根据服务器的承载&#xff0c;进行客户端负…

Nginx安装配置

目录 准备工作 安装Nginx及相关组件 a、yum安装: b、tar安装: c、也可以yum安装pcre、zlib、openssl&#xff0c;tar安装nginx 启动Nginx 简单配置Nginx Nginx配置静态web服务器 Nginx实现负载均衡(不要使用刷新按钮,在地址栏回车) 1.负载均衡策略 2.配置Nginx的负载均衡与分发…