Title: Flutter SDK Locale: zh URL: https://sensorswave.com/docs/data-integration/client-sdks/flutter/ Description: Flutter SDK 集成指南和 API 参考 Sensors Wave Flutter SDK 是专为 Flutter 应用设计的移动端数据采集和 AB 实验工具。 ## 核心功能 Flutter SDK 提供以下核心能力: - **事件追踪**:手动追踪自定义事件和用户行为 - **自动埋点**:自动采集应用启动、应用结束、页面浏览、页面离开等事件 - **用户识别**:支持匿名用户和登录用户身份关联 - **用户属性管理**:完整的用户属性操作(设置、追加、增量更新等) - **A/B 测试集成**:支持功能开关(Feature Gate)和实验变量获取 - **路由监听**:自动监听页面路由变化,采集页面浏览事件 - **批量发送**:优化网络请求性能,每 5 秒批量发送最多 10 个事件 - **公共属性**:支持静态公共属性,自动附加到所有事件 ## 安装 ### 通过 pub.dev 安装 在 `pubspec.yaml` 中添加以下内容: ```yaml dependencies: sensorswave_flutter_sdk: ^0.2.0 ``` 然后运行: ```bash flutter pub get ``` ## 快速开始 ### 基础初始化 在您的 `main.dart` 中初始化 SDK: ```dart void main() { WidgetsFlutterBinding.ensureInitialized(); // 初始化 SDK(同步方法,立即返回) final sdk = SensorsWaveSDK(); sdk.init('YOUR_SOURCE_TOKEN', config: SensorsConfig.create( apiHost: 'https://your-api-endpoint.com', // 数据上报地址 debug: false, // 调试模式 autoCapture: true // 开启自动埋点 )); runApp(MyApp()); } ``` ### 发送第一个事件 初始化完成后,您可以立即开始上报事件: ```dart // 追踪用户点击按钮 SensorsWaveSDK().trackEvent('ButtonClick', { 'button_name': 'submit', 'page': 'home', }); ``` ### 集成路由观察者 要启用自动页面追踪,将路由观察者添加到您的 `MaterialApp`: ```dart MaterialApp( navigatorObservers: [ if (SensorsWaveSDK().routeObserver != null) SensorsWaveSDK().routeObserver!, ], // ... 其他属性 ); ``` ## 配置选项 `init` 方法的 `config` 参数是配置对象,支持以下选项: | 配置项 | 类型 | 默认值 | 说明 | |--------|------|--------|------| | `debug` | `bool` | `false` | 是否开启调试模式,开启后在控制台输出详细日志 | | `apiHost` | `String` | `''` | **必填**,数据上报的 API 地址 | | `autoCapture` | `bool` | `true` | 是否开启自动埋点,自动采集应用启动、结束、页面浏览等事件 | | `enableClickTrack` | `bool` | `false` | 是否开启点击自动追踪(追踪主要可点击组件) | | `enableAB` | `bool` | `false` | 是否开启 A/B 测试功能 | | `abRefreshInterval` | `int` | `600000` | A/B 测试配置刷新间隔(毫秒),默认 10 分钟,最小 30s | | `batchSend` | `bool` | `true` | 是否使用批量发送,每 5 秒批量发送最多 10 个事件 | ### 完整配置示例 ```dart sdk.init('YOUR_SOURCE_TOKEN', config: SensorsConfig.create( apiHost: 'https://your-api-endpoint.com', debug: true, // 开发环境开启调试 autoCapture: true, // 开启自动埋点 enableClickTrack: true, // 开启点击追踪 enableAB: true, // 开启 A/B 测试 abRefreshInterval: 10 * 60 * 1000, // A/B 测试数据每 10 分钟刷新 batchSend: true // 批量发送优化性能 )); ``` > **提示**:在生产环境中建议关闭 `debug` 模式,以避免在控制台输出过多日志。 ## API 方法 ### 事件追踪 #### trackEvent - 追踪自定义事件 手动追踪自定义事件及其属性。 **参数**: - `eventName` (`String`,必填):事件名称 - `properties` (`Map`,可选):事件属性,键值对形式 **示例**: ```dart // 追踪按钮点击 SensorsWaveSDK().trackEvent('ButtonClick', { 'button_name': 'submit', 'page': 'home', }); ``` **实际场景示例**: ```dart // 电商场景:用户浏览商品 SensorsWaveSDK().trackEvent('ProductView', { 'product_id': '12345', 'product_name': '无线蓝牙耳机', 'category': '电子产品', 'price': 299.00, 'currency': 'CNY', }); // 电商场景:用户加入购物车 SensorsWaveSDK().trackEvent('AddToCart', { 'product_id': '12345', 'quantity': 1, 'price': 299.00, }); // 内容平台:文章阅读 SensorsWaveSDK().trackEvent('ArticleRead', { 'article_id': 'article_001', 'title': 'Flutter 性能优化技巧', 'category': '技术博客', 'read_duration': 120, // 阅读时长(秒) }); ``` #### track - 高级事件追踪 发送完整的事件对象,支持更精细的控制。此方法允许您手动指定所有事件字段。 **参数**: - `event` (SensorsSendEvent,必填):完整事件对象 **示例**: ```dart final event = SensorsSendEvent( event: 'purchaseCompleted', properties: { 'product_id': '12345', 'amount': 99.99, 'currency': 'USD', }, time: DateTime.now().millisecondsSinceEpoch, traceId: 'unique-trace-id-12345', anonId: SensorsWaveSDK().getAnonId(), loginId: SensorsWaveSDK().getLoginId(), userProperties: { 'plan': 'premium', 'signup_date': '2024-01-01', }, ); SensorsWaveSDK().track(event); ``` > **注意**:`track` 方法是高级功能,大多数场景下使用 `trackEvent` 即可满足需求。 ### 用户识别 #### identify - 设置登录用户 ID 设置登录用户 ID 并发送绑定事件,将匿名行为与已识别用户关联。 **参数**: - `loginId` (`String | num`,必填):用户的唯一标识符(如邮箱、用户 ID、用户名) **示例**: ```dart // 用户登录后设置用户 ID SensorsWaveSDK().identify('user_12345'); ``` **完整登录流程示例**: ```dart // 用户登录流程 Future handleUserLogin(String email, String password) async { try { // 调用登录 API final response = await http.post( Uri.parse('/api/login'), body: jsonEncode({'email': email, 'password': password}), ); final userId = jsonDecode(response.body)['userId']; // 设置用户 ID 并关联匿名行为 SensorsWaveSDK().identify(userId); } catch (error) { print('登录失败: $error'); } } ``` > **重要提醒**:如果 `loginId` 包含隐私信息(如手机号、邮箱、身份证号等),请务必在加密后再进行传输,避免敏感信息明文上报。 #### setLoginId - 仅设置登录 ID 设置登录用户 ID,但不发送绑定事件。如果您只想识别用户但不需要关联用户,可以使用此方法。 **参数**: - `loginId` (`String | num`,必填):用户的唯一标识符 **示例**: ```dart SensorsWaveSDK().setLoginId('user_12345'); // 也支持数值类型(自动转换为 String) SensorsWaveSDK().setLoginId(12345); ``` > **重要提醒**:如果 `loginId` 包含隐私信息(如手机号、邮箱、身份证号等),请务必在加密后再进行传输,避免敏感信息明文上报。 > **使用建议**:通常情况下推荐使用 `identify` 方法,因为它会记录用户身份关联事件,有助于后续分析。 #### getLoginId - 获取登录用户 ID 获取当前设置的登录用户 ID。 **返回值**:String? **示例**: ```dart final loginId = SensorsWaveSDK().getLoginId(); if (loginId != null) { print('当前用户: $loginId'); } ``` #### getAnonId - 获取匿名用户 ID 获取当前用户的匿名 ID。 **返回值**:String? **示例**: ```dart final anonId = SensorsWaveSDK().getAnonId(); print('匿名用户 ID: $anonId'); ``` ### 用户属性 用户属性用于描述用户的特征,如会员等级、注册时间、偏好设置等。与事件属性不同,用户属性会持久化保存并与用户关联。 #### profileSet - 设置用户属性 设置用户属性,如果属性已存在则覆盖。 **参数**: - `properties` (`Map`,必填):要设置的用户属性 **示例**: ```dart // 用户完成注册后,设置用户属性 await SensorsWaveSDK().profileSet({ 'name': 'John Doe', 'age': 30, 'plan': 'premium', }); ``` #### profileSetOnce - 仅首次设置 设置用户属性,仅在属性不存在时设置,已存在的属性不会被覆盖。 **参数**: - `properties` (`Map`,必填):要设置的用户属性 **示例**: ```dart // 记录用户首次访问信息(仅记录一次,后续不会覆盖) await SensorsWaveSDK().profileSetOnce({ 'signup_date': '2024-01-15', 'initial_referrer': 'google', 'initial_campaign': 'spring_sale', }); ``` #### profileIncrement - 增量更新数值属性 对数值类型的用户属性进行增减操作。仅支持数值属性。 **参数**: - `properties` (`Map`,必填):要增减的属性及其数值 **示例**: ```dart // 增加单个属性 await SensorsWaveSDK().profileIncrement({ 'login_count': 1, }); // 增加多个属性 await SensorsWaveSDK().profileIncrement({ 'login_count': 1, 'points_earned': 100, 'purchases_count': 1, }); ``` #### profileAppend - 追加到数组属性 向数组类型的用户属性追加新值,不进行去重。 **参数**: - `properties` (`Map`,必填):要追加的属性及其数组值 **示例**: ```dart await SensorsWaveSDK().profileAppend({ 'categories_viewed': ['electronics', 'mobile_phones'], 'tags': ['new_customer', 'q1_2024'], }); ``` #### profileUnion - 追加到集合属性(去重) 向数组类型的用户属性追加新值,自动去重。 **参数**: - `properties` (`Map`,必填):要追加的属性及其数组值 **示例**: ```dart // 第一次调用 await SensorsWaveSDK().profileUnion({ 'interests': ['technology', 'gaming'], }); // 第二次调用,'technology' 不会重复添加 await SensorsWaveSDK().profileUnion({ 'interests': ['technology', 'music'], // 只会增加 'music' }); ``` #### profileUnset - 删除指定属性 将指定的用户属性设置为 null。 **参数**: - `keys` (`String | List`,必填):要置为 null 的属性名或属性名数组 **示例**: ```dart // 删除单个属性 await SensorsWaveSDK().profileUnset('temporary_campaign'); // 删除多个属性 await SensorsWaveSDK().profileUnset(['old_plan', 'expired_flag', 'temp_id']); ``` #### profileDelete - 删除所有用户属性 删除当前用户的所有用户属性数据。此操作不可撤销。 **示例**: ```dart // 用户注销账号时,删除所有用户属性 await SensorsWaveSDK().profileDelete(); ``` > **警告**:`profileDelete` 会删除所有用户属性,请谨慎使用。 #### 用户属性使用示例 **会员升级场景**: ```dart Future handleMembershipUpgrade(String newPlan) async { // 更新会员等级和升级时间 await SensorsWaveSDK().profileSet({ 'plan': newPlan, 'upgrade_time': DateTime.now().toIso8601String(), }); // 增加升级次数 await SensorsWaveSDK().profileIncrement({ 'upgrade_count': 1, }); // 追踪升级事件 SensorsWaveSDK().trackEvent('membershipUpgrade', { 'from_plan': 'basic', 'to_plan': newPlan, }); } ``` ### 公共属性 公共属性会自动添加到所有事件中,适用于需要在每个事件中都包含的通用信息。 #### registerCommonProperties - 注册公共属性 注册静态公共属性,这些属性将自动包含在所有事件中。 **参数**: - `properties` (`Map`,必填):要注册的属性 **示例**: ```dart SensorsWaveSDK().registerCommonProperties({ 'app_version': '1.0.0', 'environment': 'production', 'user_tier': getUserTier(), }); ``` #### clearCommonProperties - 清除公共属性 移除指定的已注册公共属性。 **参数**: - `keys` (`List`,必填):要移除的属性名数组 **示例**: ```dart SensorsWaveSDK().clearCommonProperties(['app_version', 'user_session_id']); ``` > **注意**:公共属性会增加每个事件的数据量,建议仅添加确实需要的通用属性。 ### A/B 测试 Flutter SDK 内置了 A/B 测试支持,可以获取功能开关状态和实验变量。 #### 开启 A/B 测试功能 ```dart sdk.init('YOUR_SOURCE_TOKEN', config: SensorsConfig.create( apiHost: 'https://your-api-endpoint.com', enableAB: true, // 开启 A/B 测试 abRefreshInterval: 10 * 60 * 1000 // 配置刷新间隔(10 分钟) )); ``` #### checkFeatureGate - 检查功能开关 检查功能开关(Feature Flag)是否为当前用户启用。 **参数**: - `key` (String,必填):功能开关的 Key **返回值**:`Future` **示例**: ```dart // 检查功能是否启用 final isEnabled = await SensorsWaveSDK().checkFeatureGate('new_checkout_flow'); if (isEnabled) { // 显示新功能 showNewCheckout(); } else { // 显示旧功能 showOldCheckout(); } ``` #### getExperiment - 获取实验变量 获取当前用户的实验变量数据。 **参数**: - `key` (String,必填):实验的 Key **返回值**:`Future>` **示例**: ```dart // 获取实验配置 final experiment = await SensorsWaveSDK().getExperiment('pricing_display'); if (experiment.isNotEmpty) { // 应用实验配置 final priceFormat = experiment['price_format']; final discountType = experiment['discount_type']; updatePricingDisplay(priceFormat, discountType); } ``` **完整 A/B 测试示例**: ```dart // 电商首页 CTA 按钮 A/B 测试 Future initHomepageCTA() async { try { final experiment = await SensorsWaveSDK().getExperiment('homepage_cta_test'); if (experiment.isNotEmpty) { final buttonText = experiment['button_text'] ?? '立即购买'; final buttonColor = experiment['button_color'] ?? '#ff6600'; final buttonSize = experiment['button_size'] ?? '16px'; // 应用实验配置到 UI updateCTAButton(buttonText, buttonColor, buttonSize); } } catch (error) { print('获取实验变量失败: $error'); // 使用默认配置 } } ``` > **提示**:A/B 测试功能需要在 Sensors Wave 后台配置实验和功能开关后才能使用。 ## 自动埋点 开启自动埋点后,SDK 会自动采集以下事件类型: | 事件名称 | 说明 | 触发时机 | |---------|------|---------| | `$AppInstall` | 首次安装 | 首次启动应用时 | | `$AppStart` | 应用启动 | 应用进入前台时 | | `$AppEnd` | 应用结束 | 应用进入后台时 | | `$AppPageView` | 页面浏览 | 用户导航到新页面/路由时 | | `$AppPageLeave` | 页面离开 | 用户离开页面/路由时 | | `$AppClick` | 元素点击 | 用户点击元素时(需开启 `enableClickTrack`) | ### 开启自动埋点 ```dart sdk.init('YOUR_SOURCE_TOKEN', config: SensorsConfig.create( apiHost: 'https://your-api-endpoint.com', autoCapture: true, // 开启自动埋点 enableClickTrack: true // 开启点击自动追踪 )); ``` ### 点击自动追踪 当启用 `enableClickTrack` 时,SDK 自动追踪以下 Flutter widget 类型的点击: | Widget 类型 | 描述 | |-------------|-------------| | **ElevatedButton** | Material Design 浮起按钮 | | **TextButton** | Material Design 文本按钮(扁平按钮) | | **OutlinedButton** | Material Design 轮廓按钮 | | **FilledButton** | Material Design 填充按钮 | | **IconButton** | 带有图标的图标按钮 | | **ListTile** | 列表中的单行,带有可选的前置/后置组件 | | **GestureDetector** | 自定义手势检测器 widget | | **InkWell** | Material InkWell widget | > **提示**:自动埋点功能可以大幅减少手动编码工作量,但会增加一定的数据量。建议根据实际需求选择性开启。 ## 注意事项 ### 性能优化 - 避免在循环中频繁调用 `trackEvent`,建议合并事件或使用节流 - 批量发送功能默认已开启,可有效减少网络请求 - 自动埋点会增加一定性能开销,仅在需要时开启 ### 数据安全 - 不要在事件属性中传递敏感信息(如密码、信用卡号、身份证号) - Source Token 应妥善保管,避免在公开代码仓库中暴露 ### 初始化时机 SDK 的 `init` 方法是**同步的**并立即返回。实际初始化(从存储加载数据、收集设备信息)在后台进行。您可以在 `init()` 返回后立即调用其他 SDK 方法。 ```dart void main() { WidgetsFlutterBinding.ensureInitialized(); final sdk = SensorsWaveSDK(); sdk.init('YOUR_SOURCE_TOKEN'); // 同步,立即返回 // 可以立即使用 sdk.trackEvent('APP_READY'); runApp(MyApp()); } ``` ### 常见问题 #### `identify()` 和 `setLoginId()` 之间有什么区别? **区别**: - `identify()`:设置登录 ID 并向后端发送 `$Identify` 绑定事件。在用户登录时使用。 - `setLoginId()`:仅在本地设置登录 ID,不发送事件。当您需要更新 ID 但不想触发绑定事件时使用。 #### 什么时候应该禁用 `autoCapture`? 在以下情况下禁用 `autoCapture`: - 您想要完全控制追踪哪些事件 - 您只想追踪特定的自定义事件 - 您需要实现自定义页面浏览追踪逻辑 - 您希望最小化性能影响 #### `batchSend: true` 和 `batchSend: false` 之间有什么区别? **区别**: - `batchSend: true`(默认):事件排队并批量发送(每 5 秒最多 10 条事件)。更好的性能和网络效率。 - `batchSend: false`:每个事件立即发送。更好的实时分析,但使用更多网络请求。 #### 如何在开发期间测试 SDK? 1. 启用调试模式:`sdk.init('your-token', config: SensorsConfig.create(debug: true))` 2. 检查控制台日志的事件追踪详情 3. 验证事件已发送到您的分析仪表板 4. 使用与生产环境分离的测试源令牌 ## 完整示例 以下是展示如何将 SDK 集成到 Flutter 应用中的完整示例: ```dart void main() { WidgetsFlutterBinding.ensureInitialized(); // 初始化 SDK(同步,立即返回) final sdk = SensorsWaveSDK(); sdk.init('your-source-token', config: SensorsConfig.create( debug: false, autoCapture: true, enableAB: true, enableClickTrack: true, batchSend: true, )); runApp(MyApp()); } class MyApp extends StatelessWidget { final sdk = SensorsWaveSDK(); @override Widget build(BuildContext context) { return MaterialApp( title: 'My App', // 添加路由观察者以进行自动页面追踪 navigatorObservers: sdk.routeObserver != null ? [sdk.routeObserver!] : [], home: HomePage(), ); } } class HomePage extends StatelessWidget { final sdk = SensorsWaveSDK(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Home')), body: Column( children: [ ElevatedButton( onPressed: () { // 追踪自定义事件 sdk.trackEvent('ButtonClick', { 'button_name': 'get_started', 'page': 'home', }); }, child: Text('Get Started'), ), ElevatedButton( onPressed: () async { // 检查特性开关 final showNewFeature = await sdk.checkFeatureGate('new_dashboard'); if (showNewFeature) { Navigator.push(context, MaterialPageRoute( builder: (_) => NewDashboardPage(), )); } else { Navigator.push(context, MaterialPageRoute( builder: (_) => OldDashboardPage(), )); } }, child: Text('Go to Dashboard'), ), ], ), ); } } class LoginPage extends StatefulWidget { @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State { final sdk = SensorsWaveSDK(); void handleLogin(String email, String password) { // 您的登录逻辑在这里 // ... // 成功登录后,识别用户 sdk.identify(email); } @override Widget build(BuildContext context) { // 您的登录 UI 在这里 return Container(); } } ``` ## 相关文档 - [埋点方案选择](../tracking-strategy.mdx):了解服务端埋点和客户端埋点的优劣 - [如何正确的标识用户](../user-identification.mdx):用户身份识别的最佳实践 - [数据模型](../data-model.mdx):理解 Sensors Wave 的数据结构 - [事件和属性](../events-and-properties.mdx):事件设计规范和最佳实践 --- **最后更新时间**:2026 年 3 月 12 日 **许可证**:Apache-2.0