在日常的项目业务中,前端H5页面经常会频繁用到一些固定的资源,而且有时这个资源的文件相对比较大。H5页面加载的过程中,如果需要加载类似这种资源,就会非常影响页面的加载速度。
这时就需要把这些资源提前放到原生App本地,或者App预加载好。当H5页面需要加载这个资源时,通过制定的协议地址加载。App通过拦截资源加载地址进行判断,返回指定的资源响应。
以H5页面获取App的字体文件资源为例:
1、制定协议地址: myapp://native/resource?type=resourceType&name=resourceName
2、H5直接引用协议资源地址:
@font-face {
font-family: 'sans-serif';
src: url('myapp://native/resource?type=font&name=sans-serif');
font-weight: normal;
font-style: normal;
}
3、App的WebView复写onShouldInterceptRequest方法拦截:
override fun onShouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
val url = request?.url.toString()
if (url.startsWith("myapp://native/resource")) {
return WebRequestNativeResourceUtils.requestNativeResource(url)
}
return null
}
WebRequestNativeResourceUtils代码:
object WebRequestNativeResourceUtils {
private const val RESOURCE_KEY_TYPE = "type"
private const val RESOURCE_KEY_NAME = "name
private const val RESOURCE_TYPE_FONT = "font"
private const val RESOURCE_FONT_SAN_SERIF = "sans-serif
fun requestNativeResource(url: String): WebResourceResponse? {
val queries = URIHelper.getQueryMap(URI(url))
val resourceType = queries[RESOURCE_KEY_TYPE]
val resourceName = queries[RESOURCE_KEY_NAME]
return when (resourceType) {
RESOURCE_TYPE_FONT -> {
getFontResource(resourceName)
else -> {
null
}
}
private fun getFontResource(resourceName: String?): WebResourceResponse? {
var resourceStream: InputStream? = null
when (resourceName) {
RESOURCE_FONT_SAN_SERIF -> {
resourceStream = AppUtils.getAppContext().assets.open("fonts/SourceHanSerifCN-SemiBold.otf")
}
else -> {}
}
return resourceStream?.let {
val responseHeaders = java.util.HashMap<String, String>();
responseHeaders["Access-Control-Allow-Origin"] = "*";
WebResourceResponse("font/otf", "utf-8", 200, "ok", responseHeaders, it)
}
}
}