Flutter Web集成Firebase报错:Android正常Web端启动崩溃
Flutter应用在Android设备运行正常,但Web端启动时崩溃,抛出以下错误:
Exception has occurred. "Error: Invalid argument(s): object cannot be a num, string, bool, or null
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/internal/js_dev_runtime/private/ddc_runtime/errors.dart
266:49 throw
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart
43:7 fromBrowserObject
packages/firebase_core_web/src/firebase_core_web.dart 64:20
get [_ignoredServiceScripts]
packages/firebase_core_web/src/firebase_core_web.dart 115:28
_initializeCore C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
84:54 runBody
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
123:5 _async
packages/firebase_core_web/src/firebase_core_web.dart 107:31
[_initializeCore]
packages/firebase_core_web/src/firebase_core_web.dart 149:11
initializeApp
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
84:54 runBody
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
123:5 _async
packages/firebase_core_web/src/firebase_core_web.dart 145:44
initializeApp packages/firebase_core/src/firebase.dart 40:47
initializeApp
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
84:54 runBody
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
123:5 _async packages/firebase_core/src/firebase.dart
36:43
initializeApp packages/afterdefence_web/main.dart 31:18
main
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
84:54 runBody
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
123:5 _async packages/afterdefence_web/main.dart 19:18
main$ web_entrypoint.dart 24:31C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
334:14 _checkAndCall
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
339:39 dcall
C:/b/s/w/ir/cache/builder/src/out/host_debug/flutter_web_sdk/lib/ui/initialization.dart
77:15
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
45:50
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart
1653:54 runUnary
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart
147:18 handleValue
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart
766:44 handleValueCallback
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart
795:13 _propagateToListeners
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart
566:5 [_completeWithValue]
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart
639:7 callback
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/schedule_microtask.dart
40:11 _microtaskLoop
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/schedule_microtask.dart
49:5 _startMicrotaskLoop
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
166:15 "
应用的main函数代码:
Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await FirebaseAppCheck.instance.activate( webRecaptchaSiteKey: 'recaptcha-v3-site-key', ); runApp(const MyApp()); }
Web端的index.html代码:
<!DOCTYPE html> <html> <head> <!-- If you are serving your web app in a path other than the root, change the href value below to reflect the base path you are serving from. The path provided below has to start and end with a slash "/" in order for it to work correctly. For more details: * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base This is a placeholder for base href that will be replaced by the value of the `--base-href` argument provided to `flutter build`. --> <base href="$FLUTTER_BASE_HREF"> <meta charset="UTF-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="description" content="A new Flutter project."> <!-- iOS meta tags & icons --> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-title" content="afterdefence_web"> <link rel="apple-touch-icon" href="icons/Icon-192.png"> <!-- Favicon --> <link rel="icon" type="image/png" href="favicon.png" /> <title>AfterDefence Web</title> <link rel="manifest" href="manifest.json"> <script> // The value below is injected by flutter build, do not touch. var serviceWorkerVersion = null; </script> <!-- This script adds the flutter initialization JS code --> <script src="flutter.js" defer></script> </head> <body> <script type="module"> // Import the functions you need from the SDKs you need import { initializeApp } from "https://www.gstatic.com/firebasejs/9.9.4/firebase-app.js"; import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.9.4/firebase-analytics.js"; // TODO: Add SDKs for Firebase products that you want to use // https://firebase.google.com/docs/web/setup#available-libraries // Your web app's Firebase configuration // For Firebase JS SDK v7.20.0 and later, measurementId is optional const firebaseConfig = { apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "", measurementId: "" }; // Initialize Firebase const app = initializeApp(firebaseConfig); const analytics = getAnalytics(app); </script> <script> window.addEventListener('load', function (ev) { // Download main.dart.js _flutter.loader.loadEntrypoint({ serviceWorker: { serviceWorkerVersion: serviceWorkerVersion, } }).then(function (engineInitializer) { return engineInitializer.initializeEngine(); }).then(function (appRunner) { return appRunner.runApp(); }); }); </script> </body> </html>
你同时用了两种方式初始化Firebase:
- 在
index.html中通过原生JS的Firebase SDK(v9.9.4)初始化了Firebase App - 在Flutter的
main函数中又通过firebase_core插件调用Firebase.initializeApp()再次初始化
这种重复初始化会导致Flutter的Firebase web插件与原生JS SDK产生冲突,引发类型转换错误——插件尝试处理已由JS SDK初始化的对象时,无法将其转换为Dart端期望的类型,从而抛出object cannot be a num, string, bool, or null错误。
只保留一种Firebase初始化方式即可,推荐保留Flutter插件的初始化方式,步骤如下:
删除
index.html中的原生Firebase初始化代码
移除<body>内的<script type="module">标签及其内部所有内容,也就是这段代码:<script type="module"> // Import the functions you need from the SDKs you need import { initializeApp } from "https://www.gstatic.com/firebasejs/9.9.4/firebase-app.js"; import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.9.4/firebase-analytics.js"; // TODO: Add SDKs for Firebase products that you want to use // https://firebase.google.com/docs/web/setup#available-libraries // Your web app's Firebase configuration // For Firebase JS SDK v7.20.0 and later, measurementId is optional const firebaseConfig = { apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "", measurementId: "" }; // Initialize Firebase const app = initializeApp(firebaseConfig); const analytics = getAnalytics(app); </script>确保Flutter端的Firebase配置正确
检查DefaultFirebaseOptions.currentPlatform是否已正确包含Web端的Firebase配置信息。如果没有,需要在firebase_options.dart中补充Web平台的配置,或者直接传入配置对象:await Firebase.initializeApp( options: FirebaseOptions( apiKey: "你的apiKey", authDomain: "你的authDomain", projectId: "你的projectId", storageBucket: "你的storageBucket", messagingSenderId: "你的messagingSenderId", appId: "你的appId", measurementId: "你的measurementId", ), );重新运行Web应用
执行flutter run -d chrome重新启动Web应用,确认错误是否消失。
内容的提问来源于stack exchange,提问作者Anas Ansari

