HarmonyOS鸿蒙Next埋点总结
HarmonyOS鸿蒙Next埋点总结
背景
关于脚本埋点,在上一篇文章有所实践,当时主要是验证一下脚本动态修改源码埋点的可行性,结论是可行的。
本篇是对完善之后的脚本做个总结。
初衷
为实现基本页面生命周期追踪和点击行为追踪,能够快捷的在项目中实现基础数据采集。
可惜HarmonyOS没有对应用开发者提供自定义transformer的功能
在TypeScript语言中,可以采用自定义装饰器和AST(Abstract Syntax Tree)两种方式来提高基础埋点效率。
备注
实践下来,采用AST方式操纵代码修改,暂时能想到的方法就是另外开一个工程,专门用于自动化源码埋点
1. 解析源文件结构
脚本埋点,需要首先要能正确的解析源文件结构
1.1 注释解析
HarmonyOS UI层文件均遵循的是TypeScript语言注释规则
1.1.1 多行注释
以 /*
开头,以 */
结尾,两个标识都十分容易通过程序辨识
1.1.2 单行注释
以 //
开头
1.1.3 数据结构
注释解析完成后,仅仅需要将其位置存储下来。因此可定义一个基础代码通用数据结构
class CodeIndex{
public startIndex: number = 0
public endIndex: number = 0
constructor(s: number, e: number) {
this.startIndex = s
this.endIndex = e
}
}
由于整个解析过程都是在“hvigorfile.ts”文件中完成的,这里直接定义两个注释变量,如下:
//多行注释
let mulCodeIndex: CodeIndex[] = []
//单行注释
let singleCodeIndex: CodeIndex[] = []
对于这两个变量,可以只定义一个
对于多行注释和单行注释,在解析的先后顺序上,没有先后,因为两者的格式都可以相互被包含在对方内容中。
我是优先解析多行注释,原因是它解析起来相对比较简单
1.2 字符串解析
在TypeScript中,源码标识字符串的标识总共有三种
'
"
`
例如
let a: string = 'demo'
let b: string = "demo"
let c: string = `demo`
解析字符串的首要准备条件,必须确定字符串是以哪种标识表示的,所以在遍历过程中,遍历下标每移动一次,需要把三个标识全部查找一遍,然后由小到大排序,取最小下标,然后截取字符串。
同时基于注释范围,遍历过程中,需要忽略注释内的字符串。
1.3 类结构解析
每个以".ets"和".ts"结尾的文件,在其内部,可能出现多个类,例如
@Component
struct TestOne{
build(){
}
}
class TestTwo{
}
@Entry
@Component
struct TestThree{
build(){
}
}
通过观察上边的Test.ets文件可以发现,如果我们要在Test.ets中对@Component组件进行生命周期代码插入,可能就比较麻烦,因为有两个@Component
为了方便后续代码插入,还需要对文件中的类进行整体的结构化,结构化之前,需要清楚一个文件中,到底会出现哪些样式的类?
根据HarmonyOS SDK common.d.ts文件中的 “ClassDecorator” 类型可知,ArkTS中会出现的类有4种,
- @Entry
- @Component
- @Observed
- @CustomDialog
这4种装饰器修饰的类,其对应的关键词为"struct"
根据TypeScript语言规范可知,类的关键词为"class"
结构化文件,这里可以根据类的类型定义一个Map,从而达到能对一个文件中的多个类进行精准分割
let programClassMap: Map<string, CodeIndex[]> = new Map<string, CodeIndex[]>()
结构化之后,如果要在如上Test.ets文件中的@Component装饰类中进行变量定义,就可以使用如下形式进行每个类的代码遍历
let codeIndex: CodeIndex[] = programClassMap.get('@Component')
//开始遍历
......
至此3步,已基本可以确定整个源码结构,并且可以通过脚本对源码进行插入动作
2. 文件过滤
2.1 服务卡片
关于服务卡片的ets文件, 暂时无法引用自定义的埋点文件,因此必须对其过滤
根据HarmonyOS服务卡片开发指南可知,所有的服务卡片的UI配置均在 form_config.json 文件中
2.2 无@Component装饰器
由于这里做的埋点目标是页面生命周期和点击事件,所以在一个文件内,如果没有@Component装饰器,则忽略对文件进行后续操作
3. 埋点信息
3.1 页面生命周期
@Entry 和 @Component对应生命周期函数是不一样的,因此在代码插入时,需要分别处理
注意:一个 struct 类,可能同时被@Entry 和 @Component修饰,所以在插入代码中,需要依次判断
if(funName == 'onPageShow' || funName == 'onPageHide' || funName == 'onBackPress') {
// @Entry修饰的 struct 类
......
}
if(funName == 'aboutToAppear' || funName == 'aboutToDisappear') {
//@Component修饰的 struct 类
......
}
3.1.1 基础信息
这篇文章,针对生命周期,定义了5个基础数据
- 行为序列编号(即 每次从主模块主入口进入应用时的标识)
- 页面所属模块
- 页面所在的容器
- 页面所在的文件
- 生命周期名称
3.2 点击事件
onClick是HarmonyOS的一个通用API,这篇文章中的代码插入目标就是它。
onClick的参数是一个无返回值的方法
本篇文章仅针对箭头函数做代码插入
3.2.1 常见写法
//箭头函数
Text().onClick(() => console.log('箭头函数,无花括号'))
Text().onClick(() => {
console.log('箭头函数,带花括号')
})
function clickTest(){
console.log('测试点击')
}
Text().onClick(this.clickTest)
3.2.2 基础信息
这篇文章中,针对点击事件,定义了3个基础数据
- 行为序列编号(即 每次从主模块主入口进入应用时的标识)
- 事件被哪个文件消耗
- 事件被哪个onClick消耗
3.3 Entry模块入口
应用内的所有埋点信息,应该带有使用次数的概念,对于这个次数的定义,从程序来定义,即经过应用主入口算作一次。对应的文件,可以从entry模块中的module.json5文件中找到
所以,脚本执行开始时,需要在主入口文件中的 onCreate()方法中,插入一个唯一标识,我的脚本采用时间戳
private static startBootTime: number = 0
4. 脚本说明
4.1 API接口
- copyConfigFile
复制埋点文件至模块ets文件夹下 - initAppEntry
Entry模块主入口初始化埋点行为序号 - extractCodeIndex
提取注释,提取字符串,结构化文件中的类 - insertLifecycleFunction
插入生命周期埋点 - insertContentToOnClick
onClick函数增加埋点
结尾
埋点不是什么重点,“.hvigor/project_caches” 这个隐藏文件夹中的@ohos文件夹文件比较有意思。
当前这种埋点对于测试人员也是比较有利。
祝各位好运!
更多关于HarmonyOS鸿蒙Next埋点总结的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS鸿蒙Next埋点总结的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,埋点主要用于收集用户行为数据,以优化产品体验和功能。以下是埋点总结的关键点:
埋点类型:
- 页面埋点:记录用户访问的页面和停留时间。
- 事件埋点:记录用户操作,如点击、滑动等。
- 曝光埋点:记录内容的曝光次数。
埋点工具:
- 使用HarmonyOS提供的Analytics Kit,支持自动和手动埋点。
- 第三方工具如友盟、神策等也可集成。
埋点规范:
- 统一命名规则,确保数据一致性。
- 区分开发、测试和生产环境,避免数据污染。
数据安全:
- 遵守隐私政策,确保用户数据安全。
- 数据加密传输,防止泄露。
通过合理埋点,可以高效获取用户行为数据,为产品优化提供数据支持。