前面提到了全自动埋点的范围和方法,这个章节主要记录一下关于点击事件采集的相关方法论。
Android开发基础知识
需要先说明几个基础的知识,这样对于无码采集的方法论理解就更清晰,这也是做一个事情分析的逻辑。
- Adnroid开发基于java代码(常规)
Android的基础语言是java语言,java语言的开发流程包括
java代码-class文件-运行 - Android安装包apk构建打包
是将上述class代码通过gradle构建打包成dex文件,然后签名输出成apk
Android事件机制
每一个应用有一个Application,每一个Application有多个Activity,一个Activity下有一个PhoneWindow,一个PhoneWindow下有DecorView,一个DecorView下的content就是我们开发的展示给用户的界面。一个界面由ViewGroup和View组成。借用一张经典的图:
我们设置的点击事件是在ViewGroup/View上设置类似setOnClicklistener来实现。
Android的事件分发机制简单来说会从Activity自上而下分发,然后看中间是否有消费的,具体不细说了。
采集方法一 - AOP技术
通过上述Android开发基础知识,我们应该就能想到这个方法,本身用户行为采集也是从切面去处理的,所以AOP技术的应用就自然而然了。
我们从构建流程往下分析,看一看AOP都有几种方式实现:
- APT - 注解处理器
先来一个简单的,我们在开发中经常遇到APT技术的使用,比如路由框架、EventBus等等。
APT的具体使用就不过多描述了,主要说下这里面的实现原理:
就是通过APT后,我们在处理器中可以拿到代码的抽象语法树(AST),这个又是一个技术点,然后通过操作语法树上的元素进行源码的修改,从而修改view的setOnClicklistener相关代码,插入我们的逻辑。 - AspectJ、Javassist
这两个也不难想到,本身就是对class文件的处理,通过这两个技术我们可以在代码编译的过程中修改class文件,同样找到目标view的方法,插入我们的采集代码,从而达到采集的目的。 - ASM
这个和上面两个类似,不过是Android常用的,通过使用Transform需要开发一个自定义的gradle plugin,然后再通过官方提供的相应工具来实现对于class文件的修改和编织。这个也常用在一些诸如采集App网络请求数据等一些实现上。
上述技术手段理解上难度不大,比较费时的是在具体代码拦截和替换注入上面,这个需要花费一定的功夫去研究里面的逻辑和处理方式,还要掌握一定的字节码相关知识。这个掌握之后以后对于一些自动化生成代码都比较有用。
采集方法二 - 代理
这个方法在我们分析Android屏幕组成和事件分发机制那块可以想到的,既然可以通过一系列方法获取到窗口的各个对象(Activity、PhoneWindow、View),加上事件的分发机制,所以我们可以罗列一下相应的采集手段。
- Window.Callback
我们通过代码分析,发现window对象下面可是设置Callback,实现接口之后有一个dispatchTouchEvent的回调方法,那我们通过代理这个接口(可能用到反射相关的技术),这样就可以获取到的用户当前点击的坐标,在通过对于ViewGroup和view的遍历,就可以查出来当前点击在哪一个view上。 - 透明层遮罩
通过上面的分析,我们获取到用户点击的位置就可以获取到对应点击的view,那是不是可以设置一个全屏透明的View插入在DecorView下面,这样是不是就可以实现获取用户点击行为。 - 代理View.onClickListener
既然我能遍历到具体的view,那我就可以通过反射等技术手段获取到View的onClickListener事件,通过代理包装这个事件,就达到了采集用户行为的目的。 - View.mAccessibilityDelegate
通过代理思路,我们又可以发现在开发一些辅助模式时可以在View上设置mAccessibilityDelegate,这个样子View被触摸之后就可以通过接口回调通知我们,也就能够采集到的用户点击的行为数据。
上面就是用户点击行为数据的采集方法论,有了方法论我们也需要分析一下对应的优缺点,做到心里有数。
无码采集方法对比
- AOP
缺点:
1、有一些AOP方法不能处理第三方库,比如APT技术
2、技术门槛有些高,后期改动维护需要高人支持
3、这会增加编译时长
有点:
1、当然增加的是编译时长,不是运行打开时长,影响力度可接受哈。
2、通用的技术,如果是java语言开发,兼容性小一些。 - 代理
缺点:
1、运行时代理,用到反射,会增加性能损耗。
2、反射就存在不同版本对应的对象或者API不一样,有兼容问题。
3、一些游离态的控件采集不到,因为主要是采用Application中监听Activity生命周期方式,有一些对话框、popwindow等无法监听到弹出,所以可能采集不到游离态控件(当然最终还是有办法去解决的,有机会再单独介绍这部分)。
优点:
1、其实就是简单,容易理解,从0搞一个难度不大(其实还需要考虑数据上报、数据缓存、异步线程采集等具体问题,所以从0搞一个还是需要些时间的)
其他问题
前面也提到了,全自动埋点数据量比较到,会采集很多数据,所以怎么样减少无效数据的采集也是摆在全自动采集方案中需要解决的一个问题。
同时还有另一个问题,全自动采集本身和业务关联不大,那么就需要通过技术手段为每一个元素view设置一个唯一的标识,而通过技术手段生成的唯一标识在业务人员看起来肯定无法理解(采集数据最终是给到业务人员使用的),所以这就是第二个需要解决的问题。
上面这两个问题有技术手段一并解决,业内通常的叫法就叫做圈选埋点,通过可视化全选的方式控制那些界面采集,那些界面不采集,以及可以给界面和元素生成业务可以理解的映射字段,这个样子也就让全埋点具体操作权放到业务运营人员手里了,由他们自行来处理。这方面的技术手段以及上述游离态控件的采集有时间再做统一的介绍。