首先了解 Android应用程序的打包流程:
方案:在应用程序打包生成.dex文件前,拿到当前应用程序中所有的.class文件,然后借助相关代码库,就可以遍历这些 .class文件中的所有方法,再根据一定的条件找到需要埋点监控的目标方法,最后进行修改并保存,就可以实现埋点代码。
关键技术:
Gradle Transform
Gradle Transform 是Android官方提供给开发者在项目构建阶段(即由.class到.dex转换期间)用来修改.class文件的一套标准API。目前比较经典的应用是字节码插桩、代码注入等等。
功能介绍:将输入的 .class 文件转变成目标字节码文件。
TransformInput
.class 输入文件的抽象类,主要包括:
- DirectoryInput 集合
是指以源码方式参与项目编译的所有目录结构及其目录下的源码文件。
- JarInput 集合
是指以 jar 包方式参与项目编译的所有本地 jar包和远程 jar 包。(注:也包括 .aar)
- TransformOutputPorvider
是指 Transform 的输出,通过它可以获取输出路径等信息。
相关代码如下:
public abstract class Transform { |
getName
代表该 Transform 对应 Task 的名称,它会出现在 app/build/intermediates/transforms 目录下。
getInputTypes
指定 Transform 要处理的数据类型。目前主要是支持两种数据类型
CLASSES
表示要处理编译后的字节码,可能是 jar 包也可能是目录
RESOURCES
表示处理标准的 java 资源。
getScopes
指定 Transform 的作用域。常见的作用域有以下7种:
1)PROJECT
只处理当前项目
2)SUB_PROJECTS
只处理子项目
3)PROJECT_LOCAL_DEPS
只处理当前项目的本地依赖,例如:jar、aar
4)SUB_PROJECTS_LOCAL_DEPS
只处理子项目的本地依赖,例如:jar、aar
5)EXTERNAL_LIBRARIES
只处理外部的依赖库
6)PROVIEDE_ONLY
只处理本地或远程以 provided 形式引入的依赖库
7)TESTED_CODE
测试代码
isIncremental
是否是增量构建
ASM 框架几个核心的相关类
ClassLoader
该类主要用来解析编译过的.class字节码文件
ClassWriter
该类主要用来重新构建编译后的类,比如修改类名、属性以及方法,甚至可以生成新的类字节码文件
ClassVisitor
主要负责“拜访”类成员信息。其中包括标记在类上的注解、类的构造方法、类的字段、类的方法、静态代码块等等
重点需了解此类,其类结构如下
该类会按照一定的标准次序来遍历一个类中的所有成员。在ClassVisitor类中,我们可以根据实际的需求进行条件判断,只要满足我们的特定条件的类,我们才会去修改它的特定方法。比如我们自动采集Button控件的点击事件,那么只有实现了View$OnClickListener接口的类,我们才回去遍历这个类并找到重写的onClick(view)方法,然后进行修改操作并保存
AdviceAdapter
实现了 MethodVisitor 接口,主要负责“拜访”方法的信息,用来进行具体的方法字节码操作。