1.基本使用
    首先要添加网络权限<usespermission android:name=”android.permission.INTERNET”&gt;
从Android9.0(API 28)开始默认不再支持直接load加密url解决方法是在manifestapplication节点添加android:usesCleartextTraffic=”true

加载方式

webView.loadUrl("http://game.163.com")
val webSetting: WebSettings = webView.settings
webSetting.javaScriptEnabled = true

webView.webViewClient = object: WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
        url?.let { view?.loadUrl(it) }
        return super.shouldOverrideUrlLoading(view, url)
    }
}

如果不给webView.webViewClient赋值那么它会在浏览器打开这个网页,而不是在WebView中打开,如果是加载本地html文件需要file协议开头

webView.loadUrl("file:///android_asset/my.html")

注意加载本地html时不需要设置WebViewClient
还有几个方法

webSettings webSetting = mWebView.getSettings();
webSetting.setJavaScriptEnabled(true);//启用js
webSetting.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//优先使用缓存
//自适应屏幕
webSetting.setUseWideViewPort(true);
webSetting.setLoadWithOverviewMode(true);
webSetting.setSupportZoom(true);//支持缩放
webSetting.setBuiltInZoomControls(true);//设置出现缩放工具
webSetting.requestFocusFromTouch();//支持获取手势焦点

2.JS调用Android

Android代码

val webSettings = mWebView.getSettings() 
webSettings.javaScriptEnabled = true
webView.addJavascriptInterface(this, "android")
webView.loadUrl("file:///android_asset/web.html")

fun toastMessage(message: String) {
    Toast.makeText(applicationContext, "通过Natvie传递的Toast:$message", Toast.LENGTH_LONG).show()
}

js中的代码

<!DOCTYPE html>
<html lang="en">
<head>
     <meta charset="UTF-8">
     <title>Title</title>
     <h1>webview示例</h1>
     <input type="button" value="jsnative" onclick="ok()">
</head>
<body>
    <script type="text/javascript">
        function ok() {
            android.toastMessage("哈哈,i m webview msg");
        }
    </script>
</body>
</html>

我们可以看到直接用addJavaScriptInterface(this, “android“)把整个类作为对象传给了WebView,这个对象名为android”。但这样会有很大风险,一般我们不会直接传this,而是传入一个内部对象,而这个内部类是专门用来和js交互的:

inner class JsBridge {
    @JavascriptInterface
    fun toastMessage(message: String) {
        Toast.makeText(applicationContext, "通过Natvie传递的Toast:$message", Toast.LENGTH_LONG).show()
    }
}

注入方法:mWebView.addJavascriptInterface(new JSBridge(), “android“);   为了更好处理addJavascriptInterface()的安全性问题,在android4.2(17)之后只允许有@JavascriptInterface注解方法可以和js交互

3.Java调JS
JS代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
     <title>Title</title>
     <h1 id="h">欢迎光临启舰的blog</h1>
</head>
<body>
     <script type="text/javascript">
         function sum(i,m) {
             document.getElementById("h").innerHTML= (i+m);
         }
     </script>
</body>
</html>

Android调用代码

val webSettings = mWebView.getSettings()
webSettings.javaScriptEnabled = true
webView.loadUrl("file:///android_asset/web.html");
mBtn.setOnClickListener {
    webView.loadUrl("javascript:sum(3,8)")
}

如果js的方法返回值,要在java中搞到这个返回值要怎么做呢?Android4.4之后:
js:

function sum(i, m) {
    document.getElementById("h").innerHTML = (i + m);
    return i + m;
}

Android:

webView.evaluateJavascript("sum(i, m)", object: ValueCallback<String> {
    override fun onReceiveValue(p0: String?) {
        Log.i("TAG", "result: $p0")
    }
})

4.WebViewClient
这个类提供了一些加载网页时的回调方法

//在开始加载网页时会回调
public void onPageStarted(WebView view, String url, Bitmap favicon) 
//在结束加载网页时会回调
public void onPageFinished(WebView view, String url)
//拦截 url 跳转,在里边添加点击链接跳转或者操作
public boolean shouldOverrideUrlLoading(WebView view, String url)
//加载错误时候会回调,在其中可做错误处理比如请求加载一次或者提示404的错误页面
public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)
//当接收到https错误时,会回调此函数,在其中可以错误处理
public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)
//在每一次请求资源时,都会通过这个函数来回调
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
    return null;
}

另外通过重写shouldOverrideUrlLoading,可以实现对网页中超链接的拦截

webView.webViewClient = object: WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
        url?.let {
            if (it.contains("blog.csdn.net")) {
                view?.loadUrl("http://www.baidu.com");//在当前webview加载的url中包含blog.csdn.net”,则将其转换成”www.baidu.com”         
            } else {
                view?.loadUrl(it)
            }
            return true
        }
        return false
    }
}

而且如果是return true就告诉系统我们已经拦截了URL并进行了处理,不要再去加载默认的URL
所以要想在不满足条件的情况下继续加载原URL就必须手写else代码块重新加载原URL,如果不写
这个else判断,那么当前URL不满足if里面条件时他也不会去加载原URL,就会产生白屏。所以,一般我们建议使用return false; 这两段代码的效果是一样的:

webView.webViewClient = object: WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
        url?.let {
            if (it.contains("blog.csdn.net")) {
                view?.loadUrl("http://www.baidu.com");//在当前webview加载的url中包含blog.csdn.net”,则将其转换成”www.baidu.com”         
            }
            return false
        }
        return false
    }
}

5.webView内下载文件监听:DownloadListener

webview加载的html页面中如果发生下载文件事件就会触发DownloadListener响应,前提是必须webSettings.javaScriptEnabled置为true,否则点击下载按钮时候无法触发任何响应

webView.setDownloadListener { url, userAgent, contentDisposition, mimeType, contentLength ->
    Log.i("TAG", "url:$url n" +
                 "userAgent:$userAgent n" +
                 "contentDisposition:$contentDisposition n" +
                 "mimeType:$mimeType n" +
                 "contentLength:$contentLength")
    progressDialog.show()
    lifecycleScope.launch {
        if (url.endsWith(".apk")) {
            val msg = download(url)
            Toast.makeText(this@MainActivity, "$msg", Toast.LENGTH_SHORT).show()
//          val uri = Uri.parse(url) //或者直接跳系统下载进程
//          val intent = Intent(Intent.ACTION_VIEW, uri)
//          startActivity(intent)
        }
        progressDialog.dismiss()
    }
}

具体的下载逻辑

private suspend fun download(url: String): String {
    return withContext(Dispatchers.IO) {
        try {
            val httpUrl = URL(url)
            val conn = httpUrl.openConnection() as HttpURLConnection
            conn.doInput = true
            conn.readTimeout = 3000;//设置读取超时毫秒conn.connectTimeout = 3000;//设置连接超时毫秒val connIn = conn.inputStream
            val loadFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
            val apkFile = File(loadFile, "111.apk")
            val connOut = FileOutputStream(apkFile)
            val b = ByteArray(8 * 1024)
            var len = 0
            do {
                len = connIn.read(b)
                if (len != -1) {
                    connOut.write(b, 0, len)
                } else {
                    break
                }
            } while (true)
            connOut.close()
            connIn.close()
            "success!"
        } catch (e: Exception) {
            Log.e("TAG", "$e")
            "fail!"
        }
    }
}

6.返回
    如果用webview链接看了很多页以后,如果不做任何处理点击系统“Back”键,整个浏览器会调用finish()而结束自身,如果希望浏览的网页回退而不是退出浏览器需要在当前Activity中处理消费掉该Back事件覆盖Activity类的onKeyDown(int keyCoder,KeyEvent event)方法

override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
    //改写物理返回键的逻辑
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        if (webView.canGoBack()) {
            webView.goBack() //返回一页return true
        } else {
            exitProcess(0) //退出程序
        }
    }
    return super.onKeyDown(keyCode, event)
}

7.强制使用外部浏览器加载

val uri = Uri.parse("http://www.example.com")
val intent = Intent(Intent.ACTION_VIEW, uri)
startActivity(intent)

原文地址:https://blog.csdn.net/qq_37159335/article/details/125273562

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_48286.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注