Android埋点技术分析
1.现有的几种埋点技术的实现原理和优劣分析
(1)代码埋点:将收集数据的代码直接写在需要的地方,当用户点击某个控件或者打开某个页面时调用到该部分代码完成数据的收集。
优势:准确性高,收集数据和发送数据都能精确控制,同时能方便的设置自定义属性,自定义控件,自定义View等。
劣势:埋点工作量大,更新代价大。
(2)可视化埋点:根据配置文件收集用户行为,从而获取数据进行分析。
优势:无须手动埋点,配置文件可动态更新。
劣势:配置文件的配置比较耗时,弹出框,隐藏控件等行为不能收集。收集的数据比较简单,只能收集用户行为,不能收集到与行为相关的具体数据。
(3)无埋点:与可视化埋点基本一致。不同点在于可视化埋点是根据配置文件收集数据,无埋点是预先收集所有的用户行为,然后根据配置文件来提取数据。无埋点可以通过修改配置文件追溯之前的用户行为数据。
(4)后端埋点:Sensors Analytics 这个平台有解决方案,优点是能收集到详细的与行为相关的数据,适用于电商等大平台。比如用户选择了一件商品,点击了加入购物车,那么可以收集到用户信息,商品信息,商品价格,商品库存,卖家等诸多信息。
埋点技术的选择
(1)代码埋点:既可以自己与后台定义接口,也可以使用第三方,常用的有友盟,百度统计等。
(2)可视化埋点和无埋点:移动端可以自己实现数据采集(下面有Android端的实现原理和demo)。第三方有诸葛IO,GrowingIO 。在知乎上查了关于这两个平台的信息,GrowingIO隐藏收费,官网并没有说到收费,但是使用15天后发邮件通知收费并停止数据采集和分析。诸葛IO免费模式的数据量是每月200万条,还有其他收费模式。
(3)后端埋点:Sensors Analytics
总结:根据当前公司产品特点和对埋点的要求,建议用可视化埋点;虽然诸葛IO的免费数据量对目前公司App使用规模来说够用,但是一方面以后数据量会越来越大,另一方面用户数据会被第三方掌握;同时在实现上面没有技术难点,所以,建议自己实现。
附录:Android实现可视化埋点技术
原理解析:
(1)页面跳转:Activity的生命周期,创建BaseActivity基类,实现对Activity生命周期的监听。
(2)控件的点击:根据UI布局的特性和Android点击事件传递机制实现。让创建的BaseActivity基类重写Activity的dispatchTouchEvent方法,当touch button时,可以获取到按下(DOWN)和抬起(UP)时产生的MotionEvent对象。这个MotionEvent对象有两个方 法,getRawX()和getRawY(),通过这两个方法我们可以获取到“点击位置”在界面中的坐标。然后搜索所有的子View或者控件的布局区域是否包含“点击位置”,从而来判断哪个View或控件被点击。
难点:如何标识点击的控件,这里我们用该控件实例化所在的类名和该控件的UI路径来做唯一标识。
下面实现一个具体Demo:
(1)先写一个简单的登陆界面:有两个EditText分别输入用户名和密码,一个登陆Button,一个去注册的TextView。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.wangliang160818.traking.MainActivity"> <EditText
android:id="@+id/activity_main_user"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入用户名 "/>
<EditText
android:id="@+id/activity_main_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="输入密码 "/>
<TextView
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="登陆"
android:layout_marginTop="12dp"
android:background="@color/colorPrimary"
android:padding="10dp"
android:textColor="@android:color/white"
android:textSize="22sp"/>
<TextView
android:id="@+id/register"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="去注册"
android:layout_marginTop="12dp"
android:background="@color/colorAccent"
android:padding="10dp"
android:textColor="@android:color/white"
android:textSize="16sp"/>
</LinearLayout>
(2)然后模拟埋点数据,实际中就是我们放在服务器的埋点文件,通过动态修改这个文件实现动态埋点的效果。
@Override
public void onWindowFocusChanged (boolean hasFocus){
super.onWindowFocusChanged(hasFocus); if(allView != null)
allView.clear();
allView = getView((ViewGroup) rootView);
for(int i=;i<allView.size();i++) {
Log.v("out", allView.get(i).toString());
viewPath.add(mClassName+"."+allView.get(i).toString().split("\\{")[]);
}
Log.v("out" , allView.size()+"");
Rect outRect = new Rect();
this.getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect);
statusBarHeight = outRect.top; }
遍历布局文件
/*获取所有View和没有子View的ViewGroup*/
public ArrayList<View> getView(ViewGroup viewGroup){
if(views == null)
views = new ArrayList<View>();
if(viewGroup == null) return null;
//views.add(viewGroup);
int count = viewGroup.getChildCount();
for(int i=;i<count;i++){
if(!(viewGroup.getChildAt(i) instanceof ViewGroup)){
views.add(viewGroup.getChildAt(i));
}else this.getView(viewGroup);
}
return views;
}
点击时的处理
/*重写dispatchTouchEvent*/
public boolean dispatchTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_UP){
/*获取当前点击位置,遍历布局,获取当前点击位置对应的view,根据view映射路径,与json文件中的对比*/
double x = ev.getRawX();
double y = ev.getRawY() - statusBarHeight;
if(allView2 != null)
allView2.clear();
allView2 = getView((ViewGroup) rootView);
for(int i=;i<allView2.size();i++) {
/*获取点击位置的view*/
int left = allView2.get(i).getLeft();
int right = allView2.get(i).getRight();
int top = allView2.get(i).getTop();
int bottom = allView2.get(i).getBottom();
if(x > left && x < right &&
y > top && y < bottom){
/*判断这个view是否是我们要埋点的*/
String s = mClassName+"."+allView2.get(i).toString().split("\\{")[];
if(viewPath.contains(s)){
Log.v("out" , "这是我们的埋点:"+s);
}
}
}
}
return super.dispatchTouchEvent(ev);
}
总结:根据无埋点原理初步实现了,目前还有几个问题:
(1)每个View都必须有唯一标识,当前采用的是用view的路径,但是这样当布局文件层级比较复杂的时候,获取路径还有问题。
(2)其二,当布局有margin,标题栏等情况时需要额外考虑。
将以上两个问题完善后可以在实际应用中使用,后续做这部分工作。
第三方友盟:http://dev.umeng.com/analytics/reports/usage#2
Android埋点技术分析的更多相关文章
- Android埋点技术概览
注:本文同步发布于微信公众号:stringwu的互联网杂谈Android无埋点技术概览 本文是Android无埋点系列的开篇---埋点技术概览 1 背景 埋点是数据产品经理(分析师)基于业务需求,对用 ...
- Android“寄生兽”漏洞技术分析
一.关于app的缓存代码 安卓的应用程序apk文件是zip压缩格式的文件,apk文件中包含的classes.dex文件相当于app的可执行文件,当app运行后系统会对classes.dex进行优化,生 ...
- Android插件化技术——原理篇
<Android插件化技术——原理篇> 转载:https://mp.weixin.qq.com/s/Uwr6Rimc7Gpnq4wMFZSAag?utm_source=androi ...
- 基于日志服务的GrowthHacking(1):数据埋点和采集(APP、Web、邮件、短信、二维码埋点技术)
数据质量决定运营分析的质量 在上文中,我们介绍了GrowthHacking的整体架构,其中数据采集是整个数据分析的基础,只有有了数据,才能进行有价值的分析:只有高质量的数据,才能驱动高质量的运营分析. ...
- Android 热修复技术(1)---原理
热修复技术分为几部分: 原理介绍 Android HotFix源码分析 自定义框架 1.Android分包MultiDex原理 首先Dex是什么东西? Dex就是Window里面的exe文件 也就是可 ...
- 【转】Android 防破解技术简介
http://www.cnblogs.com/likeandroid/p/4888808.html Android 防破解技术简介 这几年随着互联网的不断发展,Android App 也越来越多!但是 ...
- 《Android系统源代码情景分析》连载回忆录:灵感之源
上个月,在花了一年半时间之后,写了55篇文章,分析完成了Chromium在Android上的实现,以及Android基于Chromium实现的WebView.学到了很多东西,不过也挺累的,平均不到两个 ...
- 全面了解Android热修复技术
WeTest 导读 本文探讨了Android热修复技术的发展脉络,现状及其未来. 热修复技术概述 热修复技术在近年来飞速发展,尤其是在InstantRun方案推出之后,各种热修复技术竞相涌现.国内大部 ...
- Android 中图片压缩分析(上)
作者: shawnzhao,QQ音乐技术团队一员 一.前言 在 Android 中进行图片压缩是非常常见的开发场景,主要的压缩方法有两种:其一是质量压缩,其二是下采样压缩. 前者是在不改变图片尺寸的情 ...
随机推荐
- L09-Linux系统修改网卡名称(eth1修改为eth0)
一.环境 VirtualBox + CentOS6.5 二.问题 有时候在克隆服务器之后配置网络时,或者在维护别人建好的服务器时,会遇到这样一种情况.如下图所示: 即:在接口配置文件ifcfg-e ...
- jmeter -- 在beanshell中拿到请求body参数和header参数
beanshell: import org.apache.jmeter.config.Arguments; import org.apache.jmeter.protocol.http.control ...
- django框架--视图系统
目录 一.视图函数的理解 二.视图函数的定位 三.请求对象HttpRequest 四.响应对象HttpResponse 一.视图函数的理解 视图函数的作用是,对指定的url执行业务逻辑,视图函数将会作 ...
- Class与Style绑定
本文主要介绍如何使用Vue来绑定操作元素的class列表和内联样式(style属性). 因为class和style都是属性,所以通过v-bind命令来处理它们:只需要通过表达式计算出结果即可,不过字符 ...
- css设置:图片文字等不能被选择
-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;
- 生成xml文件的步骤 -- XML的序列化器
1. 初始化一个xml的序列化器 XmlSerializer serializer = Xml.newSerializer(); 2. 设置序列化器的参数 serializer.setOutput(o ...
- Android Library项目发布到JCenter最简单的配置方法
前沿 网上的步骤看起来实在太麻烦,gituhb上偶然间看到的一个项目,经过实际验证确实可行.github连接:https://github.com/xiaopansky/android-library ...
- ES6-Set and Map
依赖文件地址 :https://github.com/chanceLe/ES6-Basic-Syntax/tree/master/js <!DOCTYPE html> <html&g ...
- k折交叉验证
原理:将原始数据集划分为k个子集,将其中一个子集作为验证集,其余k-1个子集作为训练集,如此训练和验证一轮称为一次交叉验证.交叉验证重复k次,每个子集都做一次验证集,得到k个模型,加权平均k个模型的结 ...
- mongodb-地理坐标存储查询
mongodb可支持空间地理搜索: 查询器 $geoWithin Selects geometries within a bounding GeoJSON geometry. The 2dsphere ...