Dav*_*ide 8 javascript android webview
我正在 Android 中开发应用程序,其中有一个使用Transcrypt用 javascript 和 python 编写的部分(这几乎与我直接用 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");
Run Code Online (Sandbox Code Playgroud)
相关部分AndroidWebView.html类似于Transcript 的 iOS 演示
<script type="module">
import * as my_app from "./target/my_app.js"; window.my_app = my_app;
</script>
Run Code Online (Sandbox Code Playgroud)
该应用程序在模拟器上运行良好,但在真实设备上 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.
Run Code Online (Sandbox Code Playgroud)
如果我通过将 HTML 更改为强制 MIME 类型
<script type="text/javascript">
import * as my_app from "./target/my_app.js"; window.my_app = my_app;
</script>
Run Code Online (Sandbox Code Playgroud)
这似乎适用于我的页面的其他部分,即普通的 javascript(不是模块),它显然会失败Uncaught SyntaxError: Cannot use import statement outside a module。
有没有办法强制后面的 HTML 成为一个模块,或者前面的 HTML 不那么严格地检查 MIME 类型?
查看WebView 的选项,我看不到任何相关的内容。环顾四周,这个问题似乎正是由这个错误引起的。
另一方面,在我看来,问题在于script接受类型的 HTML 标记的语法可以是其中之一"text/javascript","module"但不能同时是两者(我尝试过,它似乎只使用第一个),而从语义上讲,有两者都有的理由。是否有解决方法,或者甚至是两者兼得的黑客?我知道一种可以用于加载 的 hack my_app.js,但是该 hack 无法进一步加载其他模块(确实my_app.js如此)。因此,除非有一个转译器或能够自动将我的所有模块合并为一个的东西,否则这是行不通的。FWIW,这些模块是从 Transcrypt 的 python 生成的,所以它必须是一个自动化的过程,而不是手动的过程。
PS:我不是 HTML 或 javascript 开发人员,这些是我在这个领域的第一步,所以请善待我的猜测
PPS:我理解不在计算机上执行任何操作而是启动服务器的原因。这就是我为我的开发环境所做的。但对于 Android 应用程序中的单个 Activity,HTTP 服务器似乎是一种矫枉过正和令人头疼的问题(跟踪端口、潜在的更多故障模式、在浏览器或其他应用程序中可能可见、额外的权限、额外的资源和电池使用情况,以及可能还有更多我没有想到的麻烦)。
有些事情你可以尝试。
<!DOCTYPE html>1. 通过添加到你的index.html来确保它是html 5
2. 您可以使用 WebViewAssetLoader,而不是使用 file://... 直接从系统加载文件,这将返回 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
}
}
Run Code Online (Sandbox Code Playgroud)
我只是以更容易阅读的方式重述之前的答案(并且使用 Java 而不是 Kotlin)
不确定这是否重要,但最佳实践是通过添加来使用 html 5<!DOCTYPE html>
import androidx.webkit.WebViewAssetLoader;正如另一个问题中所述
强制使用正确的 MIME 类型,例如
mWebView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
WebResourceResponse intercepted = assetLoader.shouldInterceptRequest(request.getUrl());
if (request.getUrl().toString().endsWith("js")) {
if (intercepted != null) {
intercepted.setMimeType("text/javascript");
}
}
return intercepted;
}
});
Run Code Online (Sandbox Code Playgroud)
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.loadUrl("https://appassets.androidplatform.net/assets/AndroidWebView.html");
Run Code Online (Sandbox Code Playgroud)
请注意 HTTPS(而非文件)协议,并且缺少AllowFileAccessFromFileURLs
| 归档时间: |
|
| 查看次数: |
4337 次 |
| 最近记录: |