如何在Android原生WebView中运行Flutter Web并解决空白页问题
问题背景
尝试通过Android原生WebView展示Flutter Web应用时页面空白,代码如下:
class MainActivity : AppCompatActivity() { private lateinit var webView: WebView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.webview_test) webView = findViewById(R.id.webview) webView.settings.setJavaScriptEnabled(true) webView.loadUrl("http://localhost:5011/#/login") }
该应用在模拟器浏览器中运行正常,但WebView输出以下错误日志:
022-10-19 09:53:02.040 21184-21184/com.example.kotlinwebview
I/chromium: [INFO:CONSOLE(82)] "Loading app from service worker.",
source: http://localhost:5011/ (82) 2022-10-19 09:53:24.678
21184-21184/com.example.kotlinwebview I/chromium:
[INFO:CONSOLE(52119)] "registerExtension() from dart:developer is only
supported in build/run/test environments where the developer event
method hooks have been set.", source:
http://localhost:5011/dart_sdk.js (52119) 2022-10-19 09:53:25.370
21184-21184/com.example.kotlinwebview I/chromium:
[INFO:CONSOLE(52101)] "postEvent() from dart:developer is only
supported in build/run/test environments where the developer event
method hooks have been set.", source:
http://localhost:5011/dart_sdk.js (52101) 2022-10-19 09:53:25.453
21184-21184/com.example.kotlinwebview I/chromium: [INFO:CONSOLE(5067)]
"Uncaught (in promise) Error", source:
http://localhost:5011/dart_sdk.js (5067) 2022-10-19 09:53:25.453
21184-21184/com.example.kotlinwebview I/chromium: [INFO:CONSOLE(5067)]
"Uncaught (in promise) Error", source:
http://localhost:5011/dart_sdk.js (5067)
关键配置步骤
1. 补充WebView核心设置
仅启用JavaScript不足以支持Flutter Web,需添加以下配置:
webView.settings.apply { // 启用DOM存储,Flutter Web依赖此存储状态 domStorageEnabled = true // 启用数据库存储 databaseEnabled = true // Android 9+允许HTTP资源加载(如果使用开发服务器的HTTP地址) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW } // 可选:开启WebView调试,方便排查问题 WebView.setWebContentsDebuggingEnabled(true) }
2. 适配Service Worker加载
日志显示Flutter Web尝试通过Service Worker加载,WebView需特殊处理:
- 确保
AndroidManifest.xml已添加网络权限:<uses-permission android:name="android.permission.INTERNET" /> - 配置WebViewClient处理路由与加载错误:
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
request?.url?.let { view?.loadUrl(it.toString()) }
return true
}
// 处理Service Worker加载失败的情况,回退到直接加载页面 override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) { if (request?.isForMainFrame == true) { view?.loadUrl("http://localhost:5011/#/login") } }
}
- 设置缓存模式支持Service Worker: ```kotlin webView.settings.cacheMode = WebSettings.LOAD_DEFAULT
3. 规避开发者API兼容性问题
日志中的registerExtension()和postEvent()错误来自Flutter Web的开发者工具API,WebView不支持该API,解决方式:
- 构建Flutter Web生产版本:运行
flutter build web --release生成无开发者代码的生产包 - 使用生产包的URL替代开发服务器地址
4. 确保路由兼容
Flutter Web使用哈希路由(如/#/login)时,上述shouldOverrideUrlLoading配置已确保WebView不会拦截哈希路由请求,无需额外配置。
内容的提问来源于stack exchange,提问作者Stevanus Wijaya

