出于对数据的信仰,我们不仅认为数据开放才更有价值,也认为技术开放才会更有活力。分享的目的绝不是鼓励跟风,我们更希望以此能够为业界打开新的思路,激发更多的创新,和生态中的伙伴和战友们一起把客户服务提升到新的水平。
上期重点说明了TalkingData灵动分析的结构和流程,使大家对于灵动分析的技术框架有一个基本的认识。本期,我们就安卓和iOS系统SDK实现细节做更加详细的说明,让大家看到毛孔级的干货分享。
闲话少说,直奔主题。
安卓系统的技术点
【如何同步手机界面到管理后台】
在事件管理后台中动态添加事件的基础,是要能够同步应用界面到管理后台中。界面同步方案中有两个关键点:
1. 通过Canvas来获取屏幕内容:
void android.graphics.Canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint);
2. 获取view属性
位置相关:x,y,width,height,偏移等,
唯一性相关:id,类名等。
绘制相关:hidden,alpha等
view的属性有很多,哪些属性是应该上传的,哪些属性是可以忽略的,为了动态的调整这些,可以使用反射的机制来实现。具体说,就是在进入UI同步状态时,服务器将一个属性配置单下发到App中,SDK通过对配置的解析,利用反射执行配置中的指定方法获取view的响应属性数据。这也是配置即代码的一种实现。
完成以上两项内容,就可以把数据发送至管理后台,并绘制出手机的内容了。
【如何绑定事件至控件】
Android系统定位一个控件,需要先获取当前Activity的rootview,方法是:
View rootView = activity.getWindow().getDecorView().getRootView();
然后遍历动态事件列表,用每个动态事件中控件的唯一标示去匹配rootview中的内容,匹配规则:
viewClassName && id && tag && contentDescription
当符合条件时,就给当前的view添加一个AccessibilityDelegate对象
View.AccessibilityDelegate ret = null;
try {
Class<?> klass = v.getClass();
Method m = klass.getMethod("getAccessibilityDelegate");
ret = (View.AccessibilityDelegate) m.invoke(v);
} catch (Exception e) {
}
AccessibilityDelegate newDelegate = new AccessibilityDelegate(ret);
view.setAccessibilityDelegate(newDelegate);
【如何监测点击事件】
通过分析Android系统View类的源代码,发现可利用Android中View类的方法来实现事件触发的:
sendAccessibilityEvent(int eventType)
该方法实现如下:
public void sendAccessibilityEvent(int eventType) {
if (mAccessibilityDelegate != null) {
mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
} else {
sendAccessibilityEventInternal(eventType);
}
}
即只要设置了代理就可以对具备Accessibility能力的view实现点击事件的响应。
View.AccessibilityDelegate具体说明请参考Android的开发者文档。
【界面主线程占用是否有影响】
界面的监测操作是要放在界面主线程中,开始我们担心这样会不会对应用本身的界面交互产生影响?经过实际测试,这样实现是完全没有问题的,应用不会受任何影响。
另外,事件的侦测是实时的循环监测,这样自定义的事件越多,必然会有占用时间,不过代价很小(毫秒级),实测中也没有发现对应用交互有可感知的影响。
【如何应对界面动态布局】
为了应对页面的动态布局,我们需要在单一线程中实现事件监测,通过循环操作,使每个事件都对当前页面的所有view进行匹配。经过实测,也没有发现对应用交互有可感知的影响。
【如何保持事件触发链】
处理完事件后,要交还给系统继续处理,不要扔掉,否则会导致应用本身工作异常。
iOS系统的技术点
【如何同步手机界面到管理后台】
iOS平台,同步界面的操作分为几个步骤:
1. 截屏
通过以下方法获取屏幕截图:
UIGraphicsGetImageFromCurrentImageContext()
2. 获取控件属性
根据服务器下发配置表获取每个对象所需要的属性。
3. 上传数据
将屏幕截图进行base64编码,并和控件属性一起上传到服务器。
4. 管理后台界面展示
管理后台绘制手机屏幕的截图,根据获取到的x、y、w、h、alpha、hidden等属性绘制控件的范围。
【如何绑定事件至控件】
绑定事件到控件的步骤是:
1. 从服务器获取动态事件列表,根据每条动态事件数据创建一个EventBinding对象。
2. 获取当前window的rootViewController:
UIViewController *root = [[UIApplication sharedApplication] keyWindow].rootViewController;
3. 遍历动态事件列表,用每个动态事件中控件的path去匹配rootViewController中的内容,匹配规则是:
ClassName && tag && 所在容器中的成员变量名 && Button中图片的指纹 && title
【如何监测点击事件】
对控件点击事件进行监测的步骤是:
1. 找到要监控的控件时,就给当前控件添加一个Action:
[control addTarget:self action:@selector(execute:) forControlEvents:UIControlEventTouchUpInside];
2. 监控事件被触发时相应的EventBinding对象得到响应,生成事件数据上报服务器进行统计。
【界面主线程占用是否有影响】
和Android一样,iOS应用界面的监测操作是要放在界面主线程中,开始我们也担心这样会对应用本身的界面交互产生影响。经过实测,依然没有发现对应用交互有可感知的影响。
后记
向一直艰苦奋斗在最前线的,为客户极致体验而努力的TalkingData产品团队、研发团队、BD团队、市场团队和客服团队致意!
从2011年国内首批推出第一代移动应用分析平台开始,TalkingData一直致力于为开发者提供更方便好用的产品运营工具。本次我们再度首开国内先河,推出新一代的移动分析系统“灵动分析”,拉开了移动分析新时代的序幕。这次发布,是整个团队心血的结晶,也是我们对4年多以来一同奋斗的开发者们诚挚的敬礼。
我们第一时间分享技术,希望能够帮助友商尽快跟进,群策群力,为客户提供更加优质的服务体验,同时带动行业进入一种良性的互动,大家取长补短,共同营造更加健康的服务生态。
——这就是极致到1行代码背后的意义。
更多内容,请关注我的知乎专栏:【峰言峰语】
