【开源中国 APP 全新上线】“动弹” 回归、集成大模型对话、畅读技术报告”
TalkingData 灵动分析是一个产品和运维使用的工具,他是用来分析App使用者是如何使用一个App的,通过对发布后的App进行动态埋点,解决了两大疑问:
第一,埋点不再需要在发布前预先编码;
第二,埋点工作不再是开发的工作,现在可以由产品独立完成;
那么灵动分析的实现原理中,最核心的技术是什么,按照我们的理解,灵动分析的功能可以分为以下几个大的方面:
1. 实现手机到Web的跨屏,即截屏后发送至Web显示当前手机内容。
2. Web上绘制View,通过分析应用中UI元素的x ,y,宽,高,把每一个View在Web上进行区分,并将可以用于事件绑定的元素展示给操作者
3. UI的查找,这里一个查找方法生成与执行的过程,查找方法由平台特性决定,iOS 和 Android 是不同的思路。
4. UI 绑定与数据劫持,属于单点技术突破,只要API支持,我们就可以实现,这个并不是难点,是需要找到对应的代理方法就好。
5. 数据交互,可以使用轮询,长轮询,Comet,WebScoket实现
这些技术点,每一个展开都可以再分解出更多的详细技术内容,哪个才是核心,才是最重要的。根据我们实践来看,‘UI查找’ 是整个解决方案的灵魂,其他的技术,要么可以找到很多实现方法,要么只要单点突破就可以搞定。接下来,我们分别解释 Android 和 iOS 两个平台,在 ‘UI查找’ 这个核心功能上是如何实现的。
首先,我们来分析Android平台的实现,要说Android的View查找,我们先要介绍一些Android的UI知识。
1.Activity:大家都知道Activity是Android的四大组件之一,负责和用户交互,Activity中的所有操作都和用户相关,可以通过setContentView(View)来显示指定的控件。
2.WindowManager:Activity的窗口和图形系统,用来管理window的添加,删除,移动等。
3.Window:在不同的地方有着不同的含义。在Activity里,Window 是一个抽象类,代表了一个矩形的不可见的容器,里面布局着若干个可视的区域(View). 每个Activity都会有一个Window类成员变量,WindowManagerService里管理的Window其实是Acitivity的ViewRoot。从用户角度来看,Android是个多窗口的操作系统,不同尺寸的窗口区域根据尺寸,位置,z-order及是否透明等参数叠加起来一起并最终呈现给用户。这些窗口既可以是来自一个应用,也可以来自与多个应用,这些窗口既可以显示在一个平面,也可以是不同的平面。
4.View:是一个矩形的可见区域。
5.ViewGroup:是一种特殊的View, 它可以包含其他View并以一定的方式进行布局。
对以上概念不是很理解,请百度相关概念,有了对以上内容的了解,接下来我们来描述一下他们的关系,一个应用可以有多个Activity,每个 Activity 有一个Window(PhoneWindow), 每个Window 有一个DecorView(Activity Window的顶级View, 所有在窗口里显示的View都是它的子View.), 一个ViewRootImpl(Android 的默认实现,被添加在DecorView中),也就是说我们要找的,并不是setContentView(View)中的View,而是DecorView,只有找对了起点,接下来的工作才会有意义。
View中可以找到的具有标记性的属性:
Id: 静态整形数,应用在编译期,aapt会生成R类,其中包含所有资源ID。
Resource Id:开发者操作控件的唯一标示,通过findViewById找到View
Class Name:View所属的Class
Tag:View的Tag属性
这些属性看上去如果Id能够使用,是可以直接解决的,但是,从aapt生成id的原则来看,在不同的版本相同的resource Id对应的整形数Id 是有可能不一样的,请参考:
所以没有办法使用Id来唯一标示。Resource Id,是开发者定义的View识别方式,对于有Resource Id 的View可以说具备了唯一标识,那么没有Resource Id的View,我们考虑添加一个index属性,index属性可以有如下方式赋值:
1.每个ViewGroup下的所有View作为一个数组,从0开始。
2.每个ViewGroup下的所有View先按照Class分类,然后再把每个类型中的数据按照数组的方式,从0开始
3.每个ViewGroup下的所有View先按照Class分类,再确认是否有Resource Id,如果存在,就不需要index来做标记
综上,我们对要查找的View和他所有的父节点都做这样的描述,最后形成一个查找路径,这样就可以找到一个View了,接下来要考虑的是查找效率的疑问,这里我们建议使用树的深度优先算法来查找View,关于算法的实现,请百度。理论上,Activity中的每个View都可以被识别。以上就是Android的如何在UI中查找View的方法,那么,iOS 平台的实现我们通过以下三个部分做介绍
- 1、控件到 window 的层级关系
- 2、分析控件的详细路径
- 3、动态修改控件
控件到 window 的层级关系:
每个 App , 至少有一个根 Window , 通常情况下我们只用一个 。window 有一个 rootViewController , 这就是我们所谓的根视图 , 我们所有的控制器都是放在 rootViewController 里面的。
这个是最简单的层级关系
如果在项目里有了这么一个路径 , 我们可以做什么呢?
- 在当项目很复杂 , 可以其它地方可以直接修改这个控件的状态
- 当某个控件命名存在却又没有显示出来 , 可以通过路径来辅助查找
- 由服务器下发一些配置 , 使用 Runtime 去动态的修改已上线的项目
下面将介绍如何使用代码来找出这些视图(控件)的路径
分析控件的详细路径
1、找出 Window :
每一个视图、控件 , 他们最终的根都是main函数返回的 application , 通过 [UIApplication sharedApplication]可以得到 。 application 的 windows 属性是一个数组 , 这里面装的是这个应用的所有 Window , 我们通常用的是第一个也就是 application.windows[0]
2、遍历视图 :
动态修改控件
3、修改 button 的事件处理 。
4、 绑定查找控件时 , 这个界面必须要已经初始化完成了才行 , 假如界面还没生成肯定是查找不到这个控件的 。 这里给大家提供两种思路 :
这样我们就给大家完整剖析了灵动分析的核心功能。
关于TalkingData
TalkingData自2011年起即始终专注在移动端数据服务上,管理团队来自于Oracle,IBM,Microsoft,腾讯,百度,360等企 业,即融合了互联网的“开放精神”又传承了传统IT的“严谨服务”这两种文化。伴随4年移动互联网的高速发展,TalkingData打造了由开发者服务 平台,数据服务平台,数据商业化的完整数据服务链条。服务超过8万款移动应用及6万多应用开发者,覆盖超过17亿独立智能设备。