countly-sdk-android

用户行为分析开源框架(埋点)
github

1.该框架用到的第三方框架

androidTestCompile 'org.mockito:mockito-core:2.5.6'
androidTestCompile 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0'

mockito

单元测试框架

dexmaker

运行在Android Dalvik VM上,利用Java编写,来动态生成DEX字节码的API。为我们在Android上实现AOP编程提供了很好的选择

2.sdk包结构

sdk包结构图.png

openudid包
用于获取设备唯一标识的一种方案

count包
AdvertisingIdAdapter.java
获取谷歌的广告id

CertificateTrustManager.java
https证书信任管理器

ConnectionProcessor.java
将收集到的数据发送给服务器的一个后台任务。
接到发送通知后,将存储在本地的数据一条一条的送给服务端,每送一条,就删除本地对应的那条数据,直到数据为空,此时任务结束,等待下次发送数据的通知。

ConnectionQueue.java
将收集的各个类型的数据,存储在本地,并通知ConnectionProcessor将数据发送到服务端
ConnectionQueue中的记录事件的方法

void recordEvents(final String events) {
    checkInternalState();
    final String data = "app_key=" + appKey_
                      + "&timestamp=" + Countly.currentTimestampMs()
                      + "&hour=" + Countly.currentHour()
                      + "&dow=" + Countly.currentDayOfWeek()
                      + "&events=" + events
                      + "&sdk_version=" + Countly.COUNTLY_SDK_VERSION_STRING
                      + "&sdk_name=" + Countly.COUNTLY_SDK_NAME;

    store_.addConnection(data);

    tick();
}

Countly.java
核心类,代码行数比较多,放在后面详细介绍

CountlyStarRating.java
展示一个带星级评分的对话框

CountlyStore.java
本地存储类(sp)
存储各种收集到的数据

CrashDetails.java
收集设备的详细信息,并将这些信息和崩溃信息整合在一起,当APP崩溃时,整合的全部信息都会被上传到服务器

DeviceId.java
设置设备唯一标识,有三种选择:用户自定义,OPEN_UDID和ADVERTISING_ID

DeviceInfo.java
获取设备以及App相关信息

Event.java
定义了待传递事件的数据结构,即上传哪些字段

public String key;
public Map<String, String> segmentation;
public int count;
public double sum;
public double dur;
public long timestamp;
public int hour;
public int dow;

EventQueue.java
收集数据到本地SP以及从本地获取事件列表

MessagingAdapter.java
通过反射调用CountlyMessaging类的方法,该类在sdk-messaging模块中

OpenUDIDAdapter.java
通过反射调用OpenUDID_manager类的方法

ReferrerReceiver.java
接收com.android.vending.INSTALL_REFERRER的广播

UserData
定义了用户相关的信息,如姓名等等

3. 事件记录分类

3.1 点击事件收集
Countly.sharedInstance().recordEvent("Custom event 1")
3.2 跟踪视图(Activity)
 Countly.sharedInstance().setViewTracking(true);//开启视图跟踪
 Countly.sharedInstance().onStart(this); //在onStart中调用该方法
3.3 崩溃日志收集
 Countly.sharedInstance().enableCrashReporting();

4. 核心类Countly分析

构造方法
利用线程池开启了一个定时任务,每隔60S刷新会话,只要Event队列有数据,就将Event队列中的数据加入到Connection队列中,然后通知后台任务从前到后上传队列中的数据

onCreate方法

Intent intent = activity.getIntent();
Uri data = intent.getData();

主要是获取当前Activity的<data>属性

init方法
需要三个必传参数
context 上下文
serverURL 服务器地址,会校验合法性,并去掉最后一个'/'
appKey App秘钥,只校验的是否为空

关于设备id
默认设置id为null 设备id类型为uuid 且设备支持uuid

在初始方法中,做了以下工作
校验参数合法性
初始化ConnectionQueue参数
创建EventQueue

halt方法
将所有的参数设置为空,并清空Event队列和Connection队列

onStart和onStop方法
这个两个方法需要成对使用,一次onStart和onStop,其实就是一个Activity停留的那一段时间,在每一次的onStart方法中都会记录当前的Activity,同时也会通过beginSession和endSession,记录APP从打开到关闭的持续时间

recordEvent方法

void sendEventsIfNeeded() {
    if (eventQueue_.size() >= EVENT_QUEUE_SIZE_THRESHOLD) {
        connectionQueue_.recordEvents(eventQueue_.events());
    }
}

private static int EVENT_QUEUE_SIZE_THRESHOLD = 10;
调用该方法,会将Event数据存入Event队列,当存入的数据大于等于10条时,将Event队列的数据转化成JsonArry格式移动到Connection队列
移动的同时,Event队列的数据删除(eventQueue_.events()方法会执行这个操作)
通知后台任务将队列中的数据从前到后一条一条上送给服务端,直到队列没有数据为止

recordView方法
在开启视图追踪时,记录的View就是Activity(自动记录),也可以主动记录要记录的View的名字,在记录View相关数据的同时,也会记录两次调用recordView的时间间隔。最终调用recordEvent方法将数据插入Event队列。

setUserData方法
将用户相关的信息,直接放入Connection队列,并清空用户信息

startEvent和endEvent(事件的唯一性由key值决定)
这两个方法应该成对使用,当调用startEvent时,会将此事件暂时记录,当调用endEvent,会将发生在start到event之间的数据,通过调用recordEvent方法加入到Event队列

5. 总结

该框架收集信息的总体流程
数据收集->放入Event队列->放入Connection队列->传递给服务器

其中数据从Event队列转移到Connection队列的触发要求:

  1. Event队列超出设置的最大事件数
  2. 计时器触发(每隔60S一次)
    二者只要满足其一就会触发

Event队列一次添加一个事件
Connection队列一次添加一个Event队列

一旦数据添加到Connection队列,就会自动触发后台任务将数据传递给服务器

传递给服务器的数据是从Conection队列的首部开始一个一个传递给服务器的

每一个Event事件都包含的属性

countlyStore_.addEvent(key, segmentation, timestamp, hour, dow, count, sum, dur);

每一个Connection事件包含的属性

final String data = "app_key=" + appKey_
                      + "&timestamp=" + Countly.currentTimestampMs()
                      + "&hour=" + Countly.currentHour()
                      + "&dow=" + Countly.currentDayOfWeek()
                      + "&events=" + events
                      + "&sdk_version=" + Countly.COUNTLY_SDK_VERSION_STRING
                      + "&sdk_name=" + Countly.COUNTLY_SDK_NAME;

        store_.addConnection(data);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,640评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,254评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,011评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,755评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,774评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,610评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,352评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,257评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,717评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,894评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,021评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,735评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,354评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,936评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,054评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,224评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,974评论 2 355

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,657评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,639评论 18 399
  • 数字是我的好朋友。我们的友谊 是在初中 莫名其妙担任了三年数学课代表开始培养和建立起来的。有点包办的味道 倒也是一...
    Vivian_dh阅读 199评论 0 0
  • 我们是小学同学,他很优秀,老师眼中的好孩子,她也很优秀同样是老师眼中的好孩子,我喜欢他,其实那时候才小学算得上是喜...
    sunshineL_7c72阅读 271评论 0 0