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 。
最終,我們的網頁就可以正常顯示了,完美!