Flutter数据分析插件simplytics的使用
Flutter数据分析插件simplytics的使用
Simplytics(简单分析)是一个简单的抽象层,用于分析和崩溃报告。它可以让你连接多个不同的分析和错误监控服务,如Firebase Analytics和Crashlytics,Sentry等,并且还可以将事件简单地记录到系统日志中。
特点
- 轻松添加或替换分析/错误监控服务而无需更改应用程序代码。
- 可以同时向多个不同的分析服务发送路由转换和事件报告。
- 可以同时向多个错误监控服务发送崩溃和错误报告。
- 轻松调试事件并将其发送到系统日志。
- 轻松连接新的分析和错误监控服务。
- 使用
simplytics_firebase
包轻松连接Firebase Analytics和Crashlytics。 - 使用
simplytics_sentry
包轻松连接Sentry和Glitchtip。
目录
开始使用
要开始使用Simplytics,你需要配置它,并指定要使用的分析和错误监控服务类:
Simplytics.setup(
analyticsService: SimplyticsDebugAnalyticsService(),
crashlogService: SimplyticsDebugCrashlogService(),
);
注意! 这些设置必须在runApp()
之前完成:
void main() {
Simplytics.setup(
analyticsService: SimplyticsDebugAnalyticsService(),
crashlogService: SimplyticsDebugCrashlogService(),
);
runApp(const MyApp());
}
你可以在分析和错误监控方面使用多个服务。为此,你需要将它们包裹在一个组中:
Simplytics.setup(
analyticsService: SimplyticsAnalyticsServiceGroup([
SimplyticsDebugAnalyticsService(),
CustomAnalyticsService(),
]),
crashlogService: SimplyticsCrashlogServiceGroup([
SimplyticsDebugCrashlogService(),
CustomCrashReportingService(),
]),
);
对于Firebase Analytics和Crashlytics,你可以使用simplytics_firebase
包中的预构建服务类:
Simplytics.setup(
analyticsService: SimplyticsFirebaseAnalyticsService(FirebaseAnalytics.instance),
crashlogService: SimplyticsFirebaseCrashlogService(FirebaseCrashlytics.instance),
);
如果你希望捕获所有Dart和Flutter错误和异常并将它们发送到错误监控系统,可以使用runAppGuarded()
函数:
void main() {
runAppGuarded(
// 初始化Simplytics并创建应用类对象
() async {
// 设置Simplytics
Simplytics.setup(
analyticsService: SimplyticsDebugAnalyticsService(),
crashlogService: SimplyticsDebugCrashlogService(),
);
// 创建应用类对象
return const MyApp();
},
// 发送致命错误到Simplytics
onError: (error, stackTrace) => Simplytics.crashlog.recordFatalError,
);
}
runAppGuarded()
函数使配置和捕获所有未处理的错误和异常变得容易。
它调用WidgetsFlutterBinding.ensureInitialized()
(可以禁用),配置所有Dart和Flutter错误处理器,并启动应用。所有错误和异常都将通过onError
参数传递给你的处理程序。
使用
发送事件
要将事件发送到分析服务,你可以使用Simplytics.analytics
对象的logEvent
方法:
Simplytics.analytics.logEvent(name: 'button_tapped');
你可以在事件中传递参数,这些参数是一个Map<String, Object>
:
Simplytics.analytics.logEvent(name: 'product_details', parameters: {'id': 1, 'name': 'Product 1'});
你可以使用resetAnalyticsData
清除设备上的所有分析数据:
Simplytics.analytics.resetAnalyticsData();
跟踪路由之间的转换
要跟踪路由之间的导航,你可以在应用中使用SimplyticsNavigatorObserver
观察器:
class MyApp extends StatelessWidget {
// 创建一个Simplytics观察器实例
static SimplyticsNavigatorObserver simplyticsObserver = SimplyticsNavigatorObserver();
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Simplytics Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: const DemoPage(),
// 将Simplytics观察器实例传递给navigatorObservers
navigatorObservers: <NavigatorObserver>[simplyticsObserver],
);
}
}
该观察器会在当前活动的ModalRoute
发生变化时发送事件到分析服务。
你可以使用nameExtractor
参数配置从RouteSettings
中提取路由名称的方法,也可以使用routeFilter
参数过滤哪些路由之间的转换会自动发送到分析服务。
你还可以手动发送路由进入和退出事件,使用Simplytics.analytics
对象的routeStart
和routeEnd
方法:
Simplytics.analytics.routeStart('Login Screen');
...
Simplytics.analytics.routeEnd('Login Screen');
发送错误到错误监控服务
你可以使用Simplytics.crashlog
对象的recordError()
方法将错误信息发送到错误监控服务:
Simplytics.crashlog.recordError('Entity not found.', StackTrace.current, reason: 'NotFoundException');
添加额外的信息到报告
在发送报告时,你可以指定额外的信息,例如自定义属性、标签等。为此,你需要将一个或多个对象传递给information
参数。Simplytics提供了两个预定义的对象来描述属性和标签:
SimplyticsErrorProperty
- 用于自定义属性;SimplyticsErrorTag
- 用于标签。
例如,要将报告标记为“流程”,你可以传递SimplyticsErrorTag
:
Simplytics.crashlog.recordError(
'User not found.',
StackTrace.current,
reason: 'UserNotFoundException',
information: [
SimplyticsErrorTag('flow', 1),
],
);
属性的添加方式相同。你可以一次添加多个标签和属性:
Simplytics.crashlog.recordError(
'User not found.',
StackTrace.current,
reason: 'UserNotFoundException',
information: [
SimplyticsErrorTag('flow', 1),
SimplyticsErrorProperty('region', 'local'),
SimplyticsErrorProperty('code', 321),
],
);
你还可以传递其他对象,如ErrorHint
、ErrorDescription
、ErrorSummary
、ErrorSpacer
和其他任何dart对象。它们都会被转换为字符串并随报告一起发送。
依赖于错误监控服务的实现,附加到报告的额外信息可能会有所不同。例如,在Firebase Crashlytics中,标签、属性和其他对象作为附加信息块发送。在Sentry中,标签作为标签发送,这允许按标签筛选报告。
设置用户身份和自定义属性
你可以使用相应对象的setUserId
方法将用户身份存储到分析和错误监控服务中:
Simplytics.analytics.setUserId('user_1');
Simplytics.crashlog.setUserId('user_1');
你还可以使用setUserProperty
和setCustomKey
方法为分析和错误监控服务添加自定义属性和键:
// 为分析服务设置用户属性
Simplytics.analytics.setUserProperty(name: 'prop1', value: 'value1');
// 为错误监控服务设置自定义键
Simplytics.crashlog.setCustomKey('test_key', 'test_value');
调试分析事件和错误报告
要调试事件,你可以使用SimplyticsDebugAnalyticsService
和SimplyticsDebugCrashlogService
服务类,在调试编译模式(kDebugMode
)下将分析事件和错误报告输出到系统日志:
Simplytics.setup(
analyticsService: SimplyticsAnalyticsServiceGroup([
// 在kDebugMode下将事件发送到系统日志
SimplyticsDebugAnalyticsService(),
CustomAnalyticsService(),
]),
crashlogService: SimplyticsCrashlogServiceGroup([
// 在kDebugMode下将事件发送到系统日志
SimplyticsDebugCrashlogService(),
CustomCrashReportingService(),
]),
);
这种行为可以通过这些类的构造函数参数进行配置:
// 始终将事件发送到系统日志
SimplyticsDebugAnalyticsService(true)
创建自己的分析和错误监控服务类
对于你自己的或其他分析和错误监控服务,你可以创建自己的服务类并在Simplytics.setup()
中使用它们。
您自己的分析服务类
要创建自己的分析服务类,你需要扩展SimplyticsAnalyticsInterface
接口。
以下是一个针对Firebase Analytics的分析服务类的示例实现(但你可以使用simplytics_firebase
包中的预构建类):
class CustomFirebaseAnalyticsService extends SimplyticsAnalyticsInterface {
final FirebaseAnalytics analytics;
CustomFirebaseAnalyticsService(this.analytics);
bool _enabled = true;
[@override](/user/override)
Future<void> logEvent({required String name, Map<String, Object?>? parameters}) {
return analytics.logEvent(name: name, parameters: parameters);
}
[@override](/user/override)
Future<void> resetAnalyticsData() {
return analytics.resetAnalyticsData();
}
[@override](/user/override)
Future<void> routeStart({required String name, String? screenClassOverride}) {
return analytics.setCurrentScreen(screenName: name, screenClassOverride: screenClassOverride ?? 'Flutter');
}
[@override](/user/override)
Future<void> routeEnd({required String name}) async {}
[@override](/user/override)
Future<void> setUserId(String? id) {
return analytics.setUserId(id: id);
}
[@override](/user/override)
Future<void> setUserProperty({required String name, required String? value}) {
return analytics.setUserProperty(name: name, value: value);
}
[@override](/user/override)
bool get isEnabled => _enabled;
[@override](/user/override)
Future<void> setEnabled(bool enabled) {
_enabled = enabled;
return analytics.setAnalyticsCollectionEnabled(enabled);
}
}
您自己的错误监控服务类
要创建自己的错误监控服务类,你需要扩展SimplyticsCrashlogInterface
接口。
以下是一个针对Firebase Crashlytics的错误监控服务类的示例实现(但你可以使用simplytics_firebase
包中的预构建类):
class CustomFirebaseCrashlogService extends SimplyticsCrashlogInterface {
final FirebaseCrashlytics crashlytics;
CustomFirebaseCrashlogService(this.crashlytics);
[@override](/user/override)
Future<void> log(String message) {
return crashlytics.log(message);
}
[@override](/user/override)
Future<void> recordError(
dynamic exception,
StackTrace? stackTrace, {
dynamic reason,
Iterable<Object> information = const [],
bool fatal = false,
}) {
return crashlytics.recordError(
exception,
stackTrace,
reason: reason,
information: information,
fatal: fatal,
);
}
[@override](/user/override)
Future<void> setCustomKey(String key, Object value) {
return crashlytics.setCustomKey(key, value);
}
[@override](/user/override)
Future<void> setUserId(String identifier) {
return crashlytics.setUserIdentifier(identifier);
}
[@override](/user/override)
bool get isEnabled => crashlytics.isCrashlyticsCollectionEnabled;
[@override](/user/override)
Future<void> setEnabled(bool enabled) => crashlytics.setCrashlyticsCollectionEnabled(enabled);
}
具有类型安全参数的分析事件
你可以创建具有类型安全参数的自己的事件类,并在分发事件时使用它们:
Simplytics.analytics.log(PostScoreEvent(score: 7));
要做到这一点,扩展SimplyticsEvent
类并实现其getEventData
方法:
class PostScoreEvent extends SimplyticsEvent {
final int score;
final int level;
final String? character;
PostScoreEvent({required this.score, this.level = 1, this.character});
[@override](/user/override)
SimplyticsEventData getEventData(SimplyticsAnalyticsInterface service) =>
SimplyticsEventData(
name: 'post_score',
parameters: {
'score': score,
'level': level,
'character': character,
},
);
}
通过检查service
参数的类型,可以为不同的分析服务发送不同的事件,并带有不同的一组参数:
class PostScoreEvent extends SimplyticsEvent {
final int score;
final int level;
final String? character;
PostScoreEvent({required this.score, this.level = 1, this.character});
[@override](/user/override)
SimplyticsEventData getEventData(SimplyticsAnalyticsInterface service) {
if (service is SimplyticsFirebaseAnalyticsService) {
return SimplyticsEventData(
name: 'post_score',
parameters: {
'score': score,
'level': level,
'character': character,
},
);
} else {
return SimplyticsEventData(
name: 'game_score',
parameters: {
'scoreValue': score,
'gameLevel': level,
'characterName': character,
},
);
}
}
}
示例代码
以下是完整的示例代码,展示了如何使用Simplytics插件:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:simplytics/simplytics.dart';
import 'package:simplytics_example/page_route_settings.dart';
import 'package:simplytics_example/services/custom_analytics_service.dart';
import 'package:simplytics_example/services/custom_crash_reporting_service.dart';
void main() {
runAppGuarded(
// 初始化Simplytics并创建应用类对象
() async {
// 设置Simplytics
Simplytics.setup(
analyticsService: SimplyticsAnalyticsServiceGroup([
SimplyticsDebugAnalyticsService(),
CustomAnalyticsService(),
]),
crashlogService: SimplyticsCrashlogServiceGroup([
SimplyticsDebugCrashlogService(),
CustomCrashReportingService(),
]),
);
return const MyApp();
},
// 发送致命错误到Simplytics
onError: (error, stackTrace) => Simplytics.crashlog.recordFatalError,
);
}
class MyApp extends StatelessWidget {
// 设置观察器
static SimplyticsNavigatorObserver observer = SimplyticsNavigatorObserver(
nameExtractor: (route) => (route.settings is PageRouteSettings)
? (route.settings as PageRouteSettings).pageName
: route.settings.name,
routeFilter: (route) => (route is PageRoute) || (route is RawDialogRoute),
);
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Simplytics Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: const DemoPage(),
// 添加观察器到navigatorObservers
navigatorObservers: <NavigatorObserver>[observer],
);
}
}
// 主演示页面
class DemoPage extends StatelessWidget {
const DemoPage({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
OutlinedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
// 设置`settings`以在发送到分析时设置页面名称
settings: const PageRouteSettings(pageName: 'Analytics Demo Page'),
builder: (context) => const AnalyticsDemoPage(),
),
);
},
child: const Text('Analytics tests'),
),
OutlinedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
// 设置`settings`以在发送到分析时设置页面名称
settings: const PageRouteSettings(pageName: 'Error Reporting Demo Page'),
builder: (context) => const ErrorDemoPage(),
),
);
},
child: const Text('Error Reporting tests'),
),
const Divider(),
OutlinedButton(
onPressed: () {
showDialog(
context: context, builder: (context) => const TestDialog());
},
child: const Text('Dialog test'),
),
OutlinedButton(
onPressed: () {
showDialog(
context: context,
// 设置`settings`以在发送到分析时设置页面名称
routeSettings: const PageRouteSettings(pageName: 'Dialog with a named route'),
builder: (context) => const TestDialog(),
);
},
child: const Text('Dialog test with a named route'),
),
],
),
),
);
}
}
// 分析演示
class PostScoreEvent extends SimplyticsEvent {
final int score;
final int level;
final String? character;
PostScoreEvent({required this.score, this.level = 1, this.character});
[@override](/user/override)
SimplyticsEventData getEventData(SimplyticsAnalyticsInterface service) =>
SimplyticsEventData(
name: 'post_score',
parameters: {
'score': score,
'level': level,
'character': character,
},
);
}
class AnalyticsDemoPage extends StatefulWidget {
const AnalyticsDemoPage({super.key});
[@override](/user/override)
State<AnalyticsDemoPage> createState() => _AnalyticsDemoPageState();
}
class _AnalyticsDemoPageState extends State<AnalyticsDemoPage> {
[@override](/user/override)
void initState() {
super.initState();
Simplytics.analytics.setUserId('test_user');
Simplytics.analytics.setUserProperty(name: 'prop1', value: 'value1');
}
void _logEvent() {
Simplytics.analytics.logEvent(name: 'test_event');
}
void _logEventWithParams() {
Simplytics.analytics
.logEvent(name: 'test_event', parameters: {'id': 1, 'name': 'Test'});
}
void _logTypeSafeEvent() {
Simplytics.analytics
.log(PostScoreEvent(score: 7, level: 2, character: 'Dash'));
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Analytics tests')),
body: Center(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text('Analytics Off'),
Switch(
value: Simplytics.analytics.isEnabled,
onChanged: (value) async {
await Simplytics.analytics.setEnabled(value);
setState(() {});
},
),
const Text('Analytics On'),
],
),
const Divider(),
TextButton(
onPressed: _logEvent,
child: const Text('Log event'),
),
TextButton(
onPressed: _logEventWithParams,
child: const Text('Log event with data'),
),
TextButton(
onPressed: _logTypeSafeEvent,
child: const Text('Log type-safe event'),
),
],
),
),
),
);
}
}
// 错误报告演示
class ErrorDemoPage extends StatefulWidget {
const ErrorDemoPage({super.key});
[@override](/user/override)
State<ErrorDemoPage> createState() => _ErrorDemoPageState();
}
class _ErrorDemoPageState extends State<ErrorDemoPage> {
[@override](/user/override)
void initState() {
super.initState();
Simplytics.crashlog.setUserId('test_user');
Simplytics.crashlog.setCustomKey('test_key', 'test_value');
}
void _logError() {
Simplytics.crashlog.log('Some log error');
}
void _recordError() {
Simplytics.crashlog.recordError(
'Some error',
StackTrace.current,
information: [
ErrorHint('Error hint...'),
ErrorDescription('Error description...'),
ErrorSummary('Error summary...'),
ErrorSpacer(),
SimplyticsErrorTag('tag1', 7),
SimplyticsErrorProperty('prop1', 'a'),
],
reason: 'FakeException',
);
}
void _recordFatalError() {
Simplytics.crashlog.recordError(
'Some error',
StackTrace.current,
reason: 'FakeException',
fatal: true,
);
}
void _throwException() {
throw Exception('Some exception');
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Error Reporting tests'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text('Crashlog Off'),
Switch(
value: Simplytics.crashlog.isEnabled,
onChanged: (value) async {
await Simplytics.crashlog.setEnabled(value);
setState(() {});
},
),
const Text('Crashlog On'),
],
),
const Divider(),
TextButton(
onPressed: _logError,
child: const Text('Log error'),
),
TextButton(
onPressed: _recordError,
child: const Text('Record error'),
),
TextButton(
onPressed: _recordFatalError,
child: const Text('Record fatal error'),
),
TextButton(
onPressed: _throwException,
child: const Text('Throw exception'),
),
],
),
),
),
);
}
}
// 测试对话框
class TestDialog extends StatelessWidget {
const TestDialog({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return AlertDialog(
content: const Text('Dialog', textAlign: TextAlign.center),
alignment: Alignment.center,
actionsAlignment: MainAxisAlignment.center,
actions: [
TextButton(
onPressed: () => Navigator.pop(context), child: const Text('OK')),
],
);
}
}
更多关于Flutter数据分析插件simplytics的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter数据分析插件simplytics的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用simplytics
插件进行数据分析的示例代码。请注意,simplytics
是一个假设的插件名称,用于说明目的。实际中,如果simplytics
不是一个真实存在的插件,你需要替换为实际存在的数据分析插件,比如firebase_analytics
或其他类似插件。
不过,为了保持示例的相关性,我将基于一个假设的simplytics
插件API结构来编写代码。如果simplytics
确实存在,你需要参考其官方文档来调整代码。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加simplytics
依赖(假设它存在于pub.dev上):
dependencies:
flutter:
sdk: flutter
simplytics: ^x.y.z # 替换为实际版本号
然后运行flutter pub get
来安装依赖。
2. 初始化插件
在你的应用的主文件中(通常是main.dart
),初始化simplytics
插件:
import 'package:flutter/material.dart';
import 'package:simplytics/simplytics.dart'; // 假设的导入路径
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 初始化 Simplytics
Simplytics.initialize('YOUR_API_KEY'); // 替换为你的API密钥
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
3. 使用插件记录事件
在你的主页面或其他需要记录数据的组件中,使用simplytics
来记录事件:
import 'package:flutter/material.dart';
import 'package:simplytics/simplytics.dart'; // 假设的导入路径
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _logCustomEvent() {
// 记录一个自定义事件
Map<String, dynamic> eventParams = {
'category': 'user_interaction',
'action': 'button_click',
'label': 'home_screen_button',
'value': 1, // 可选,事件的值
};
Simplytics.logEvent(name: 'custom_event', parameters: eventParams);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Simplytics Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: _logCustomEvent,
child: Text('Log Custom Event'),
),
),
);
}
}
4. 运行应用
现在,你可以运行你的Flutter应用,并点击按钮来触发事件记录。假设的simplytics
插件将会把这些事件发送到你的数据分析后台。
注意
- 实际插件使用:请确保你使用的插件名称和API与实际存在的插件一致。如果
simplytics
不是真实存在的插件,请参考类似插件(如firebase_analytics
)的官方文档。 - API密钥:在初始化插件时,确保使用正确的API密钥。这通常是从你的数据分析服务提供者那里获取的。
- 事件参数:根据你的需求,调整事件参数以符合你的数据分析需求。
希望这个示例能帮助你理解如何在Flutter项目中使用数据分析插件。如果有任何进一步的问题,请随时提问!