Android:WebView全面总结

1 篇文章 0 订阅
1 篇文章 0 订阅

1.为何使用WebView?

我们先来探讨一下,为何好端端的一个app,嵌入了WebVIew这种控件。

WebVIew控件带来的好处:
  • 复用性高。 只需要写一次 HTML5 代码,就可以在 Android 和 iOS 平台上运行,这就是所谓的「 跨平台 」。
  • 动态更新。 由于页面是由HTML5实现的,出现的大部分改动问题,只需要修改服务器对应的HTML5页面,而不需要移动端重新打包编译上架。

但为什么它并没有被广泛地使用呢?

WebVIew控件使用的缺点:
  • 兼容性差。 由于Android版本碎片化严重,无法很好的向下兼容,运行效率不一。
  • 内存泄露。 webView内部的一些线程持有activity对象,导致activity无法释放。继而内存泄漏。
  • 加载速度慢。 加载速度比原生慢上许多,造成了不好的用户体验。
适用场景:
  • 简单的界面,不涉及复杂功能。 因为涉及到一些比较复杂的需求,依赖WebVIew,交互过多,对性能和兼容性的要求较高。

2.如何使用WebView?

2.1 基本用法

(1)获取网络权限

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

(2)XML文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
    <WebView
            android:id="@+id/wv"
            android:layout_width="match_parent"
             android:layout_height="300dp"/>

</LinearLayout>

(3)代码实现:

class WebViewActivity:Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_webview)
        wv.loadUrl("https://blog.csdn.net/QQ1010110087")
    }
}

(4)实现效果:
在这里插入图片描述

  • 点击其中的链接,默认会跳转到网页显示,而不是在WebVIew上直接显示。
原因
  • 不提供WebVIewClient,默认情况下,WebView将要求Activity Manager 为URL选择适合的处理程序。
  • 提供了WebVIewClient,如果shouldOverrideUrlLoading方法
    返回true,宿主应用程序处理URL,返回false,WebView处理URL

因此,在WebVIew上显示,需要设置WebViewClient对象

class WebViewActivity:Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_webview)
        wv.loadUrl("https://blog.csdn.net/QQ1010110087")
        //设置WebViewClient对象
        wv.webViewClient= WebViewClient() ;
    }
2.1.1 获取并显示标题栏
class WebViewActivity:Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_webview)
        wv.loadUrl("https://blog.csdn.net/QQ1010110087")
        
       //设置WebViewClient
        wv.webViewClient= WebViewClient() ;
        //设置WebChromeClient
        wv.webChromeClient = object : WebChromeClient() {
            //获取HTML标题
            override fun onReceivedTitle(view: WebView?, title: String?) {
                tvTitle.setText(title)
                super.onReceivedTitle(view, title)
            }
        }
    }
}
2.1.2 WebViewClient和WebChromeClient用法

我们在处理URL和获取标题栏,分别使用到了WebViewClient、WebChromeClient.

Android应用开发的时候可能会用到WebView这个组件,使用过程中可能会接触到WebViewClient与WebChromeClient,那么这两个类到底有什么不同呢?

WebViewClient主要帮助WebView处理各种通知、请求事件的,比如:

  • onLoadResource
  • onPageStart
  • onPageFinish
  • onReceiveError
  • onReceivedHttpAuthRequest

WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等比如

  • onCloseWindow(关闭WebView)
  • onCreateWindow()
  • onJsAlert (WebView上alert无效,需要定制WebChromeClient处理弹出)
  • onJsPrompt
  • onJsConfirm
  • onProgressChanged
  • onReceivedIcon
  • onReceivedTitle

看上去他们有很多不同,实际使用上:

  • 如果你的WebView只是用来处理一些html的页面内容,只用WebViewClient就行了。
  • 如果需要更丰富的处理效果,比如JS、进度条等,就要用到WebChromeClient。
2.1.3 WebViewClient和WebChromeClient简单使用
 wv.webViewClient = object : WebViewClient() {
            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                Log.v("WebViewActivity", "onPageStarted")
                super.onPageStarted(view, url, favicon)
            }

            override fun onPageFinished(view: WebView?, url: String?) {
                Log.v("WebViewActivity", "onPageFinished")
                super.onPageFinished(view, url)
            }
        }
  wv.webChromeClient = object : WebChromeClient() {
            //获取HTML标题
            override fun onReceivedTitle(view: WebView?, title: String?) {
                Log.v("WebViewActivity", "onReceivedTitle:title=" + title)
                super.onReceivedTitle(view, title)
            }
        }
  wv.loadUrl("https://blog.csdn.net/QQ1010110087")

打印日志:
在这里插入图片描述

2.2 WebView下载文件
        //允许与JS进行交互
        wv.settings.javaScriptEnabled=true
        //加载百度手机助手页面
        wv.loadUrl("https://shouji.baidu.com/appsearch/")
        //设置下载监听事件
        wv.setDownloadListener(object:DownloadListener{
            override fun onDownloadStart(
                url: String?,
                userAgent: String?,
                contentDisposition: String?,
                mimetype: String?,
                contentLength: Long
            ) {
            //限制加载文件为apk或带有.apk
                url?.run {
                    if(contains(".apk")){
                        val uri=Uri.parse(url)
                        //调用系统自带的下载界面
                        val intent=Intent(Intent.ACTION_VIEW,uri)
                        startActivity(intent)
                    }
                }

            }
        })
  • 在onDownloadStart方法中,我们也可以自己利用流去下载保存文件。
2.3 WebView与Js交互
2.3.1 Android调用Js方法
  • WebView的loadUrl()方法

html页面:

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>webview</title>
</head>

<body>

<p>Hello world! This is WebView Test</p>
<script> function callJs() {
  alert("调用js的callJs方法")
}
</script>

</body>

</html>

在app/src/main目录下,创建assets目录,复制这个html文件到这个目录下。

XML文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
    <TextView
            android:id="@+id/tvTitle"
            android:layout_width="match_parent"
            android:background="#3AA9F1"
            android:layout_height="40dp"
            android:gravity="center"
            android:textColor="#ffffff"
            tools:text="标题"/>
    <WebView
            android:id="@+id/wv"
            android:layout_width="match_parent"
            android:layout_height="300dp"/>
    <Button
            android:id="@+id/btCallJS"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="调用js方法"/>
</LinearLayout>

代码实现:

class WebViewActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_webview)
        /**
         * 调用Js方法
         */
        callJSMethod()
    }

    fun callJSMethod() {
        /**
         * file:///android_asset  代表app/src/main/assets这个目录
         */
        wv.loadUrl("file:///android_asset/index.html")
         //允许与Js交互
        wv.settings.javaScriptEnabled = true
        wv.settings.javaScriptCanOpenWindowsAutomatically = true
        wv.webChromeClient = object : WebChromeClient() {
            override fun onReceivedTitle(view: WebView?, title: String?) {
                super.onReceivedTitle(view, title)
                //设置标题栏标题
                tvTitle.setText(title)
            }
            //拦截Js的alert方法,可在该方法内重写alert的布局实现
            override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
                val alertDialog = AlertDialog.Builder(this@WebViewActivity)
                alertDialog.setTitle("onJsAlert")
                alertDialog.setMessage(message)
                alertDialog.setPositiveButton("确认", object : DialogInterface.OnClickListener {
                    override fun onClick(dialog: DialogInterface?, which: Int) {
                        //dialog.dismiss() 若调用这个方法而不调用result的confirm方法,会出现只能调用一次警告框的情况
                        result?.confirm()
                    }
                })
                alertDialog.setCancelable(false)
                alertDialog.show()
                return true
            }
        }
        btCallJS.setOnClickListener {
            wv.loadUrl("javascript:callJs()")
        }

    }

}

效果图:
在这里插入图片描述

  • 需要在每次调完onJsAlert后设置参数JsResult调用cancel()或者confirm()方法,否则再去调用时,警告框不会出现。
2.3.2 JS调用Android方法
  • WebView的addJavascriptInterface()方法 对象映射

addJavascriptInterface(obj:Object, interfaceName:String)

(1)HTML页面添加button回调android方法

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>webview</title>
</head>

<body>

<p>Hello world! This is WebView Test</p>
<button type="button"  style="width:150px;height:50px;" 
             onclick="javascript:callAndroidMethod();" >调用android方法</button>

<script> function callJs() {
  alert("调用js的callJs方法")
}
</script>

<script> function callAndroidMethod() {
  wvActivity.androidMethod("js处调用androidMethod方法")
}
</script>
</body>

</html>

(2)根据HTML中的对象名和对象方法设置对象名称和对象回调方法

class WebViewActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_webview)
   
        callAndroidSetting()
    }
    
    fun callAndroidSetting(){
        //对象为该activity,该activity对应html文件中wvActivity对象
        wv.settings.javaScriptEnabled=true
        wv.loadUrl("file:///android_asset/index.html")
        wv.addJavascriptInterface(this,"wvActivity")
    }

    @JavascriptInterface
    fun androidMethod(jsParams:String){
        Log.v("WebViewActivity","androidMethod:"+jsParams)
    }
    
}

(3)实现效果
在这里插入图片描述
点击Button,打印日志如下:

在这里插入图片描述

2.4 处理系统返回键

问题:系统返回键,调用的是Activity的finish方法,而不是页面的回退操作。

解决方案:Activity的onBackPressed方法中判断webview是否有上一个页面?

  • 有,则返回到上一个HTML页面。
  • 没有,则执行父类方法。
  override fun onBackPressed() {
        if (wv.canGoBack()) {
            wv.goBack()
        }else
            super.onBackPressed()
    }
2.4 WebView的Cookie处理
  • 获取CookieSyncManager
  CookieSyncManager.createInstance(this);
  CookieManager cookieManager = CookieManager.getInstance();
  cookieManager.setAcceptCookie(true);
  • 设置Cookie
  //帐号的cookie设置规则
  String mCookie = "wv.token=xxxxxxx";
  //设置Cookie
  cookieManager.setCookie(Url, mCookie);
  //同步Cookie
  CookieSyncManager.getInstance().sync();
  • 获取Cookie
  String mCookie = cookieManager.getCookie(Url);
  • 清除Cookie
  cookieManager.removeAllCookie();
  CookieSyncManager.getInstance().sync();
总结

后续待补充。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值