之前客户端加载H5时遇到了一些问题,我为了方便解决问题,所以将对应场景复刻到了Demo中,从之前的网络加载模拟为了本地加载Html的方式,但是没想到无意被一个基础知识点卡了一些时间,翻看往昔笔记发现未曾记录这种基础场景,故补不足,记录于此
关于 WebView
加载数据的几种方式,可以算是基础内容,相信大家都耳熟于心了,直接开讲
- 基础配置
- 加载方式
- 经常使用
- 较少遇到
- 实战场景
- 本地加载
- 远程加载
- 所遇问题
- 加载本地数据报 Not Found...
- 加载网络资源报 404、500、Not Found... 等
基础配置
关于 WebView
基础配置主要是对 WebSettings
相关属性的设置
简化版
WebView webView = (WebView) findViewById(R.id.webView);
WebSettings mWebSettings = webView.getSettings();
mWebSettings.setJavaScriptEnabled(true);
因为后续我们需要加载网络资源,所以有必要 添加一下网络权限
Tip
:如果仅加载本地资源,可不添加该权限… 但一个项目中不可能没有 INTERNET权限
!
<uses-permission android:name="android.permission.INTERNET" />
通用 xml 布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
加载方式
关于以下所有方式有的是经常使用的,也有的很少使用,当然还有一些我基本都没用过,没想到AI直接一起归总了,故我整合解释了一下,希望对你我有所帮助
WebView
加载数据的方式很多,但是我从业以来 用的最多的还是本地加载和网络加载
,所以这也是我们主讲的内容,关于其他加载方式先做记录,以后如果我遇到了类似场景再来补充实战感受
经常使用
插一句:在项目中有些富文本的样式也可以通过 Html实现,如果主要是看WebView,请忽略此句
本地加载 (加载本地 html文件)- 项目中会遇到一些组件需要固定的数据,有的成品数据就是html文件,所以有时候会用到这种方式
使用 loadUrl(String path)
方法加载本地文件,如 file:///android_asset/test.html
(自行定义html
文件名)
webView.loadUrl("file:///android_asset/test.html");
网络加载 (加载H5的URL)- 主流方式,项目中基本90%都用这种方式
使用 loadUrl(String url)
方法加载网络或本地文件的URL
webView.loadUrl("https://www.example.com");
在 WebView
实际使用中,我们经常会通过 WebViewClient
监听一些加载情况,以下是比较常用的两个重载监听方法
通过设置 WebViewClient 并重写 shouldOverrideUrlLoading
方法来控制URL加载行为
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
使用 WebResourceRequest
:在Android N(API 24)及以上版本,可以在 WebViewClient
中重写 shouldOverrideUrlLoading
方法的重载版本,接收 WebResourceRequest
参数
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
view.loadUrl(request.getUrl().toString());
return true;
}
});
较少遇到
加载HTML字符串(感觉这种方式相当于把html文件提到了代码内部,如果html比较多的话,可能不太适用
)
使用 loadData(String data, String mimeType, String encoding)
方法加载HTML字符串
String htmlData = "<html><head><title>Page Title</title></head><body>Hi, WebView!</body></html>";
webView.loadData(htmlData, "text/html; charset=UTF-8", "UTF-8");
加载JavaScript代码 (双端交互时调用H5的Js方法,前提的和H5确定过交互需求,否则无效,且有可能报错
)
使用 loadUrl(String js)
方法执行 JavaScript
代码。
String jsCode = "javascript:alert('Hello, world!');";
webView.loadUrl(jsCode);
加载数据并设置基础URL(可能类似URL组装效果,未使用过
)
使用 loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl)
加载HTML字符串,并可以设置基础URL
String baseUrl = "https://www.example.com";
String htmlData = "<html>...</html>";
webView.loadDataWithBaseURL(baseUrl, htmlData, "text/html", "UTF-8", null);
加载POST请求数据(可能类似URL组装效果,未使用过
)
使用 postUrl(String url, byte[] postData)
方法通过POST请求加载数据。
String url = "https://www.example.com/post";
byte[] postData = ...; // 你的POST数据
webView.postUrl(url, postData);
加载XML或HTML文件:可以将其作为字符串加载,然后解析(未见过该类需求,未使用过
)
实战场景
本地加载
WebView mWebView = (WebView) findViewById(R.id.wv1);
WebSettings mWebSettings = mWebView.getSettings();
mWebSettings.setJavaScriptEnabled(true);
mWebView.loadUrl("file:///android_asset/test.html");//工程目录assets test.html文件
mWebView.loadUrl("file:///android_asset/icon.png");//工程目录assets图片文件(未尝试过)
示例全码
package com.example.webviewproject
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private val mWebView: WebView by lazy {
findViewById<WebView>(R.id.webView)
}
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initWebView(mWebView)
//加载本地资源
mWebView.loadUrl("file:///android_asset/test.html");
// mWebView.loadUrl("file:///android_asset/web/test.html")
}
/**
* 初始化WebSettings配置
* */
private fun initWebView(mWebView: WebView) {
mWebView.clearCache(true)
mWebView.clearHistory()
val webSettings = mWebView.settings
webSettings.cacheMode = WebSettings.LOAD_DEFAULT
webSettings.domStorageEnabled = true
webSettings.javaScriptEnabled = true
webSettings.useWideViewPort = true
webSettings.loadWithOverviewMode = true
webSettings.builtInZoomControls = true
webSettings.displayZoomControls = false
webSettings.setSupportZoom(false)
webSettings.javaScriptCanOpenWindowsAutomatically = true
webSettings.allowFileAccess = true
webSettings.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS
// webSettings.setAppCacheEnabled(true);
// webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
// webSettings.setAppCachePath(this.getApplicationContext().getCacheDir().getAbsolutePath());
// webSettings.setUserAgentString(webSettings.getUserAgentString() + " ECTASR/1");
// mWebView.setWebChromeClient(new CustomerActivity.WebChromeClient());
// mWebView.webViewClient = WebViewClient()
mWebView.isFocusable = true
mWebView.isVerticalScrollBarEnabled = false
mWebView.isHorizontalScrollBarEnabled = false
mWebView.setOnLongClickListener { v: View? -> true }
}
}
远程加载
相比加载本地文件,远程加载 url
除了添加授权和加载数据源不同之外,示例层面没变动,主要还是功能方面有了更多的可能性和交互性
mWebView.loadUrl("http://www.baidu.com");
示例全码
package com.example.webviewproject
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private val mWebView: WebView by lazy {
findViewById<WebView>(R.id.webView)
}
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initWebView(mWebView)
//加载本地资源
mWebView.loadUrl("http://www.baidu.com")
}
/**
* 初始化WebSettings配置
* */
private fun initWebView(mWebView: WebView) {
mWebView.clearCache(true)
mWebView.clearHistory()
val webSettings = mWebView.settings
webSettings.cacheMode = WebSettings.LOAD_DEFAULT
webSettings.domStorageEnabled = true
webSettings.javaScriptEnabled = true
webSettings.useWideViewPort = true
webSettings.loadWithOverviewMode = true
webSettings.builtInZoomControls = true
webSettings.displayZoomControls = false
webSettings.setSupportZoom(false)
webSettings.javaScriptCanOpenWindowsAutomatically = true
webSettings.allowFileAccess = true
webSettings.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS
// webSettings.setAppCacheEnabled(true);
// webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
// webSettings.setAppCachePath(this.getApplicationContext().getCacheDir().getAbsolutePath());
// webSettings.setUserAgentString(webSettings.getUserAgentString() + " ECTASR/1");
// mWebView.setWebChromeClient(new CustomerActivity.WebChromeClient());
// mWebView.webViewClient = WebViewClient()
mWebView.isFocusable = true
mWebView.isVerticalScrollBarEnabled = false
mWebView.isHorizontalScrollBarEnabled = false
mWebView.setOnLongClickListener { v: View? -> true }
}
}
所遇问题
加载本地数据报 Not Found…
提前和你说一下,当你遇到这种问题,基本和我一样都是一个粗心的人儿!
- 关于 asserts 目录层级要求
关于通过对 WebView
加载本地Html的方式,这么多年来一直没有变过,但是我尝试多次,一直加载失败…
不清楚你是否也遇到了这样粗心的问题?关于存放html的文件需要放置于asserts目录内,而该目录是与 java、res 同级的目录文件,切勿放错了!
- 有心的朋友可能注意到了我在本地加载中注释了一行
mWebView.loadUrl("file:///android_asset/web/test.html")
,注意这里加载层级有没有多一层或者少一层之类的?
如下
加载网络资源报 404、500、Not Found… 等
- 首先将加载的链接放在游览器看是否可以正常加载?
- 是否添加了网络权限?
- 是否为https 的url?Android在9.0开始好像对安全有了提升,所以有此要求
- 项目中可以看一下另一端是否可正常加载,排除错误场景
- 项目中可以找返给你url的同事看看是否有错误地方,请教请教