Title: Harmony SDK Locale: zh URL: https://sensorswave.com/docs/data-integration/client-sdks/harmony/ Description: Harmony SDK 集成指南和 API 参考 Sensors Wave HarmonyOS SDK 是专为鸿蒙应用设计的客户端数据采集和 AB 实验工具,支持 API 10+ (HarmonyOS 4.0+),采用 Stage 模型架构。 ## 核心功能 HarmonyOS SDK 提供以下核心能力: - **事件追踪**:手动追踪自定义事件和用户行为 - **自动埋点**:自动采集应用生命周期事件和页面浏览事件 - **点击采集**:支持组件点击事件的自动追踪 - **用户识别**:支持匿名用户和登录用户身份关联 - **用户属性管理**:完整的用户属性操作(设置、追加、增量更新等) - **A/B 测试集成**:支持功能开关(Feature Gate)和实验变量获取 - **同步调用**:除 AB 测试外,所有方法均为同步调用,立即返回 - **批量发送**:优化网络请求性能,自动批量发送事件 ## 系统要求 - **DevEco Studio**:4.0+ - **HarmonyOS API**:10+ (HarmonyOS 4.0+) - **开发语言**:ArkTS - **应用模型**:Stage 模型 ## 安装 ### OHPM 安装 通过 OHPM 安装 SDK: ```bash ohpm install @sensorswave/harmony-sdk ``` 或在项目的 `oh-package.json5` 中添加依赖: ```json5 { "dependencies": { "@sensorswave/harmony-sdk": "^latest" } } ``` ### 配置权限 在模块的 `src/main/module.json5` 中添加必要的权限: ```json5 { "module": { "requestPermissions": [ { "name": "ohos.permission.INTERNET", "reason": "$string:internet_permission_reason", "usedScene": { "abilities": ["EntryAbility"], "when": "always" } }, { "name": "ohos.permission.GET_NETWORK_INFO", "reason": "$string:network_info_permission_reason", "usedScene": { "abilities": ["EntryAbility"], "when": "always" } }, { "name": "ohos.permission.GET_WIFI_INFO", "reason": "$string:wifi_info_permission_reason", "usedScene": { "abilities": ["EntryAbility"], "when": "always" } } ] } } ``` **权限说明**: - `ohos.permission.INTERNET`:必需权限,允许应用访问网络 - `ohos.permission.GET_NETWORK_INFO`:必需权限,允许应用获取网络信息 - `ohos.permission.GET_WIFI_INFO`:可选权限,允许应用获取 WIFI 信息 ## 快速开始 ### 基础初始化 在 `UIAbility` 的 `onCreate` 方法中初始化 SDK: ```typescript onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { // 初始化 SDK(同步调用,立即返回) Sensorswave.getInstance().init('your-source-token', { apiHost: 'https://your-api-host.com', context: this.context, debug: false, autoCapture: true }); } } ``` > **提示**:除 AB 测试相关 API 外,所有 SDK 方法均为**同步调用**,立即返回。事件会自动入队并在后台发送。 ### 发送第一个事件 初始化完成后,您可以立即开始上报事件: ```typescript // 追踪按钮点击事件 Sensorswave.getInstance().trackEvent('button_click', { button_name: 'submit', page: 'home' }); ``` ## 配置选项 `init` 方法的第二个参数是配置对象,支持以下选项: | 配置项 | 类型 | 默认值 | 说明 | |--------|------|--------|------| | `sourceToken` | `string` | *必填* | 数据接收 Token | | `apiHost` | `string` | *必填* | 数据上报服务器地址 | | `context` | `Context` | *必填* | 应用上下文(用于获取应用信息) | | `debug` | `boolean` | `false` | 是否开启调试模式 | | `autoCapture` | `boolean` | `true` | 是否自动采集预置事件(生命周期事件) | | `enableClickTrack` | `boolean` | `false` | 是否开启点击自动采集 | | `batchSend` | `boolean` | `true` | 是否使用批量发送 | | `enableAB` | `boolean` | `false` | 是否开启 A/B 测试功能 | | `abRefreshInterval` | `number` | `600000` | A/B 测试配置刷新间隔(毫秒),默认 10 分钟 | ### 完整配置示例 ```typescript Sensorswave.getInstance().init('your-source-token', { apiHost: 'https://your-api-host.com', context: this.context, debug: true, // 开发环境开启调试 autoCapture: true, // 开启自动埋点 enableClickTrack: true, // 开启点击追踪 batchSend: true, // 批量发送优化性能 enableAB: true, // 开启 A/B 测试 abRefreshInterval: 10 * 60 * 1000 // A/B 测试数据每 10 分钟刷新 }); ``` ## API 方法 ### 事件追踪 所有追踪方法均为**同步调用**,立即返回。事件会自动入队并在后台发送。 #### trackEvent - 追踪自定义事件 发送自定义事件,支持添加自定义属性。 **参数**: - `event` (string,必填):事件名称 - `properties` (Record,可选):事件属性 **示例**: ```typescript // 电商场景:用户浏览商品 Sensorswave.getInstance().trackEvent('product_view', { product_id: '12345', product_name: '无线蓝牙耳机', category: '电子产品', price: 299.00 }); ``` #### track - 高级事件追踪 发送完整自定义事件数据,支持更精细的控制。 **参数**: - `eventData` (SensorswaveSendEvent,必填):完整事件对象 - `event` (string,必填):事件名称 - `properties` (Record,可选):事件属性 - `time` (number,必填):时间戳(毫秒) - `trace_id` (string,可选):请求追踪 ID - `anon_id` (string,可选):匿名用户 ID **示例**: ```typescript Sensorswave.getInstance().track({ event: 'product_view', properties: { product_id: '12345', source: 'search' }, time: Date.now(), trace_id: 'custom-trace-id', anon_id: 'custom-anon-id' }); ``` ### 用户识别 所有用户身份方法均为**同步调用**。 #### identify - 设置登录用户 ID 设置当前用户的登录 ID,并发送绑定事件将匿名行为与已识别用户关联。 **参数**: - `loginId` (string,必填):用户唯一标识(如邮箱、用户 ID、用户名) **示例**: ```typescript // 用户登录后设置用户 ID Sensorswave.getInstance().identify('user_12345'); ``` **完整登录流程示例**: ```typescript async function handleUserLogin(email: string, password: string) { try { // 调用登录 API const response = await fetch('/api/login', { method: 'POST', body: JSON.stringify({ email, password }) }); const { userId } = await response.json(); // 设置用户 ID 并关联匿名行为 Sensorswave.getInstance().identify(userId); } catch (error) { console.error('登录失败:', error); } } ``` > **重要提醒**:如果 `loginId` 包含隐私信息(如手机号、邮箱、身份证号等),请务必在加密后再进行传输,避免敏感信息明文上报。 #### setLoginId - 仅设置登录 ID 设置当前用户的登录 ID,不发送绑定事件。 **参数**: - `loginId` (string,必填):用户唯一标识 **示例**: ```typescript Sensorswave.getInstance().setLoginId('user_12345'); ``` > **重要提醒**:如果 `loginId` 包含隐私信息(如手机号、邮箱、身份证号等),请务必在加密后再进行传输,避免敏感信息明文上报。 #### getAnonId - 获取匿名用户 ID 获取匿名用户 ID。 **返回值**:string(同步) ```typescript const anonId = Sensorswave.getInstance().getAnonId(); ``` #### getLoginId - 获取登录用户 ID 获取登录用户 ID。 **返回值**:string(同步) ```typescript const loginId = Sensorswave.getInstance().getLoginId(); ``` ### 用户属性 所有用户属性方法均为**同步调用**,立即返回。属性会自动入队并在后台发送。 #### profileSet - 设置用户属性 设置用户属性,如果属性已存在则覆盖。 **参数**: - `properties` (Record,必填):用户属性 **示例**: ```typescript // 用户完成注册后,设置用户属性 Sensorswave.getInstance().profileSet({ name: '张三', age: 30, plan: 'premium' }); ``` #### profileSetOnce - 仅首次设置 设置用户属性,仅在属性不存在时设置,已存在的属性不会被覆盖。 **参数**: - `properties` (Record,必填):用户属性 **示例**: ```typescript // 记录用户首次访问信息(仅记录一次,后续不会覆盖) Sensorswave.getInstance().profileSetOnce({ signup_date: '2024-01-15', initial_referrer: 'google', initial_campaign: 'spring_sale' }); ``` #### profileIncrement - 增量更新数值属性 对数值类型的用户属性进行增减操作。仅支持数值属性。 **参数**: - `properties` (Record,必填):数值属性 **示例**: ```typescript // 增加登录次数和积分 Sensorswave.getInstance().profileIncrement({ login_count: 1, points_earned: 100, purchases_count: 1 }); ``` #### profileAppend - 追加到数组属性 向数组类型的用户属性追加新值,不进行去重。 **参数**: - `properties` (Record,必填):列表属性 **示例**: ```typescript // 追加浏览分类和标签(不去重) Sensorswave.getInstance().profileAppend({ categories_viewed: ['电子产品', '手机'], tags: ['新用户', '2024Q1'] }); ``` #### profileUnion - 追加到集合属性(去重) 向数组类型的用户属性追加新值,自动去重。 **参数**: - `properties` (Record,必填):列表属性 **示例**: ```typescript // 第一次调用 Sensorswave.getInstance().profileUnion({ interests: ['科技', '游戏'] }); // 第二次调用,'科技' 不会重复添加 Sensorswave.getInstance().profileUnion({ interests: ['科技', '音乐'] }); ``` #### profileUnset - 删除指定属性 将指定的用户属性设置为 null。 **参数**: - `properties` (string | string[],必填):属性名或属性名数组 **示例**: ```typescript // 删除单个属性 Sensorswave.getInstance().profileUnset('temporary_campaign'); // 删除多个属性 Sensorswave.getInstance().profileUnset(['old_plan', 'expired_flag', 'temp_id']); ``` #### profileDelete - 删除所有用户属性 删除当前用户的所有用户属性数据。此操作不可撤销。 **示例**: ```typescript // 用户注销账号时,删除所有用户属性 Sensorswave.getInstance().profileDelete(); ``` > **警告**:`profileDelete` 会删除所有用户属性,请谨慎使用。 #### 用户属性使用示例 **会员升级场景**: ```typescript function handleMembershipUpgrade(newPlan: string) { // 更新会员等级和升级时间 Sensorswave.getInstance().profileSet({ plan: newPlan, upgrade_time: new Date().toISOString() }); // 增加升级次数 Sensorswave.getInstance().profileIncrement({ upgrade_count: 1 }); // 追踪升级事件 Sensorswave.getInstance().trackEvent('membership_upgrade', { from_plan: 'basic', to_plan: newPlan }); } ``` ### 公共属性 所有公共属性方法均为**同步调用**。 #### registerCommonProperties - 注册公共属性 注册公共属性,所有事件都会自动包含这些属性。 **参数**: - `properties` (CommonProps,必填):公共属性 **示例**: ```typescript const commonProps = new CommonProps(); commonProps.set('app_version', '1.0.0'); commonProps.set('environment', 'production'); commonProps.set('user_tier', 'vip'); Sensorswave.getInstance().registerCommonProperties(commonProps); ``` #### clearCommonProperties - 清除公共属性 移除指定的已注册公共属性。 **参数**: - `propertyNames` (string[],必填):要移除的属性名数组 **示例**: ```typescript Sensorswave.getInstance().clearCommonProperties(['app_version', 'user_tier']); ``` > **注意**:公共属性会增加每个事件的数据量,建议仅添加确实需要的通用属性。 ### A/B 测试 HarmonyOS SDK 内置了 A/B 测试支持,可以获取功能开关状态和实验变量。 > **注意**:AB 测试方法是**异步调用**,需要网络请求。 #### 开启 A/B 测试功能 ```typescript Sensorswave.getInstance().init('your-source-token', { apiHost: 'https://your-api-host.com', context: this.context, enableAB: true, // 开启 A/B 测试 abRefreshInterval: 10 * 60 * 1000 // 配置刷新间隔(10 分钟) }); ``` #### checkFeatureGate - 检查功能开关 检查功能开关(Feature Gate)是否为当前用户启用。 **参数**: - `key` (string,必填):功能开关的 Key **返回值**:Promise **示例**: ```typescript // 检查功能是否启用 async function initFeature() { const isEnabled = await Sensorswave.getInstance().checkFeatureGate('new_checkout_flow'); if (isEnabled) { // 显示新功能 showNewCheckout(); } else { // 显示旧功能 showOldCheckout(); } } ``` #### getExperiment - 获取实验变量 获取当前用户的实验变量数据。 **参数**: - `key` (string,必填):实验的 Key **返回值**:Promise> **示例**: ```typescript // 获取实验配置 async function initExperiment() { const experiment = await Sensorswave.getInstance().getExperiment('homepage_layout'); if (experiment) { const { layout_type, color_scheme } = experiment; applyLayout(layout_type, color_scheme); } } ``` **完整 A/B 测试示例**: ```typescript // 首页布局 A/B 测试 async function initHomepageLayout() { try { const experiment = await Sensorswave.getInstance().getExperiment('homepage_layout'); if (experiment) { const { layout_type, color_scheme, card_size } = experiment; updateHomepageLayout(layout_type, color_scheme, card_size); } } catch (error) { console.error('获取实验变量失败:', error); // 使用默认配置 } } // 页面加载时初始化 initHomepageLayout(); ``` > **提示**:A/B 测试功能需要在 Sensors Wave 后台配置实验和功能开关后才能使用。 ## 自动埋点 ### 预置事件 当 `autoCapture: true`(默认值)时,SDK 会自动采集以下预置事件: **生命周期事件**: | 事件名 | 触发时机 | 专属属性 | |--------|----------|----------| | `$AppInstall` | 首次启动应用 | - | | `$AppStart` | 应用进入前台 | `$screen_name` | | `$AppEnd` | 应用进入后台 | `$screen_name`、`$event_duration` | | `$AppPageView` | 页面显示 | `$screen_name`、`$title`、`$url` | | `$AppPageLeave` | 页面隐藏 | `$screen_name`、`$title`、`$url`、`$event_duration` | **点击事件**(`enableClickTrack` 启用时): | 事件名 | 触发时机 | 专属属性 | |--------|----------|----------| | `$AppClick` | 点击控件 | `$screen_name`、`$element_type`、`$element_id`、`$element_content`、`$element_position`、`$element_selector` | ### 导航支持 SDK 通过 UIObserver 监听页面切换事件,实现 `$AppPageView` 和 `$AppPageLeave` 的自动触发。 **支持的导航方式**: | 导航方式 | 支持情况 | 说明 | 示例 | |---------|---------|------|------| | **Router** | ✅ 完全支持 | 传统 Router 导航方式 | `router.pushUrl()` | | **Navigation** | ✅ 完全支持 | HarmonyOS Navigation 组件 | `NavDestination` | | **组件状态** | ❌ 不支持 | 通过 `@State` 变量切换页面 | 条件渲染 | #### Router 导航示例 ```typescript // 页面跳转 router.pushUrl({ url: 'pages/DetailPage', params: { id: '123' } }); // 返回上一页 router.back(); ``` #### Navigation 组件示例 ```typescript @Entry @Component struct Index { private navStack: NavPathStack = new NavPathStack(); build() { Navigation(this.navStack) { // 页面内容 } .navDestination((name: string, params: ESObject) => { // NavDestination 页面 }) } } ``` > **注意**:如果使用组件状态导航(如 `@State currentPage` 切换页面),SDK **无法**自动触发页面浏览事件。建议使用 Router 或 Navigation 组件以实现完全自动的页面追踪。 ### $AppClick 事件详情 SDK 使用 UIObserver 的 `willClick` 事件自动采集组件点击事件,采用**黑名单机制**过滤输入类组件。 **支持的组件类型示例**: - **交互组件**:Button、Toggle、Checkbox、Radio、Slider、Rating - **容器组件**:Stack、Row、Column、Flex、Grid、List、Scroll - **媒体组件**:Image、Text、Span、ImageAnimator - **导航组件**:Navigator、Tabs、Divider、Panel > **重要说明**: > 1. 所有支持点击事件的组件都会被自动采集(包括自定义的可点击容器) > 2. 对于 Dialog、Menu/Option、TabBar 等组件,可能无法采集 `$element_content` 属性 **启用方式**: ```typescript Sensorswave.getInstance().init('your-source-token', { context: this.context, enableClickTrack: true // 启用点击自动采集 }); ``` > **注意**:`enableClickTrack` 默认为 `false`,需要显式开启。 ## 预置属性 SDK 会自动采集以下预置属性: **SDK 相关**: - `$lib`:固定值 "harmony" - `$lib_version`:SDK 版本号 **设备相关**: - `$manufacturer`:设备制造商 - `$model`:设备型号 - `$os`:固定值 "HarmonyOS" - `$os_version`:系统版本号 - `$screen_width`:屏幕宽度 - `$screen_height`:屏幕高度 **App 专属**: - `$network_type`:网络类型(wifi、4G、5G 等) - `$wifi`:是否 WiFi 网络 - `$app_version`:应用版本号 - `$app_id`:应用 ID - `$app_name`:应用名称 - `$brand`:设备品牌 **通用**: - `$timezone_offset`:时区偏移 - `$language`:系统语言 ## 注意事项 ### 同步调用特性 除 AB 测试相关 API 外,所有 SDK 方法均为**同步调用**,立即返回。事件会自动入队并在后台发送。这意味着: - 不会阻塞 UI 线程 - 调用后可立即执行后续代码 - 事件数据会自动批量发送 ### 性能优化 - 避免在循环中频繁调用 `trackEvent`,建议合并事件或使用节流 - 批量发送功能默认已开启,可有效减少网络请求 - 自动埋点和点击追踪会增加一定性能开销,仅在需要时开启 ### 数据安全 - 不要在事件属性中传递敏感信息(如密码、信用卡号、身份证号) - Source Token 应妥善保管,避免在公开代码仓库中暴露 - 确保数据上报地址使用 HTTPS 协议 ### 数据丢失风险 - 客户端埋点可能受网络环境、应用被强制关闭等因素影响,存在一定的数据丢失风险 - 核心业务数据建议使用服务端埋点,详见 [埋点方案选择](../tracking-strategy.mdx) ## 常见问题 ### 为什么我的数据没有上报成功? 检查以下几点: 1. **Source Token 是否正确**:确认 `sourceToken` 参数是否正确 2. **数据上报地址是否正确**:确认 `apiHost` 配置是否正确 3. **网络权限**:确认已在 `module.json5` 中添加网络权限 4. **网络连接**:开启 `debug: true` 查看控制台日志 5. **系统版本**:确认设备系统版本为 API 10+ (HarmonyOS 4.0+) ### 如何避免在开发环境发送数据? ```typescript // 根据构建配置决定是否初始化 SDK const isDebug = true; // 实际项目中可根据构建环境获取 if (!isDebug) { Sensorswave.getInstance().init('your-source-token', { apiHost: 'https://your-api-host.com', context: this.context }); } ``` ## 相关文档 - [埋点方案选择](../tracking-strategy.mdx):了解服务端埋点和客户端埋点的优劣 - [如何正确的标识用户](../user-identification.mdx):用户身份识别的最佳实践 - [数据模型](../data-model.mdx):理解 Sensors Wave 的数据结构 - [事件和属性](../events-and-properties.mdx):事件设计规范和最佳实践 --- **最后更新时间**:2026 年 3 月 13 日 **许可证**:Apache-2.0