App可视化埋点技术原理大揭秘
一、背景
运营者能够对用户行为进行分析的前提,是对大量数据的掌握。在以往,这个数据通常是由开发者在控件点击、页面等事件中,一行行地编写埋点代码来完成数据收集的。然而传统的操作模式每当升级改版时,开发和测试人员就需要重复不断对代码进行更新,整个流程耗时长,无法满足业务的需求。
为帮助开发者解决这一痛点,个推应用统计“个数”推出“可视化埋点”这一技术来更高效地实现这个这一过程。“个数”的可视化埋点灵活、方便,开发者不需对数据追踪点添加任何代码,只需要连接管理台并圈选页面中需要埋点的元素,即可添加随时生效的界面追踪点。
本文将结合个数实践经验,对可视化埋点中的两大关键技术点即控件唯一标识和事件采集进行分析并提供解决方案。
二、可视化埋点关键技术点
可视化埋点的难点,或者说核心就是如何在开发者不编写任何代码的情况下,SDK 如何确定任意一个控件在该应用内的唯一性,以及如何监听控件的点击和页面的切换。
标识
为了防止不同页面中的控件标识重复出现,控件的唯一标识一般由页面标识加上控件标识生成。
页面标识生成
页面标识可以直接使用页面的名称,即 Activity name。其获取方式比较多,这里介绍一种比较通用的方法,即通过注册 Application.ActivityLifecycleCallbacks ,开发者可以在以下生命周期的回调中,轻松地拿到当前的 Activity 对象。此方法适用于一个 Activity 并无 Fragment 存在的情形。
代码详见下图:

获取方式也是比较多,不过较于 Activity 的获取会相对麻烦一些,因为系统没有直接提供 API ,因而需要稍微转个弯:通过 Gradle 插桩的方式,获取 Fragment 的生命周期,以及 Fragment 实例对象:
如果该应用的页面存在一个 Activity 中嵌套多个 Fragment 的情况,单单一个 Activity name则可能无法精准地定位到某个页面,因而还需要加上 Fragment 的名称。Fragment的获取可以通过 Gradle 插桩法来实现,即根据 Fragment 的生命周期来获取Fragment 实例对象。

1.2控件标识生成
理想的情况下页面中的每个控件都有属于自己的唯一 id,SDK 直接获取控件的 id 当做控件标识即可。但现实情况却是,一个页面中往往存在多个相同 id 的控件,或者是没有 id 的控件,比如 Listview 的 item ,开发者不可能给listview的每个item 设置不同的 id。
因此需要转变一下思路。我们可以从控件路径这个除id 外比较独特的性质着手来生成控件标识。开发者可以通过给控件的路径加上控件角标的结构方式,生成控件的唯一标识。下图是Github 上一个仿 B 站的应用。我们对这个应用进行一下控件树分析。首先我们使用 Android Studio 自带的 UI Automator Viewer 工具查看该页面的布局结构:

接下来,我们可以从Application.ActivityLifecycleCallbacks 的回调中拿到 Activity 实例,再使用 activity.getWindow().getDecorView().getRootView() 方法来获取当前页面的控件树。
例如图中的文字控件是 TextView,且无兄弟布局,则可以标记为 TextView[0] 。它的父布局是 LinearLayout 且排在兄弟布局中的第二位,那么就可以写成是 LinearLayout[1],然后使用自己定义的符号拼接,像是 LinearLayout[1]/TextView[0] 。之后以此类推、循环遍历、层层递进,将所有经过的控件以及它们的下标都拼接起来,组成控件在该页面中的唯一标识。
对于一些可复用的 View ,我们则需要采取一些特殊处理。例如对于 RecyclerView、ListView、 ViewPager 等复用控件,我们都需要采取不同的处理方式,去获取当前 View 在该控件中的具体下标。如果没有进行特殊处理,则会导致子控件错位,数据统计不准确。
采集
在以往的处理中,如果需要知道一个按钮的点击次数,开发者就要在该控件的click事件中加入对应的打点代码。这种重复劳作,无疑增加了开发者的开发负担。对此,我们可以采用动态代理方式或Gradle 插桩方式来改善这个问题。
动态代理方式
使用安卓自带的辅助功能 View.AccessibilityDelegate 。前文提到当页面变化时,我们可以通过 Application.ActivityLifecycleCallbacks 获取到 Activity 的实例对象,接着根据activity.getWindow().getDecorView().getRootView() 来获取到控件树。由于控件树可能会实时发生变化,我们则需要通过 ViewTreeObserver.OnGlobalLayoutListener 的方法监听视图变化,从而在该回调中拿到变化的控件。接着我们 要根据递归判断该控件是否为 ViewGroup、是否可以点击、是否能够显示等,继而给符合条件的 View 设置 sendAccessibilityEvent();此外,我们还要在继承了 View.AccessibilityDelegate 的定义类中,对以下这些方法添加 SDK 的代理:

当对应的控件被点击时,系统就会自动调用设置过代理的方法,存储或者上报对应数据。

Gradle 插桩的方式
Android Gradle 工具在1.5.0 版本后提供了 Transfrom API , 该API 允许第三方 Plugin 在打包 dex 文件之前的编译过程中操作 .class 文件。在编译期,开发者可以通过onClick、onItemClick等方法(详见下图)进行监听,这相当于是正则匹配。
当上述监听的方法被编译的时候,就可以将埋点的代理操作插入这些方法中,实现自动化埋点的流程。网上相关流程也是非常详细,有兴趣的可以自行搜索学习。

三、结语
以上就是APP端可视化埋点实现过程中的关键点,特别需要注意的是控件唯一标识那一块,由于布局千变万化,开发者针对很多特定的布局都需要采取对应的处理方式。
目前个推应用统计——个数这个产品只需要一行初始化代码就可以自动帮助开发者采集包括页面统计、事件埋点、新增活跃等多维度信息。
借着万圣节,悄悄跟你说个恐怖的故事:除个推应用统计服务之外,VIP消息推送、用户画像,现在申请均可以免费用一年!一键认证服务还可以享受充10万条送5万条的优惠哦 !点击https://www.getui.com/2019devfest,“码“上申请吧!
行业前沿、面试宝典,更多技术干货,尽在个推技术学院。

App可视化埋点技术原理大揭秘的更多相关文章
- 诗人般的机器学习,ML工作原理大揭秘
诗人般的机器学习,ML工作原理大揭秘 https://mp.weixin.qq.com/s/7N96aPAM_M6t0rV0yMLKbg 选自arXiv 作者:Cassie Kozyrkov 机器之心 ...
- 不要再被骗了------QQ盗号原理大揭秘
前言 相信大家在懵懂无知的时候都有被盗号的经历吧,QQ胡乱的加好友,突然有个好友传了个文件给你,打开以后发现QQ竟然显示强制下线,然后再也上不去了QAQ,很明显,QQ号被人盗了.最近也是很多小伙伴私信 ...
- AsyncTaskLoader设计原理大揭秘
简介 在Android异步处理之AsyncTaskLoader简单使用中我简单的介绍了一下AsyncTaskLoader的基本用法和使用场景,对AsyncTaskLoader还不是很熟悉的小伙伴可以先 ...
- Protocol Buffer 序列化原理大揭秘 - 为什么Protocol Buffer性能这么好?
前言 习惯用 Json.XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存 ...
- Android埋点技术分析
1.现有的几种埋点技术的实现原理和优劣分析 (1)代码埋点:将收集数据的代码直接写在需要的地方,当用户点击某个控件或者打开某个页面时调用到该部分代码完成数据的收集. 优势:准确性高,收集数据和发送数据 ...
- 【腾讯Bugly干货分享】iOS黑客技术大揭秘
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5791da152168f2690e72daa4 “8小时内拼工作,8小时外拼成长 ...
- 大数据基础总结---MapReduce和YARN技术原理
Map Reduce和YARN技术原理 学习目标 熟悉MapReduce和YARN是什么 掌握MapReduce使用的场景及其原理 掌握MapReduce和YARN功能与架构 熟悉YARN的新特性 M ...
- 【高德地图API】汇润做爱地图技术大揭秘
原文:[高德地图API]汇润做爱地图技术大揭秘 昨日收到了高德地图微信公众号的消息推送,说有[一大波免费情趣用品正在袭来],点进去看了一眼,说一个电商公司(估计是卖情趣用品的)用高德云图制作了一张可以 ...
- 基于日志服务的GrowthHacking(1):数据埋点和采集(APP、Web、邮件、短信、二维码埋点技术)
数据质量决定运营分析的质量 在上文中,我们介绍了GrowthHacking的整体架构,其中数据采集是整个数据分析的基础,只有有了数据,才能进行有价值的分析:只有高质量的数据,才能驱动高质量的运营分析. ...
随机推荐
- Docker 构建私有镜像仓库
在使用Docker一段时间后,往往会发现手头积累了大量的自定义镜像文件,这些文件通过公有仓库进行管理并不方便,另外有时候只是希望在内部用户之间进行分享,不希望暴露出去.这种情况下,就有必要搭建一个本地 ...
- EJB通过注解方式注入并使用其它EJB或者服务、配置JBoss数据源
版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/Jerome_s/article/details/37103171 通过注解方式注入并使用其他EJB或者服务 ...
- [Next] 服务端渲染知识补充
渲染 渲染:就是将数据和模版组装成 html 客户端渲染 客户端渲染模式下,服务端把渲染的静态文件给到客户端,客户端拿到服务端发送过来的文件自己跑一遍 js,根据 JS 运行结果,生成相应 DOM,然 ...
- tomcat启动报ClassNotFound
排除本来就缺少该类的原因,经过自己经验和网上查的资料,解决方式如下: jar包冲突(关闭其他项目) eclipse的java版本不对,点击项目,右键properties在project facets, ...
- python+minicap(二)
一.push文件至手机中 minicap 的使用有很强的针对性,针对不同架构的CPU和SDK制作了不同的 "minicap" 和 "minicap.so" 文件 ...
- 关于Android studio调用高德地图的简单流程和要点
一,账号与Key的申请 注册成为高德开发者需要分三步: 第一步,注册高德开发者:第二步,去控制台创建应用:第三步,获取Key. 前2步都比较简单,这里说下第三步. 获取Key 1.进入控制台,创建一个 ...
- 前端页面多级联动传输数据类型问题(数组or字符串)后端处理
在最近的工作中,遇到一个问题,个人所做的简历模块中有两个字段,分别是个人信息中的户口所在地和现居住城市. 前端界面中这两个选项框是用到了二级和三级联动,在向后端传输时希望可以通过数组类型进行传输,例如 ...
- js之运算符(位运算符)
一.概念 位运算在数字底层(表示数字的32个数位)进行运算的.由于位运算是低级的运算操作,所以速度往往也是最快的,但是它很不直观,许多场合不能够使用.大多数语言都提供了按位运算符,恰当的使用按位运算符 ...
- Vue实例:vue2.0+ElementUI框架开发pc项目
开发前准备 vue.js2.0中文,项目所使用的js框架 vue-router,vue.js配套路由 vuex,状态管理 Element,UI框架 1,根据官方指引,构建项目框架 安装vue npm ...
- linux下ifconfig只剩下lo的解决方法
运行以下命令,删除旧的网络配置,重新让networkmanager自动配置即可 sudo service network-manager stop sudo rm /var/lib/NetworkMa ...