Android-WebView加載本地Html,不能識別類型為module的JS

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 。

最終,我們的網頁就可以正常顯示了,完美!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容