从去年和朋友一起做小程序开始,我开始对于产品的运营有了一个新的认知,今年又买了一本《数据化运营:系统方法与实践案例》让我的思维开始从原来的技术型和交互设计型开始慢慢接触数据运营的概念。关于整体的方案还正在写,这个是其中关于统计数据收集关于埋点技术的一部分。
由于我自身只接触过iOS的Swift开发,但对于Android开发不太了解,而市场上关于埋点开发的书籍只找到了一本神策数据出的《Android全埋点解决方案》一书,而且是今年刚刚出版的,只好买了这本书去请教了Android开发同事,大致对于埋点开发的原理做了基础的调研,也让自己对于实现有了一点了解。
下文内容即来自于对书中内容的总结和从开发人员了解到的解释,对于代码实现部分不涉及而且我也只能以其他语言的基础去理解Android,难免会露怯。
首先先解释一下View
这是我的小程序的其中一个界面
这个页面的所有内容都是由控件组成的,所有可点击的控件都对应一个事件处理代码,埋点统计即是对所有这些事件的监控。
Android的四种事件
----
$AppStart事件:应用程序启动,同时包括冷热启动
$AppEnd事件:应用程序退出,包括正常退出、进入后台、被强杀、崩溃
$AppViewScreen事件:页面浏览,对于Android应用程序来说,就是指切换Activity或Fragment
$AppClick事件:控件的点击,即View被点击,包括Button、ListView等
这四个事件中,前三个比较简单,而围绕AppClick事件,全埋点即对AppClick事件进行拦截或者插入相关埋点代码,按照拦截或者插入的时间的不同,分为两种方式,每种方式有四个方案,也即是有八种不同的埋点方案AspectJ\ASM\Javassist\AST\View.OnClickListener代理\Window.Callback代理\View.AccessibilityDelegate代理\透明层。
静态代理AspectJ\ASM\Javassist\AST
------------
Android的开发周期
1、编写代码
2、编译代码得到Package
3、安装App
4、运行App
其中编译代码期间的流程是javaCode->.java->.class->.dex,AspectJ\ASM\Javassist\AST即是对这个编译过程不同阶段的处理,大致的处理方式就是开发者只需要对于代码块进行简单的注解或者说由SDK遍历去自动添加注解,然后在编译过程中通过插件的形式对于开发者代码进行改写加入自己的统计代码,这样不会对源码产生污染,又可以获得比动态代理更好的性能。
动态代理
------------
动态代理即是在App运行过程中对于系统的方法进行代理,比如App中的控件点击都会调用View.OnClickListener,动态代理就相当于接管了这个系统方法,然后在其中加入自己的统计代码,每一次控件点击调用View.OnClickListene的同时也会运行统计代码来上传用户行为数据。
AppStart和AppEnd事件的判定
----------------
首先注册一个Appication.ActivityLifecycleCallbacks回调用来监听Activity的生命周期,页面退出时启动一个倒计时,如果没有新页面进来则触发AppEnd事件,当页面启动时,判断与上个页面的退出事件间隔是否超过倒计时定义的时间,如果没超过则触发AppViewScreen事件,如果超过,首先判断之前是否触发了AppEnd事件,如果没有则先触发AppEnd事件,然后再触发AppStart和AppViewScreen事件
AppViewScreen事件的判定
-------------
通过Application的内部接口ActivityLifeycleCallbacks提供的一些回调方法。
AppClick事件的判定
--------------
在这里只列出一种动态代理方法View.OnClickListener,其他的还是各自买书看吧。
在应用程序自定义的Application对象的OnCreate()方法中初始化埋点SDK,并传入当前Application对象,在拿到Application对象后,通过registerActivityLifecycleCallback方法来注册Appication.ActivityLifecycleCallbacks回调,在Appication.ActivityLifecycleCallbacks的onActivityResumed回调方法中,拿到当前正在显示的Activity实例,通过activity.findViewById(android.R.id.content)方法就可以拿到整个内容区域对应的View,然后再逐层遍历这个RootView,并判断当前View是否设置了mOnClickListener对象,如果已设置mOnClickListener对象并且mOnClickListener又不是我们自定义的WrapperOnClickListener类型,则通过WrapperOnClickListener代理当前View设置的mOnClickListener,WrapperOnClickListener是统计SDK自定义的一个类,它实现了View.OnClickListener接口,在WrapperOnClickListener的onClick方法里会先调用View的原有mOnClickListener处理逻辑,然后再调用埋点代码,既可以实现自动埋点的效果。