大部分情况下我们需要对产品,特定功能进行数据监测收集(性能,crash,api异常),以便对后续的改进提供有效的数据依据。作为一名前端开发,我们有必要收集用户在使用产品中各种行为、异常数据。
Firebase产品免费又很好用,可惜域名被国内ban了没法用呀。
数据监测的产品有GrowingIO,神策之类的,最后我选了免费的百度移动统计,早先对百度统计的“实时访客”好感甚佳…
在github上找到一位朋友写的wrap百度移动统计SDK的包。(v7lin/fake_analytics
)这位朋友还wrap了很多其他的SDK(微信、新浪微博、支付宝、okhttp)。
这也是我为什么选择在这个时间点玩flutter,大部分你遇到要用的东西,应该都有人写好了,除非特别生僻的领域。
pubspec.yml 1 2 3 4 dependencies: fake_analytics: git: url: https://github.com/v7lin/fake_analytics.git
这位仁兄的包引不进来,于是我自己把源码复制到项目里来了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 BaiduAnalytics.dart class BaiduAnalytics { static const String _METHOD_STARTWORK = 'startWork' ; static const String _METHOD_SIGNUP = 'signUp' ; static const String _METHOD_SIGNIN = 'signIn' ; static const String _METHOD_SIGNOUT = 'signOut' ; static const String _METHOD_TRACKEVENT = 'trackEvent' ; static const String _METHOD_STARTEVENTTRACKING = 'startEventTracking' ; static const String _METHOD_STOPEVENTTRACKING = 'stopEventTracking' ; static const String _METHOD_STARTPAGETRACKING = 'startPageTracking' ; static const String _METHOD_STOPPAGETRACKING = 'stopPageTracking' ; static const String _ARGUMENT_KEY_APPKEY = 'appKey' ; static const String _ARGUMENT_KEY_APPCHANNEL = 'appChannel' ; static const String _ARGUMENT_KEY_ENABLEDEBUG = 'enableDebug' ; static const String _ARGUMENT_KEY_USERID = 'userId' ; static const String _ARGUMENT_KEY_EVENTID = 'eventId' ; static const String _ARGUMENT_KEY_EVENTLABEL = 'eventLabel' ; static const String _ARGUMENT_KEY_PAGENAME = 'pageName' ; static const MethodChannel _channel = const MethodChannel('plugins.flutter.io/fake_analytics' ); Future<void > startWork({ @required String appKey, @required AsyncValueGetter<String > appChannel, bool enableDebug: false , }) async { assert (appKey != null && appKey.isNotEmpty); assert (appChannel != null ); String channelId = await appChannel(); assert (channelId != null && channelId.isNotEmpty); await _channel.invokeMethod( _METHOD_STARTWORK, <String , dynamic >{ _ARGUMENT_KEY_APPKEY: appKey, _ARGUMENT_KEY_APPCHANNEL: channelId, _ARGUMENT_KEY_ENABLEDEBUG: enableDebug, }, ); }
BaiduAnalyticsObserver.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 typedef String ScreenNameExtractor(RouteSettings settings);String defaultNameExtractor(RouteSettings settings) => settings.name;class BaiduAnalyticsObserver extends RouteObserver <PageRoute <dynamic >> { BaiduAnalyticsObserver({ @required this .analytics, this .nameExtractor = defaultNameExtractor, Function (PlatformException error) onError, }) : _onError = onError; final BaiduAnalytics analytics; final ScreenNameExtractor nameExtractor; final void Function (PlatformException error) _onError; @override void didPush(Route<dynamic > route, Route<dynamic > previousRoute) { super .didPush(route, previousRoute); if (previousRoute != null && previousRoute is PageRoute) { String pageName = nameExtractor(previousRoute.settings); if (pageName != null ) analytics.stopPageTracking( pageName: pageName, ); } if (route != null && route is PageRoute) { String pageName = nameExtractor(route.settings); if (pageName != null ) analytics.startPageTracking( pageName: pageName, ); } }
Observer主要hook了didPush和didPop,也就是进入页面和返回上一个页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class MyApp extends StatelessWidget { static BaiduAnalytics analytics = BaiduAnalytics(); static BaiduAnalyticsObserver observer = BaiduAnalyticsObserver(analytics: analytics); @override Widget build(BuildContext context) { if (Platform.isAndroid) { analytics.startWork( appKey: 'f05f6201d8' , appChannel: () => Future.value('official' ), enableDebug: true , ); } else if (Platform.isIOS) { analytics.startWork( appKey: '404ff27775' , appChannel: () => Future.value('official' ), enableDebug: true , ); } return MaterialApp( title: 'Flutter Demo' , theme: ThemeData( primarySwatch: Colors.blue, ), navigatorObservers: <NavigatorObserver>[observer],
当在Flutter的MaterialApp组件中可以传递一组NavigatorObserver,来对路由变化进行观察,这样我们就可以通过实现这个Observer,来对导航级别的行为进行监测。 在入口页初始化一个observer,初始化analytics,填入你申请到的appKey启动sdk。 导航的时候给路由设置一个name来命名要进入的页面。
1 2 3 4 5 6 7 8 9 10 void _goSearch(){ var routeName = '/search/' +currentType; Navigator.push( context, MaterialPageRoute( builder: (context) => SearchPage( config: SearchConfig(type: currentType) ), settings: RouteSettings(name: routeName) ) ); }
最后收集到的数据。用户的行为路径,首页->搜索结果页->过滤->结果页
数据汇总
百度统计移动SDK还提供了事件监测,某些特定的页面还可以上报特定的事件来做针对性分析。
监测的难点主要在于大部分厂商提供的是原生(android、ios)的SDK,你可能需要写Flutter插件来跟原生代码通讯交互集成。不会很复杂,但就是费时间(很幸运百度移动统计有人写过哈哈
在Flutter内部主要是通过navigation observer
来监测页面级别的行为,给每个路由命好特定的名称,最后通过收集到路由名称的打开时序,来确定用户的访问路径达到一定的分析目的。