安卓开发基础技术——WebView加载网页

2,914 阅读4分钟

本文正在参加「金石计划 . 瓜分6万现金大奖」

前言

最近工作上需求变得简单,因为是接H5网页到APP展示,所以,内容不需要我们客户端去编写了,只需要将网页在APP内展示出来即可,所以用到了WebView(网页视图),正好聊聊工作上遇到的问题与解决方法,也正好更新一下本基础必备系列。

本篇就是说明如何用WebView去加载网页的,是基础但也是必须掌握的知识内容,下面就让我们看看WebView的用法。

正篇

基础用法

其实WebView的使用是十分简单的,和编辑视图(EditView)和文本视图(TextView)等大多数视图一样,首先我们需要将视图添加在Activity或Fragment的布局中,下面就是在XML布局中添加的Demo代码:

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

XML添加好后,我们还需要在Activity中去调用它的方法,代码如下:

class MainActivity : AppCompatActivity() {
    @SuppressLint("SetJavaScriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.webView.settings.javaScriptEnabled = true
        binding.webView.loadUrl("https://juejin.cn/")

    }
}

使用webView.settings.javaScriptEnabled可以确认是否使用Js交互,一般用到Js都给打开了,即置为true

我们访问的是网络资源,所以需要使用网络权限,在AndroidManifest.xml清单文件中添加上网络权限:

image.png

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

写好以上步骤的代码后运行就可以看到如下效果:

image.png

我们成功在App内访问了掘金网站,基础用法就结束了。

WebView的其他常用方法

说完WebView的一般使用方法,那我们也要看看其他在开发中常用的方法,开发中我们通常需要配合需求与服务端对网页的一些行为进行控制,比如H5网页加载的一些交互,所以下面我们就着重讲述这方面的方法。 本例子项目工程文件已经放在GitHub上,地址为:github.com/AndroidStud… ,下面是基于之前的Demo工程(详见 安卓UI设计开发——Material Design(BottomSheetDialogFragment篇) - 掘金 (juejin.cn))在ImageView上增加点击跳转事件到该WebView页面:

image.png image.png

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".WebViewTest">

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

</androidx.constraintlayout.widget.ConstraintLayout>

继续使用上面基础用法的XML用法,但在Activity中调用方法,代码如下:

class WebViewTest : AppCompatActivity() {

    private lateinit var binding: ActivityWebViewTestBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityWebViewTestBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initWeb()
    }

    private fun initWeb() {
        val setting = binding.vWebView.settings
        setting.javaScriptEnabled = true
        setting.javaScriptCanOpenWindowsAutomatically = true
        binding.vWebView.webChromeClient = object : WebChromeClient() {
            override fun onProgressChanged(view: WebView?, newProgress: Int) {
                Log.i("onPageStarted", "页面加载")
                super.onProgressChanged(view, newProgress)
            }

            override fun onShowFileChooser(
                webView: WebView?,
                filePathCallback: ValueCallback<Array<Uri>>?,
                fileChooserParams: FileChooserParams?
            ): Boolean {
                Log.i("onShowFileChooser", "文件处理")
                return true
            }
        }
        binding.vWebView.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(
                view: WebView?,
                request: WebResourceRequest?
            ): Boolean {
                Log.i("shouldOverrideUrl", "页面处理:" + view!!.url)
                return super.shouldOverrideUrlLoading(view, request)
            }

            override fun shouldInterceptRequest(
                view: WebView?,
                request: WebResourceRequest?
            ): WebResourceResponse? {
                return super.shouldInterceptRequest(view, request)
            }
        }
        loadWeb()
    }

    private fun loadWeb(){
        binding.vWebView.loadUrl("https://juejin.cn/")
    }


}

我们首先将之前写在Activity的WebView调用方法包装到initWeb()方法与loadWeb()方法里,然后在onCreate方法里调用initWeb()方法即可。

webChromeClient与webViewClient

在initWeb()方法中我们可以看到新增了webChromeClient与webViewClient方法,其中webChromeClient是用来帮助WebView处理各种Js的交互事件,比如上面代码中的:
onProgressChanged是用来获取网页的加载进度,可以控制进度的显示效果(比如可以在Webwiew布局下加一个ProgressBar,用来控制进度显示和进度动画样式等)
onShowFileChooser可以调用它来处理具有“file”输入类型的 HTML 表单,以响应用户按下“Select File”按钮,因为安卓现在调用相机需要权限所以一般需要在这个方法里添加用户权限的对话以获取权限从而再进行拍照等后续操作。

webViewClient中我们可以处理一些通知以及响应事件,在开发中我们经常会在其中使用*shouldOverrideUrlLoading()*方法用来处理加载网页时候的一些对URL的操作,即当 URL 即将加载到当前 WebView 的时候,让我们有机会进行控制。
如果未提供 WebViewClient,默认情况下 WebView 将要求 Activity Manager 为 URL 选择正常加载机制。
如果提供了 WebViewClient,则返回true会导致当前 WebView 中止加载 URL,而返回false会导致 WebView 照常继续加载 URL,我们就可以主动主动返回true来选择对URL操作,比如不用浏览器打开URL而是在当前WebView加载。

还有一点需要注意,目前shouldOverrideUrlLoading(WebView view, String url)方法已经废弃,需要采用上面的方法,不过在上面的代码中也给出了获取url的方法:

view!!.url

image.png

返回网页上一页与退出WebView

我们在WebView中通常访问网页会点击进入多页面访问,这时候我们返回通常需要的是返回上一页web页面而不是关闭整个网页,所以就有以下处理,调用WebView的goBack()方法:

override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
    if (keyCode == KeyEvent.KEYCODE_BACK && binding.vWebView.canGoBack()) {
        binding.vWebView.goBack();
        return true;
    }
    return super.onKeyDown(keyCode, event)
}

而在退出WebView是一定要记得销毁它,如下处理:

override fun onDestroy() {
    //加载空的
    binding.vWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
    //清楚历史记录,看情况
    binding.vWebView.clearHistory();
    //销毁
    binding.vWebView.destroy();
    super.onDestroy()
}

总结

以上就是WebView的基础使用方法和日常用到的方法,此外还有一些如onReceivedError() 方法用于页面加载错误更换提示之类的方法我们在文章中未提到,后续有关WebView还会慢慢添加到本文中,方便回顾与学习。