分析公司常用的一些数据指标,我们发现对于大部分指标而言,我们只需要有页面的曝光事件、控件的点击事件等一些发送时机、内容相对固定的埋点即可,而这部分埋点,恰恰可以比较方便的使用自动埋点(相对于代码埋点这种手动埋点来说,无痕埋点及可视化埋点均可被称为自动埋点)来进行采集。
相对于可视化埋点来说,无痕埋点在前期不需要可视化工具进行埋点收集,SDK 开发投入较小,因此我们进行了第一步从手动埋点到无痕埋点的迭代。
无痕埋点技术实现
无痕埋点需要自动采集数据,因此针对页面、控件等元素需要生成其 ID,该 ID 需尽量具备『唯一性』和『稳定性』。『唯一性』非常好理解,因为对于任意元素而言,其 ID 应该是与其他所有元素都不同的,这样我们才能根据 ID 唯一标识出那个我们想要的元素,采集上来的数据才是准确的,不重复的。而『稳定性』则是说,元素的 ID 应尽量不受版本的变动而改变,这样后期关联业务含义的操作才会更加便捷。
页面ID规则
页面的 ID 较容易定义,参考上文提到的『唯一性』和『稳定性』,我们很容易就可以想到将页面所在类的类名作为 ID。类名作为 ID,首先它是相对唯一的,除了页面复用,不存在其他类名相同的页面,而页面复用的情况可以通过页面标题名称等方式进行规避;其次它是相对稳定的,只有在页面类名被修改的情况下 ID 才会改变,而我们日常开发的过程中,除了一些页面重大的改版之外不会轻易修改类名。在 Android 中,页面有两种类型 Activity 和 Fragment,Fragment 可以镶嵌在不同的 Activity 内,因此两者的 ID 定义规则有些不同:
- Activity,ID 规则为
ActivityClassName|额外参数
- Fragment,ID 规则为
ActivityClassName[FragmentClassName]|额外参数
页面PV、UV
有了页面的唯一 ID 生成的规则,我们只需要在页面曝光的时候,生成这个 ID,然后上传即可实现页面的 PV、UV 指标。至于页面曝光的时机,在 Android 开发中很容易可以找到,因为对于 Activity 和 Fragment 而言都有标准的生命周期。针对业务中 PV、UV 的定义,我们可以将 Activity 的 onResume()
方法,Fragment 的 onResume()
、setUserVisibleHint(boolean isVisibleToUser)
、onHiddenChanged(boolean hidden)
方法作为曝光时机,在上述方法被回调时,调用 SDK 埋点方法,生成 ID 然后上传埋点。
- Activity
- Fragment
控件ID规则
相对于页面而言,控件的 ID 定义规则要更加复杂。起初我们会想到用『R.id』,在编译时 Android aapt 会给每个写在 xml 里的控件生成一个唯一 ID,但是从 aapt 的生成规则来看,这个 ID 并不是固定不变的,在资源文件发生变化的时候,id 也可能会出现变化,也就是不同版本的相同控件的 ID 是有可能不同的。根据 ID 需要具备的『唯一性』和『稳定性』来看,这个 ID 具备『唯一性』,但『稳定性』非常差&