firebase_analytics在未被广告拦截程序加载/阻止时崩溃Flutter Web应用程序



My Flutter Web应用程序在用户启用了阻止firebase-analytics.js的广告阻止程序时崩溃。我只剩下一页空白。

这是我收到的错误:

top_level.dart.lib.js:110 Uncaught (in promise) TypeError: dart.global.firebase.analytics is not a function
at Object.analytics$ [as analytics] (top_level.dart.lib.js:110)
at new firebase_analytics_web.FirebaseAnalyticsWeb.new (:7357/packages/firebase_analytics_web/firebase_analytics_web.dart.lib.js:56)
at Function.registerWith (:7357/packages/firebase_analytics_web/firebase_analytics_web.dart.lib.js:19)
at Object.registerPlugins (:7357/packages/triage/generated_plugin_registrant.dart.lib.js:13)
at main (:7357/web_entrypoint.dart.lib.js:29)

我正在使用以下版本的firebase_analytics插件:

firebase_analytics: ^7.1.1

问题

这是因为firebase包(由firebase_analytics_web使用(依赖于JS中存在的firebase.analytics()函数。请参阅相关代码
因此,当广告拦截程序阻止加载firebase-analytics.js时,这段代码将抛出,从而导致整个Flutter Web初始化崩溃。

解决方案

我们可以创建firebase.analytics()mock来解决这个问题。请注意,在firebase_analytics_web中,firebase.analytics()函数被仅调用一次,然后存储在实例中。这就是为什么如果我们希望稍后能够加载到firebase-analytics.js库中,我们的mock必须确保以某种方式再次调用JS中的firebase.analytics()

这里有一个脚本,您可以在加载至少firebase-app.js之后将其插入到<body>中。例如,如果您遵守GDPR,并且异步加载Firebase分析(例如,在用户通过Google Tag Manager同意后(,这将非常有用。无论如何,这里有一个完全修复问题的模拟允许稍后加载Firebase Analytics:

<!--
We need to create a mock for Firebase Analytics that ensures that it *does not matter **when***
the JS library is loaded. This is because Google Tag Manager will load firebase-analytics.js
and this 1. happens asynchronously and 2. only after the user consented.
The firebase.dart Dart library will crash if the firebase.analytics object does not exist,
which is why this is absolutely crucial for starting the app.
https://stackoverflow.com/a/66589887/6509751
-->
<script>
// This mock ensures that if the firebase_analytics Flutter plugin uses this mock as its
// instance (which does not change over time), the plugin will *still* be able to reach out
// to the actual firebase.analytics() instance because the object will be overridden once the
// firebase-analytics.js library is loaded in.
firebase.analytics = function () {
return {
mock: true,
app: function () {
var instance = firebase.analytics()
// Prevent infinite recursion if the real instance has not yet been loaded.
if (instance.mock === true) return
return instance.app
},
logEvent: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.logEvent(...arguments)
},
setAnalyticsCollectionEnabled: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.setAnalyticsCollectionEnabled(...arguments)
},
setCurrentScreen: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.setCurrentScreen(...arguments)
},
setUserId: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.setUserId(...arguments)
},
setUserProperties: function () {
var instance = firebase.analytics()
if (instance.mock === true) return
return instance.setUserProperties(...arguments)
},
}
}
</script>

相关内容

  • 没有找到相关文章

最新更新