javascript - 在 Android 的 WebView 中放宽 MIME 类型检查?或者强制常规javascript的模块类型?

标签 javascript android webview

我正在 Android 中开发和应用程序,其中有一段使用 javascript 和 python 编写的 Transcrypt (这几乎等同于说我正在直接用 javascript 开发该部分,但我无法完全控制事物的制作方式)。 Android 在带有 WebView 的 Activity 中显示该部分.启动它的相关java代码很简单

        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setAllowFileAccessFromFileURLs(true);
        webSettings.setAllowUniversalAccessFromFileURLs(true);
        mWebView.loadUrl("file:///android_asset/AndroidWebView.html");

AndroidWebView.html 的相关部分类似于 Transcript's demo for iOS
        <script type="module">
            import * as my_app from "./target/my_app.js"; window.my_app = my_app;
        </script>

该应用程序在模拟器上运行良好,但在真实设备上 WebView 拒绝加载 javascript 并吐出以下错误:
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.

如果我通过将 HTML 更改为强制 MIME 类型
        <script type="text/javascript">
            import * as my_app from "./target/my_app.js"; window.my_app = my_app;
        </script>

这似乎适用于我页面的其他纯 javascript 部分(不是模块),它显然失败了 Uncaught SyntaxError: Cannot use import statement outside a module .

有没有办法强制后一个 HTML 成为一个模块,或者前一个 HTML 不那么强烈地检查 MIME 类型?

看着options for WebView我看不到任何似乎相关的东西。环顾四周,这个问题似乎正是由 this bug 引起的。 .

另一方面,在我看来,问题在于 HTML script 的语法。接受类型的标记为 "text/javascript""module"但不能同时使用两者(我试过了,它似乎只使用了第一个),而从语义上讲,有理由同时拥有两者。是否有解决方法,甚至两者兼而有之?我知道一种可以加载 my_app.js 的技巧。 ,但该模块将无法进一步加载其他模块(my_app.js 确实如此)。因此,除非有转译器或能够自动将我的所有模块合并为一个的东西,否则这将不起作用。 FWIW,这些模块是从 Transcrypt 的 python 生成的,所以它必须是一个自动化的,而不是手动的过程。

PS:我不是 HTML 或 javascript 开发人员,这是我在这个领域的第一步,所以请不要怀疑我的猜测

PPS:我理解不在计算机上做任何这些,而是​​启动服务器的原因。这就是我为我的开发环境所做的。但是对于 Android 应用程序中的单个 Activity,HTTP 服务器似乎是一种矫枉过正和令人头疼的问题(跟踪端口、潜在的更多故障模式、可能在浏览器或其他应用程序中可见、额外的权限、额外的资源和电池使用,以及可能更多我没有想到的麻烦)。

最佳答案

有些事情你可以尝试。

1.
通过添加 <!DOCTYPE html> 确保它是 html 5到你的 index.html

2.
而不是使用 file://... 直接从系统加载文件,您可以使用 WebViewAssetLoader 这将返回 mimetype
https://developer.android.com/reference/kotlin/androidx/webkit/WebViewAssetLoader

3.
如果这在 webViewClient 中不起作用,您可以拦截请求并手动添加 text/javascript mimetype:

val webViewAssetLoader = WebViewAssetLoader.Builder()
        .addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(context!!))
        .build()

val webViewClient = object : WebViewClient() {

    override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest): WebResourceResponse? {
        val interceptedWebRequest = webViewAssetLoader.shouldInterceptRequest(request.url)
        interceptedWebRequest?.let {
            if (request.url.toString().endsWith("js", true)) {
                it.mimeType = "text/javascript"
            }
        }
        return interceptedWebRequest
    }
}

关于javascript - 在 Android 的 WebView 中放宽 MIME 类型检查?或者强制常规javascript的模块类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60588170/

相关文章:

javascript - 多次调用多次链接 Promise.all() 的最佳方法

javascript - 与 mongoose 类似的搜索文本(就像 sql 我们可以使用 like 查询)

javascript - ie8的js数组搜索功能

Android View 阴影

android - 自定义标题栏问题

android - WebView 和 HTML5 <视频>

qt - 在 QML Webview 中使用相对 url

cocoa - 如何在加载页面之前清除 WebView 的内容?

javascript - 如何创建多个Tooltips?

android - Renderscript 中的内存分配