Android-WebView加载本地Html,不能识别类型为module的JS
背景
最近在做Android开发时遇到一个问题,就是在Android O上加载本地网页时出现无法显示的问题,并且在控制台看到有相关错误输出,如下:
Failed to load module script: The server responded with a non-JavaScript MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.
当看到这个错误时,就想到是本地的JS无法被WebView识别,果然,查看到本地JS类型为module。在一些高版本Android上这是可以被识别出来的,但是在一些低版本上就无法识别。因此,首先想到的就是采用Webkit提供的WebViewAssetLoader来解决该问题。
具体解决步骤
WebViewAssetLoader: 用于给WebView提供资源加载的,在WebViewClient中的方法shouldInterceptRequest中调用,如下:
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest
): WebResourceResponse? {
return webviewAssetLoader.shouldInterceptRequest(view, request)
}
但是,光这样是不能解决问题的,还需要配置WebViewAssetLoader,需要配置相关参数,如下:
private val webViewAssetLoader by lazy {
val fileRegex = "^file://".toRegex()
val httpRegex = "^http(s)?://".toRegex()
val resourcePath = HybridVersionManager.currentTemplatePath
WebViewAssetLoader.Builder().addPathHandler(
resourcePath.replace(fileRegex, "").plus(File.separatorChar),
when (resourcePath) {
HybridVersionManager.DefaultHybridPath ->
WebViewAssetLoader.AssetsPathHandler(context)
else -> WebViewAssetLoader.InternalStoragePathHandler(
context,
File(resourcePath.replace(fileRegex, ""))
)
}
)
.setHttpAllowed(true)
.setDomain(BuildConfig.BaseUrl.replace(httpRegex, ""))
.build()
}
这里讲一下为什么要配置HttpAllowed和Domain,那是因为WebViewAssetLoader是为Http(s)在线网页提供的本地资源的加载,但是这里我们的网页也是本地的,因此我们就需要把自己的网页也包装成一个在线网页,因此需要这个包装后的网页的域名与设置的域名一致,我们的shouldInterceptRequest也还需要做一下修改,如下:
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest
): WebResourceResponse? {
val newUrl = request.url?.run {
if (scheme == "file")
Uri.parse(
toString().replace(
"^file://".toRegex(),
BuildConfig.BaseUrl
)
)
else this
} ?: return super.shouldInterceptRequest(view, request)
return webViewAssetLoader.shouldInterceptRequest(newUrl)?.apply {
if (request.url?.path?.endsWith(".js", true) == true)
mimeType = "text/javascript"
}
}
以上代码,通过包装file,然后交给WebViewAssetLoader处理,通过Loader的匹配处理,然后就可以得到我们设置的本地资源了,因为我们还要处理JS的MimeType,还需要通过文件后缀判断得到JS文件,并为其设置新的类型:text/javascript 。
最终,我们的网页就可以正常显示了,完美!
网友评论