1.基本使用     首先要添加网络权限 从Android9.0(API 28)开始默认不再支持直接load未加密的url,解决方法是在manifest 中application节点添加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中的代码:

     

     Title

     

webview示例

     

    

我们可以看到直接用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代码:

     Title

     

欢迎光临启舰的blog

     

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 {

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)

推荐链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: