Android全埋点解决方案(AST)
阅读本文之前如果没有APT相关的知识,可以先阅读Butterknife原理
一、AST
AST,是抽象语法树,是编辑器对代码第一步加工之后的结果,是一个树形式表示的源代码。源代码的每个元素映射到一个节点或者子树。
java编译分为三个阶段
第一阶段:所有的源文件会被解析成语法树。
第二阶段:调用注解处理器,即APT模块。如果注解处理器产生了新的源文件,新的源文件也要参与编译。
第三个阶段:语法树会被分析并转化为类文件。
二、原理概述
编译器对代码的处理流程大概是:
javaText ->词语法分析->生成AST -> 语义分析->编译字节码
通过操作AST,可以达到修源代码的功能。
在自定义注解处理器的process方法里,通过roundEnvironment.getRootElements()方法可以拿到所有的Element对象,通过tree.getTree(element)方法可以拿到对应的抽象语法树(AST),然后我们自定义一个TreeTranslator,在visitMethodDef里即可对方法进行判断。如果是目标处理方法,则通过AST框架的相关API即可插入埋点代码,从而实现全埋点的效果。
三、实践
源码地址: https://github.com/yangzai100/ASTDemo/tree/master
1.创建一个项目,自动包含主module,即app。
2.创建Android module,名称叫做Sdk,这个模块就是我们的埋点SDK模块。
3.
-
SensorsDataAPI 是用来初始化埋点sdk的,里面track方法做些基本埋点信息和自动埋点信息的合并。
-
SensorsDataAutoTrackHelper 主要是给插件plugin使用的,用来自动埋点。
-
SensorsDataPrivate 前两个类需要的一些api的抽取类。
4.创建一个java library module,名称叫做:plugin。需要添加auto-service、toolsJar的依赖关系。
plugin.png -
SensorsAnalyticsPlugin这个类是个注解解析器,拿到整个编译文件的抽象语法树,交给SensorAnalyticsTreeTranslator处理。
-
SensorAnalyticsTreeTranslator 里面会判断是不是onClick方法,如果是通过 JCTree来插入埋点代码。
app中依赖一下sdk和plugin,初始化一下sdk。运行app,点击下控件,可以看到自动注入埋点信息。
2021-07-10 12:29:30.953 11518-11518/com.example.autotrackappclick8 I/SensorsDataAPI: {
"event":"$AppClick",
"device_id":"09489e623d0a879e",
"properties":{
"$lib":"Android",
"$os_version":"10",
"$app_name":"AutoTrackAppClick8",
"$lib_version":"v1.0.0",
"$model":"Android SDK built for x86",
"$os":"Android",
"$screen_width":1080,
"$screen_height":1794,
"$manufacturer":"Google",
"$app_version":"1.0",
"$elemeng_type":"TextView",
"$element_id":"tv",
"element_content":"Hello World!",
"$activity":"com.example.autotrackappclick8.MainActivity"
},
"time":1625891370950
}