导读:全埋点,也叫无埋点、无码埋点、无痕埋点、自动埋点。全埋点是指无需 Android 应用程序开发工程师写代码或者只写少量的代码,就能预先自动收集用户的所有行为数据,然后就可以根据实际的业务分析需求从中筛选出所需行为数据并进行分析。
作者:神策数据
如需转载请联系大数据(ID:hzdashuju)
全埋点采集的事件目前主要包括下面四种(事件名称前面的 $ 符号,是指该事件是预置事件,与之对应的是自定义事件):
在采集的这四种事件当中,最重要并且采集难度最大的是 $AppClick 事件。
所以,全埋点的解决方案基本上也都是围绕着如何采集 $AppClick 事件的。
对于 $AppClick 事件的全埋点整体解决思路,归根结底,就是要自动的找到那个被点击控件的点击处理逻辑(我们后文也会叫原处理逻辑),然后再利用一定的技术原理,对原处理逻辑进行“拦截”,或者在原处理逻辑的执行前面或执行者后面“插入”相应的埋点代码逻辑,从而达到自动埋点的效果。
至于如何做到自动“拦截” 控件的原处理逻辑,一般都是参考 Android 系统的事件处理机制来进行的。关于 Android 系统的事件处理机制,由于篇幅有限,不再详述。
本文来主要介绍 $AppClick 全埋点方案:AST,更多全埋点方案请关注《Android 全埋点解决方案》一书。
01 关键技术
1. APT
APT 是 ANNOTATION PROCESSING TOOL 的缩写,即注解处理器,是一种处理注解的工具。确切的说它是JAVAC的一个工具,它用来在编译时扫描和处理注解。注解处理器以JAVA代码(或者编译过的字节码)作为输入,生成 .JAVA文件作为输出。简单来说就是在编译期,通过注解生成 .JAVA文件。
2. Element
自定义注解处理器,需要继承 AbstractProcessor 类。而 AbstractProcessor 最重要的就是 process 方法。process 方法处理的核心是 Element 对象。
我们下面详细的介绍一下 Element 对象。
Element的完整源码如下。
package javax.lang.model.element;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Set;
import javax.lang.model.AnnotatedConstruct;
import javax.lang.model.type.TypeMirror;
public interface Element extends AnnotatedConstruct {
TypeMirror asType();
ElementKind getKind();
Set<Modifier> getModifiers();
Name getSimpleName();
Element getEnclosingElement();
List<? extends Element> getEnclosedElements();
boolean equals(Object var1);
int hashCode();
List<? extends AnnotationMirror> getAnnotationMirrors();
<A extends Annotation> A getAnnotation(Class<A> var1);
<R, P> R accept(ElementVisitor<R, P> var1, P var2);
}
从以上定义可以看出, Element 其实就是一个接口,它定义了外部可以调用的几个方法。
我们下面简单的介绍一下它规定的一些常用方法。
Element 有 5 个直接子类,它们分别代表一种特定类型的元素。五个子类各有各的用处并且有各种独有的方法,在使用的时候可以强制将Element对象转换成其中的任何一种,但是必须满足转换的条件,不然会抛出异常。
其中 TypeElement 和 VariableElement 是最核心的两个 Element,也是我们下文会使用到的。
3. APT实例
我们下面来讲解一个关于 APT 实例。
我们通过 APT 来实现一个功能,功能类似于 ButterKnife 中的 @BindView 注解。即通过对 View 变量的注解,实现对 View 的绑定(无需调用 findViewById 方法)。
完整的项目源码可以参考:
https://github.com/wangzhzh/AutoTrackAPTProject
4. AST
我们下面讲解一下什么是 AST。
AST,是 Abstract Syntax Tree 的缩写,即“抽象语法树”,是编辑器对代码的第一步加工之后的结果,是一个树形式表示的源代码。源代码的每个元素映射到一个节点或子树。
Java 的编译过程可以分成三个阶段,参考图11-5。
▲图11-5 编译过程
02 原理概述
编辑器对代码处理的流程大概是:
JavaTXT->词语法分析-> 生成AST ->语义分析 -> 编译字节码
通过操作AST,可以达到修改源代码的功能。
可以在自定义注解处理器的 process 方法里,通过 roundEnvironment.getRootElements() 方法可以拿到所有的 Element 对象,通过 trees.getTree(element) 方法可以拿到对应的抽象语法树(AST),然后我们自定义一个 TreeTranslator,在 visitMethodDef 里即可对方法进行判断。
如果是目标处理方法,则通过 AST 框架的相关 API 即可插入埋点代码,从而实现全埋点的效果。
03 案例
下面以自动采集 Android 的 Button点击事件为例,详细介绍该方案的实现。对于其它控件的自动采集,后面会进行扩展。
完整的项目源码可以参考:
https://github.com/wangzhzh/AutoTrackAppClick8
04 缺点
关于作者:国内知名大数据公司神策数据出品,作者王灼洲是神策数据合肥研发中心负责人,有近10年Android开发经验,开发和维护着知名商用开源 Android & iOS 数据埋点 SDK。
延伸阅读《Android 全埋点解决方案》
点击上图了解及购买
转载请联系微信:DoctorData
推荐语:10年Andriod开发经验专家撰写,8种Android全埋点技术方案,附源码。适读人群:适用于初级、中级、高级水平的Android 开发工程师、技术经理、技术总监等。