一、背景

运营者能够对用户行为进行分析的前提,是对大量数据的掌握。在以往,这个数据通常是由开发者在控件点击、页面等事件中,一行行地编写埋点代码来完成数据收集的。然而传统的操作模式每当升级改版时,开发和测试人员就需要重复不断对代码进行更新,整个流程耗时长,无法满足业务的需求。

为帮助开发者解决这一痛点,个推应用统计“个数”推出“可视化埋点”这一技术来更高效地实现这个这一过程。“个数”的可视化埋点灵活、方便,开发者不需对数据追踪点添加任何代码,只需要连接管理台并圈选页面中需要埋点的元素,即可添加随时生效的界面追踪点。

本文将结合个数实践经验,对可视化埋点中的两大关键技术点即控件唯一标识和事件采集进行分析并提供解决方案。

二、可视化埋点关键技术点

可视化埋点的难点,或者说核心就是如何在开发者不编写任何代码的情况下,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可视化埋点技术原理大揭秘的更多相关文章

  1. 诗人般的机器学习,ML工作原理大揭秘

    诗人般的机器学习,ML工作原理大揭秘 https://mp.weixin.qq.com/s/7N96aPAM_M6t0rV0yMLKbg 选自arXiv 作者:Cassie Kozyrkov 机器之心 ...

  2. 不要再被骗了------QQ盗号原理大揭秘

    前言 相信大家在懵懂无知的时候都有被盗号的经历吧,QQ胡乱的加好友,突然有个好友传了个文件给你,打开以后发现QQ竟然显示强制下线,然后再也上不去了QAQ,很明显,QQ号被人盗了.最近也是很多小伙伴私信 ...

  3. AsyncTaskLoader设计原理大揭秘

    简介 在Android异步处理之AsyncTaskLoader简单使用中我简单的介绍了一下AsyncTaskLoader的基本用法和使用场景,对AsyncTaskLoader还不是很熟悉的小伙伴可以先 ...

  4. Protocol Buffer 序列化原理大揭秘 - 为什么Protocol Buffer性能这么好?

    前言 习惯用 Json.XML 数据存储格式的你们,相信大多都没听过Protocol Buffer Protocol Buffer 其实 是 Google出品的一种轻量 & 高效的结构化数据存 ...

  5. Android埋点技术分析

    1.现有的几种埋点技术的实现原理和优劣分析 (1)代码埋点:将收集数据的代码直接写在需要的地方,当用户点击某个控件或者打开某个页面时调用到该部分代码完成数据的收集. 优势:准确性高,收集数据和发送数据 ...

  6. 【腾讯Bugly干货分享】iOS黑客技术大揭秘

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5791da152168f2690e72daa4 “8小时内拼工作,8小时外拼成长 ...

  7. 大数据基础总结---MapReduce和YARN技术原理

    Map Reduce和YARN技术原理 学习目标 熟悉MapReduce和YARN是什么 掌握MapReduce使用的场景及其原理 掌握MapReduce和YARN功能与架构 熟悉YARN的新特性 M ...

  8. 【高德地图API】汇润做爱地图技术大揭秘

    原文:[高德地图API]汇润做爱地图技术大揭秘 昨日收到了高德地图微信公众号的消息推送,说有[一大波免费情趣用品正在袭来],点进去看了一眼,说一个电商公司(估计是卖情趣用品的)用高德云图制作了一张可以 ...

  9. 基于日志服务的GrowthHacking(1):数据埋点和采集(APP、Web、邮件、短信、二维码埋点技术)

    数据质量决定运营分析的质量 在上文中,我们介绍了GrowthHacking的整体架构,其中数据采集是整个数据分析的基础,只有有了数据,才能进行有价值的分析:只有高质量的数据,才能驱动高质量的运营分析. ...

随机推荐

  1. Angular获取dom元素,以及父子组建之间相互传值

    1.使用原生js代码获取dom元素 在ts文件中有一个ngOnInit()的方法,这个方式是指在模块加载完毕之后并不是dom加载完毕,也就是说如果你的dom元素中使用的angular的指令,然后想在这 ...

  2. 这38个小技巧告诉你如何快速学习MySQL数据库2

    1.如何快速掌握MySQL? ⑴培养兴趣兴趣是最好的老师,不论学习什么知识,兴趣都可以极大地提高学习效率.当然学习MySQL 5.6也不例外.⑵夯实基础计算机领域的技术非常强调基础,刚开始学习可能还认 ...

  3. 利用python3 调用zabbix接口完成批量加聚合图形(screens)

    在上一篇博客中,我们完成的利用python3 调用zabbix接口批量增加主机,增加主机的item,增加主机的图形! 接下来我们完成批量增加主机的screen 首先我们要增加screen需要哪些参数呢 ...

  4. python、mysql四-2:多表查询

    一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 准备表 #建表 create table department( id int, name varchar() ); create tabl ...

  5. MP4 ISO基础媒体文件格式 摘要 1

    目录 Object-structured File Organization 1 File Type Box (ftyp) Box Structures File Structure and gene ...

  6. linux 常用指令汇总

    新用户的一些操作: 查看当前用户:who am i(可以看到是否是伪终端)/也可以是whoami 添加用户:sudo adduser ..(用户名)..(此时创建的用户并未加入sudo组所以并不具有至 ...

  7. 13 Zabbix4.4.1系统告警“More than 75% used in the configuration cache”

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 13 Zabbix4.4.1系统告警“More than 75% used in the conf ...

  8. springmvc自定义异常处理类和<mvc:annotation-driven/>自带异常处理优先级问题

    自定义异常类的优先级低于注解驱动的默认异常处理,所以可以给自定义异常处理类,实现一个排序的接口, org.springframework.core.Ordered 改接口的注释: /**  * {@c ...

  9. Codeforces Round #581 (Div. 2) B. Mislove Has Lost an Array (贪心)

    B. Mislove Has Lost an Array time limit per test1 second memory limit per test256 megabytes inputsta ...

  10. 多线程(三) 同步synchronized

    五.同步 1.锁 多线程程序一般是为了完成一些相同的工作而存在的,因此有时间也会共享一些资源,例如对象.变量等等,此时如果不对各个线程进行资源协调,就会出现一些冲突,从而导致程序功能失效.例如下面的示 ...