如何在Firebase分析中跟踪抖动屏幕?

bvuwiixz  于 2022-11-30  发布在  其他
关注(0)|答案(4)|浏览(433)

我有一个Flutter应用程序,我正在Flutter上测试Firebase的谷歌分析。
我想看看我们的用户(目前是我)正在访问的路线。我按照firebase_analytics中的设置步骤进行了操作,并检查了他们的示例应用程序。我启用了Debug View docs中描述的Analytics调试
不幸的是,我在Analytics Debug视图中收到的仅有两种屏幕视图(firebase_screen_class)是FlutterMainActivity
我希望在某个地方看到/example-1/example-2/welcome,但我没有。
这是我在Flutter中运行的应用程序

class App extends StatelessWidget {
  final FirebaseAnalytics analytics = FirebaseAnalytics();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      routes: <String, WidgetBuilder>{
        '/example-1': (_) => Example1(),
        '/example-2': (_) => Example2(),
        '/welcome': (_) => Welcome(),
      },
      home: Welcome(),
      navigatorObservers: [FirebaseAnalyticsObserver(analytics: analytics)],
    );
  }
}
qkf9rpyu

qkf9rpyu1#

这个确切的用例在Track Screenviews部分下的Firebase Analytics文档中。
如果您的应用没有为您希望跟踪的每个屏幕(例如在游戏中)使用单独的UIViewController或Activity,则手动跟踪屏幕非常有用。
Flutter正是这种情况,因为Flutter负责屏幕更新:大多数简单的Flutter应用运行一个FlutterActivity/FlutterAppDelegate,它会自行渲染不同的屏幕,因此让Firebase Analytics自动跟踪屏幕不会带来预期的效果。
就我过去的经验来看,FirebaseAnalyticsObserver不是很有帮助,但是,我也推荐你,check their docs again,他们确实暗示事情应该“只是工作”。我最好的猜测是,它对我没有很好地工作,因为我没有在我的任何路线上使用RouteSettings*
如果FirebaseAnalyticsObserver不工作或不适用于您的应用程序,在过去几个月的开发中,下一种方法对我来说相当有效。
如果使用屏幕名称调用setCurrentScreen方法,则可以在任何时候使用FirebaseAnalytics设置当前屏幕:

import 'package:firebase_analytics/firebase_analytics.dart';
// Somewhere in your widgets...
FirebaseAnalytics().setCurrentScreen(screenName: 'Example1');

作为第一次尝试,我在小部件构造函数中这样做,但这样做效果不好,并且会错误地计算事件:如果你弹出或推入路径,堆栈中的所有小部件构造函数都将被调用,即使只有顶部的路径才真正有资格作为“当前屏幕”。
为了解决这个问题,我们需要使用RouteAware类,并且只在当前屏幕是顶部路线的情况下设置当前屏幕:要么我们的路由被添加到堆栈,要么前一个顶部路由被弹出,我们到达该路由。
RouteAware附带了样板代码,我们不想在所有屏幕上重复这个样板代码。即使是小应用,也有几十个不同的屏幕,所以我创建了RouteAwareAnalytics mixin:

import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:flutter/widgets.dart';

// A Navigator observer that notifies RouteAwares of changes to state of their Route
final routeObserver = RouteObserver<PageRoute>();

mixin RouteAwareAnalytics<T extends StatefulWidget> on State<T>
    implements RouteAware {
  AnalyticsRoute get route;

  @override
  void didChangeDependencies() {
    routeObserver.subscribe(this, ModalRoute.of(context));
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  @override
  void didPop() {}

  @override
  void didPopNext() {
    // Called when the top route has been popped off,
    // and the current route shows up.
    _setCurrentScreen(route);
  }

  @override
  void didPush() {
    // Called when the current route has been pushed.
    _setCurrentScreen(route);
  }

  @override
  void didPushNext() {}

  Future<void> _setCurrentScreen(AnalyticsRoute analyticsRoute) {
    print('Setting current screen to $analyticsRoute');
    return FirebaseAnalytics().setCurrentScreen(
      screenName: screenName(analyticsRoute),
      screenClassOverride: screenClass(analyticsRoute),
    );
  }
}

我创建了一个enum来跟踪屏幕(以及将枚举转换为屏幕名称的函数)。我使用枚举能够轻松跟踪所有路由,重构路由名称。使用这些枚举和函数,我可以对所有可能的值进行单元测试,并强制一致的命名:没有意外的空格或特殊字符,没有不一致的大写。可能有其他更好的方法来确定屏幕类的值,但我采用了这种方法。

enum AnalyticsRoute { example }

String screenClass(AnalyticsRoute route) {
  switch (route) {
    case AnalyticsRoute.example:
      return 'ExampleRoute';
  }
  throw ArgumentError.notNull('route');
}

String screenName(AnalyticsRoute route) {
  switch (route) {
    case AnalyticsRoute.example:
      return '/example';
  }
  throw ArgumentError.notNull('route');
}

初始设置的下一步是将routeObserver注册为MaterialAppnavigatorObserver

MaterialApp(
  // ...
  navigatorObservers: [
    routeObserver,
    // FirebaseAnalyticsObserver(analytics: FirebaseAnalytics()),
  ],
);

最后,我们可以添加第一个被跟踪的示例路径。将with RouteAwareAnalytics添加到您的州并覆盖get route

class ExampleRoute extends StatefulWidget {
  @override
  _ExampleRouteState createState() => _ExampleRouteState();
}

class _ExampleRouteState extends State<ExampleRoute> with RouteAwareAnalytics{
  @override
  Widget build(BuildContext context) => Text('Example');

  @override
  AnalyticsRoute get route => AnalyticsRoute.example;
}

每次添加新路线时,都可以轻松完成:首先,添加一个新的枚举值,然后Dart编译器将指导您接下来添加什么:在各自的switch-case中添加屏幕名称和类覆盖值。然后,找到构建路由的州,添加with RouteAwareAnalytics,并添加route getter。
*****我没有使用RouteSettings的原因是我更喜欢带类型化参数的Simon Lightfoot's approach,而不是设置提供的Object参数:

class ExampleRoute extends StatefulWidget {
  const ExampleRoute._({@required this.integer, Key key}) : super(key: key);
  // All types of members are supported, but I used int as example
  final int integer;
  static Route<void> route({@required int integer}) =>
      MaterialPageRoute(
        // I could add the settings here, though, it wouldn't enforce good types
        builder: (_) => ExampleRoute._(integer: integer),
      );
  // ...
}
bf1o4zei

bf1o4zei2#

添加导航观察器

将Firebase分析navigation observer添加到您的MatetialApp:

class MyApp extends StatelessWidget {
  FirebaseAnalytics analytics = FirebaseAnalytics();
...

MaterialApp(
  home: MyAppHome(),
  navigatorObservers: [
    FirebaseAnalyticsObserver(analytics: analytics), // <-- here
  ],
);

**就是这样!**您的分析应该出现在DebugView:

注意!

如果您是第一次在应用中集成分析功能,则需要大约一天的时间,您的分析功能才会显示在 Jmeter 盘中。

立即查看结果

要立即查看调试结果,请在终端上运行上述命令,然后检查它们是否出现在DebugView中:

adb shell setprop debug.firebase.analytics.app [your_app_package_name]

好好享受吧!

wwtsj6pe

wwtsj6pe3#

我经历了一段时间的问题,只是能够使它的工作
对我来说,问题是我没有在MaterialPageRoute中正确传递设置

return MaterialPageRoute(
      settings: RouteSettings(
        name: routeName,
      ),
      builder: (_) => viewToShow);
}

我按照FilledStack上的教程学习,在看到示例代码后能够弄清楚我的问题

hxzsmxv2

hxzsmxv24#

如果您在screen_view事件的firebase_screen_class参数中看到“Flutter”,则表示您已正确配置它。
您应该在firebase_screen参数中找到所需的值,而不是在firebase_screen_class中。
还值得检查firebase_previous_screen参数,以查看在此之前打开的屏幕是什么。

相关问题