Android无埋点的技术选型之路

数极客是国内新一代用户行为分析平台,支持无埋点采集,前端代码埋点采集,后端代码埋点采集等多种混合数据采集方式,支持30多种数据可视化效果,是增长黑客必的备大数据分析工具,支持APP分析数据网站分析用户画像,独创了6大转化率分析模型,的英文用户行为分析领域首家应用定量分析与定性分析方法的数据分析产品,运用数极客用户行为录屏系统,可以分析并优化用户体验的细节,基于用户行为分析系统- ,了提供会员营销系统- A / B测试工具两大数据智能应用解决方案,企业使得可以快速的实现数据驱动增长。

欢迎关注数极客微信公众号:shujujike,更全面的获取无埋点及用户行为大数据分析的要点。

原创作者:杨永强数极客技术合伙人

 

概述

无埋点也叫全埋点、自动埋点,无埋点就是指不需要开发人员添加任何代码,就可以实现数据的采集。

换句话说也就是在我们需要采集数据的位置插入采集数据的代码,而这个插入采集代码的过程不需要我们手动去添加,而是自动实现插入,这就是无埋点。

用户行为数据,就是用户在操作app的过程中产生的行为,比如 打开页面 / 关闭页面 / 浏览页面 / 点击按钮 /退出后台 / 返回前台 等事件,这些行为事件连起来就能组成一个用户的行为事件链条,这个链条可以理解为这个用户的行为数据。

 

、技术方案对比

1.1 几种无埋点实现方案介绍

1.2 处理时机对比

1.3 优缺点对比

二、实现ASM方案的准备知识

2.1 什么是AOP

2.2 gradle plugin的实现

2.3 Android app的编译过程

2.4 ASM介绍

三、 ASM方案实现方法

3.1实现gradle plugin

3.2通过ASM实现hook代码

3.3根据业务逻辑实现自己的SDK代码

四、总结

 

、技方案

1.1 几种无埋点实现方案介绍

在做无埋点技术选型时,我们对以下几种主流Android 无埋点方案进行对比:

AspectJ 方案

Aspectj 是它有一套自己的Java编译器,当我们用这个编译器进行编译时Aspectj会根据自己的方式进行代码插入,从而实现在编译期间插入埋点代码。

可参考:

利用AspectJ实现Android端非侵入式埋点

AspectJ in Android (一),AspectJ 基础概念

AspectJ in Android (二),AspectJ 语法

AspectJ in Android (三),AspectJ 两种用法以及常见问题

 

AST 方案

当IDE对项目code进行编译时,最先进行的是对源代码进行编译从而生成 .java 文件。

此方案就是利用这个时机,通过自定义注解器(APT)来切入我们需要插入代码的点,再通过AST的语法来插入埋点代码。

可参考:

Android AOP 抽象语法树

基于AST的组件化自动插桩方案

 

Javassist 方案

在Android app编译的过程中,.class 最终会转换为 .dex 文件,gradle 在编译的过程中 允许开发人员通过gradle plugin来修改class文件。这样就可以利用 Javassist 来修改 .class 字节码文件,从而实现插入埋点代码的目的。

可参考:

Javassist 使用指南 1 

Javassist 使用指南 2

 

ASM  方案

ASM和 Javassist 原理基本一样,只是在操作.class 文件时用的是ASM。

本文将主要介绍此种方式。

 

1.2 处理时机对比

https://img-blog.csdnimg.cn/20181218123205721.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmc2OTI1ODk3Mw==,size_16,color_FFFFFF,t_70

 

 

1.3 优缺点对比

https://img-blog.csdnimg.cn/20181218155804418.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmc2OTI1ODk3Mw==,size_16,color_FFFFFF,t_70

AspectJ 功能非常强大,使用起来也很方便,但是其不支持三方库的修改,所以果断放弃。

AST 对于不了解语法树 /注解 这些相对晦涩的知识点的不建议使用,后期维护起来非常不便,遂放弃。

Javassist 和 ASM两者原理基本一样,只是在后期操作字节码时 ASM 比 Javassist性能更好,因为javassist用到反射,所以性能上有牺牲。ASM是非常底层的,操作起来难度大,但是性能非常优秀。作为三方SDK,对源代码的侵入程度和性能要求非常严格,所以最终选择ASM方案。

 

二、实现ASM方案的准

2.1 什么是AOP

AOP 面向切向编程(Aspect Oriented Programming)与之对应的是OOP(ObjectOriented Programming)面向对象编程。

也可以自行Google,不再赘述。

2.2 gradle plugin的实现

Android Gradle Plugin 版本在1.5.0及以上,Google 官方提供了可以通过实现Plugin<Project> 接口,来实现编译成dex文件之前来修改.class 文件。

2.3 Android app的编译过程

 

 

2.4 ASM介绍

ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。

ASM相关可以参考:ASM 开发指导

三、 ASM方案实现方法

3.1实现gradle plugin

实现Plugin<Project>接口

https://img-blog.csdnimg.cn/20181218153911412.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmc2OTI1ODk3Mw==,size_16,color_FFFFFF,t_70

继承 Transform 

https://img-blog.csdnimg.cn/20181218154829551.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmc2OTI1ODk3Mw==,size_16,color_FFFFFF,t_70

对于transform API 不熟悉的可以查看API

最核心的代码就是遍历所有的class文件

https://img-blog.csdnimg.cn/2018121816511159.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmc2OTI1ODk3Mw==,size_16,color_FFFFFF,t_70

3.2通过ASM实现hook代码

在ASM的核心实现中,它主要有以下几个类、接口(在org.objectweb.asm包中)。

ClassReader类:字节码的读取与分析引擎。它采用类似SAX的事件读取机制,每当有事件发生时,调用注册的ClassVisitor、AnnotationVisitor、FieldVisitor、MethodVisitor做相应的处理。

ClassVisitor接口:定义在读取Class字节码时会触发的事件,如类头解析完成、注解解析、字段解析、方法解析等。

AnnotationVisitor接口:定义在解析注解时会触发的事件,如解析到一个基本值类型的注解、enum值类型的注解、Array值类型的注解、注解值类型的注解等。

FieldVisitor接口:定义在解析字段时触发的事件,如解析到字段上的注解、解析到字段相关的属性等。

MethodVisitor接口:定义在解析方法时触发的事件,如方法上的注解、属性、代码等。

ClassWriter类:它实现了ClassVisitor接口,用于拼接字节码。

AnnotationWriter类:它实现了AnnotationVisitor接口,用于拼接注解相关字节码。

FieldWriter类:它实现了FieldVisitor接口,用于拼接字段相关字节码。

MethodWriter类:它实现了MethodVisitor接口,用于拼接方法相关字节码。

SignatureReader类:对类定义、字段定义、方法定义、本地变量定义的签名的解析。Signature因范型引入,用于存储范型定义时的元数据(因为这些元数据在运行时会被擦除)。

SignatureVisitor接口:定义在解析Signature时会触发的事件,如正常的Type参数、类或接口的边界等。

SignatureWriter类:它实现了SignatureVisitor接口,用于拼接范型相关字节码。

Attribute类:字节码中属性的类抽象。

ByteVector类:字节码二进制存储的容器。

Opcodes接口:字节码指令的一些常量定义。

Type类:类型相关的常量定义以及一些基于其上的操作。

http://www.blogjava.net/images/blogjava_net/dlevin/ASM_Core.jpg

参考: ASM 源码解析  ,http://www.blogjava.net/DLevin/archive/2014/06/25/414292.html

 

步骤

1.通过ClassReader 读取class 文件

2.通过ClassWriter来修改class 文件,修改时需要用到ClassVisitor /MethodVisitor来访问class 内部的成员 方法,再通过相关API来插入埋点代码

https://img-blog.csdnimg.cn/20181218171629709.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmc2OTI1ODk3Mw==,size_16,color_FFFFFF,t_70

3.3根据业务逻辑实现自己的SDK代码

当hook成功后,剩下的就是自己根据业务逻辑去实现相关代码,此处不赘述。

四、总结

本文是从宏观上介绍无埋点的几种技术,和ASM的实现思路,希望能对无埋点有一个全局的认识。

 

猜你喜欢

转载自blog.csdn.net/yang69258973/article/details/85244845