4399 Analy 客户端接入文档

文档版本 变更时间 变更内容
v1.0.0 2019-05-23 初始化文档,并加入主要内容
v1.1.0 2019-05-27 增加初始化时用户参数的说明
v1.2.0 2019-10-21 日志发送后台配置;应用启动和关闭记录;记录事件时长;自动埋点

4399 Analy SDK,是4399用户分析平台的一部分,为开发者提供 Gradle 插件和接口,帮助开发者上报事件到4399用户分析平台,以进行数据分析挖掘。

接入条件

SDK 支持 Java 8 Lambda 表达式语法和 Android DataBinding

一、重要概念

事件

用户行为
: 用户在应用中的所有操作,组成的轨迹;对用户行为进行分析,可以作为应用设计合理性判定的依据

事件 : 简单事件,用户行为的基本组成部分,通常对应一个简单行为或操作,如启动应用、进入页面、点击控件等
合成事件,用户轨迹中的一些简单事件的组合,通常是按时间先后发生

事件属性 : 描述事件本身和事件来源或发生对象的一些信息,一条属性一般对应一个“名字-值”的键值对,大致有两类 :
内置属性,指事件固有的、SDK 默认加入的属性,如事件发生时间等;
用户属性,开发者在事件属性集合中追加的更多的键值对,以更详细地描述事件

事件维度 : 指事件发生的环境,比如应用渠道、版本,设备机型、系统 API 版本,网络等

上报与埋点

上报 : 事件产生后通过http请求将事件属性发送到服务端,服务端可能会进行一定的筛选、汇总,但不一定立即开始分析

埋点
: 事件上报对应的代码实现即为埋点,埋点又分两种形式——手动埋点,和自动埋点
自动埋点,通过 Gradle 插件将埋点代码在编译阶段插入到页面和点击事件中,而不需要手工编写。
手动埋点,开发者也可以根据自己的需要在特定代码插入上报方法,更加灵活、精准,且可以传入自定义事件属性

自动埋点支持下列事件

名称 标识 描述
进入Activity AutoActivityViewScreen 当触发 onResumed 时触发
进入Fragment AutoFragmentViewScreen 当 Fragment 可见状态更改,且可见时触发
点击控件 AutoClick 当按钮被点击时触发,所支持控件包括:
android/view/View$OnClickListener
android/content/DialogInterface$OnClickListener
android/content/DialogInterface$OnMultiChoiceClickListener
android/widget/CompoundButton$OnCheckedChangeListener
android/widget/RatingBar$OnRatingBarChangeListener
android/widget/SeekBar$OnSeekBarChangeListener
android/widget/RadioGroup$OnCheckedChangeListener
android/widget/AdapterView$OnItemClickListener
android/widget/AdapterView$OnItemSelectedListener
android/widget/ExpandableListView$OnGroupClickListener
android/widget/ExpandableListView$OnChildClickListener

支持 java 8 lambda表达式形式的点击回调
支持 DataBinding点击回调
支持ButterKnife绑定

可视化

可视化 : 服务端对上报的事件进行存储,提供前端工具,根据事件维度、事件属性选取事件,并产生表格和图表,也可能会对数据进一步分析挖掘

标识

更多术语参考服务端说明(todo)

二、快速上手

注册应用

接入前,请到 4399 用户分析平台注册应用。 注册完成后,将得到media id,这是调用 SDK 接口的必须参数

获取插件/SDK

4399 Analy SDK 暂时只支持 Android Studio 开发环境的接入,插件和 SDK 都是通过在线依赖提供的,只要在 gradle 相关文件中加入依赖配置即可获取

在项目的 setting.gradle文件顶部添加插件在线依赖

// Analy Plugin:配置插件仓库
pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.name == 'analytics-plugin') {
                // 请使用实际的、最新版本的插件
                useModule "cn.m4399.sdk:analytics-plugin:${ANLAY_PLUGIN_VERSION}"
            }
        }
    }
    repositories {
        // Analy Plugin:插件快照仓库,当对接完成时可以移除此仓库
        maven {
            url 'http://mvn.4399doc.com:8081/repository/maven-snapshots'
        }
        // Analy Plugin:正式发布仓库
        maven {
            url 'http://mvn.4399doc.com:8081/repository/maven-releases'
        }
        gradlePluginPortal()
    }
}

在主 module 中下的build.gradle文件中添加

repositories {
    // Analy SDK:快照仓库,发布后可以去掉
    maven {
        url 'http://mvn.4399doc.com:8081/repository/maven-snapshots'
    }
    // Analy SDK:正式发布仓库
    maven {
        url 'http://mvn.4399doc.com:8081/repository/maven-releases'
    }
}

接入 SDK

1、Gradle 配置

在主 module 中下的build.gradle文件中

// Analy Plugin:文件顶部应用插件
plugins {
    id 'analytics-plugin'
}
apply plugin: 'com.android.application'

android {
    // android dsl
}

// Analy Plugin:Gradle 自动埋点配置,关于此 DSL 的说明可以参考后文
analy {
    // jar包是否需要自动埋点
    enableJar true
    // 是否开启多线程并行构建
    enableParallel true
    // 是否支持增量构建
    enableIncremental true
    // 是否支持lambda
    enableLambda true

    include 'cn.m4399.analy.demo.autoclicktest.**'
    include 'cn.m4399.analy.demo.Home*'

    include { String className ->
        className.contains('autoclicktest')
    }
}

repositories {
    // 依赖配置,这里会添加在线仓库地址
}

dependencies {
    // Analy SDK:发布时使用最新的release版本
    implementation 'cn.m4399.sdk:analytics:${ANALY_SDK_VERSION}'
}

2、混淆配置

-keeppackagenames cn.m4399.analy
-keep class cn.m4399.analy.** {*;}

3、接口调用

为更快速接入,开发者可以使用后台的代码生成器(todo),生成接入代码.

默认支持, 应用启动和关闭的监控.

初始化

由于需要监控 Activity 声明周期, 来判断应用是否置于后台, 因此, 尽量在 Application 中初始化SDK.

new MobileAnalytics.Initializer(getApplicationContext())
        .withMedia(new AnalyticsMedia()
                .withMediaId("your_media_id")           // 应用媒体id,必须
                .withChannelId("your_app_channel_id")   // 应用渠道id,可选
        )
        .withEnv(new AnalyticsEnv()
                .withUserAgent("chrome/xxxx")           // userAgent 可选
                .withAppEnv("online")                   // appEnv 可选
         )
        .withUser(new AnalyticsUser()
                .withUid("uid_in_your_app")             // uid,可选
                .withVid("uniq_vid_in_your_app")        // vid,唯一,建议
        )
        .withOptions(new AnalyticsOptions()
                .debuggable(false)                      // 是否调试,可选,默认false
                .withAutoTrace(true)                    // 是否允许自动埋点,可选,默认false
                .withFlushBuffSize(2)                  // 设置事件缓冲大小,满后上报,可选,默认2条
                .withFlushInterval(5_000)                  // 设置上报时间间隔,单位毫秒,可选,默认5000秒
                .withDialogContextClass(activityClass) //设置附着调试对话框的页面
        )
        .initialize();

其中uidvid也提供了对应的静态设置方法,便于用户信息改变后重新设置

事件属性
MobileEvent.maker("simpleEvent")  // 事件标识,可自定义
        .property("prop1", "xxx") // 添加自定义属性
        .property("prop2", "xxxx")
        .property("int", 123)
        .property("boolean", true)
        .property("float", 123.11f)
        .property("double", 123.654)
        .commit();       // 加入到事件缓冲
用户属性
/**
 * 1.设置用户属性
 * 直接设置一个用户的 Profile,如果用户或者Profile的字段已存在,
 * 则覆盖,不存在则自动创建。
 **/
 MobileProfile.setMaker()
        .property("name", "xiao ming")
        .property("age", 18)
        .property("sex", "male")
        .commit();
        
/**
 * 2.撤销用户属性
 * 将某个用户的某些属性值设置为空。
 **/
 MobileProfile.unsetMaker()
        .property("name", "")
        .commit();

/**
 * 3.删除用户属性
 * 删除一个用户的整个Profile
 **/
MobileProfile.deleteMaker()
        .commit();

/**
 * 4.提交固定有户属性
 * 直接设置一个用户的Profile如果用户或者 Profile 的字段已存在,
 * 则这条记录会被忽略而不会覆盖已有数据,如果Profile不存在则会自动创建。
 * 因此,profile_set_once比较适用于为用户设置首次激活时间、
 * 首次注册时间等只在首次设置时有效的属性。
 **/
 MobileProfile.setOnceMaker()
        .property("channel", "dc8989a0")
        .commit();

/**
 * 5.提交数字类型属性
 * 必须是数字类型。增加或减少一个用户的某个NUMBER类型的Profile值,
 * 比如给用户属性 的充值金额加1或者减1。如果用户表(users表)中不存在这个用户,
 * 则会在用户表中自动创建该用户的id记录,并给该用户设置相应的Profile属性值,
 * 会在默认值0的基础上增加上传的Profile值。
 **/
 MobileProfile.incrementMaker()
        .property("age", 20)
        .commit();
        

/**
 * 6.提交固定有户属性
 * 必须是列表类型。向某个用户的某个数组类型的Profile添加一个或者多个值。
 * 如果本次上传的值,与系统中已存在的值有重复,默认是不会去重的。如果本次上传的值,
 * 有重复项,也不会去重的。
 **/
ArrayList<String> apps = new ArrayList<>();
list.add("qq");
list.add("wechat");
MobileProfile.appendMaker()
        .property("apps", apps)
        .commit();

自动埋点并不需要开发者写任何代码,只需要注意include/exclude规则,详见进阶用法

三、进阶用法

事件发送策略

当事件commit()后,SDK不一定立即发送,而是加入缓冲,满足一定条件再发送。SDK 允许开发者自定义事件发送策略,

追踪事件的历时

// 事件开始时调用
MobileEvent.maker("eventTest")
        .startTrack();

// 事件结束时调用
MobileEvent.maker("eventTest")
        .property("prop1", "xxx")
        .commit();
// 事件开始时调用
MobileEvent.maker("play music")
        .startTrack("see you again");

// 事件结束时调用
MobileEvent.maker("play music")
        .tag("see you again")
        .property("prop1", "xxx")
        .commit();

但是请注意:计时事件在首次maker()后添加属性是无效的,而应该在第二次调用maker()后添加;
如果一定要这样做,可以在首次maker()保留事件引用,commit()时使用引用

自动埋点开关

有两种方式可以控制是否启用自动埋点

include/exclude 规则

默认的自动埋点,是“全埋点”,即所有Activity/Fragment的关键生命周期方法、点击回调方法都会插入埋点代码。对此,你可能会有一些特别的include/exclude要求,我们提供了这样的支持。

include/exclude 规则与 Gradle 的默认方式保持一致,即

incluce/exclude dsl 用法举例如下

// 忽略单个或多个名字确定的class
analy {
    exclude 'cn.m4399.analy.demo.HomeFragment'
}

// 忽略一个包下的class
analy {
    exclude 'cn.m4399.analy.demo.*'
}

// 忽略一个包下的class,递归
analy {
    exclude 'cn.m4399.analy.demo.**'
}

// 使用闭包,根据类名,精确控制
analy {
    exclude { String className ->
        className.startsWith('cn.m4399.analy.demo')
    }
}

如果选择了支持 lambda 自动埋点, 需要在项目根目录 gradle.properties文件中添加配置

android.enableD8.desugaring=false

如何使用合成事件

// TODO

四、调试

清单文件

当开启自动埋点时,插件会将处理结果生成一份清单文件,在主module的build/reports/analytics-plugin-inject.txt

SDK debug 模式

当初始化选项里,打开了 debug 开关: AnalyticsOptions.debuggable(true),SDK 将会打印事件属性

2019-05-23 15:51:53.880 17629-17629/cn.m4399.analy.demo D/m4399AnalyticsSDK: [main] Uploader.queueTo: {
        "userinfo": {
            "uid": "56666666666",
            "vid": "8963hhjjhh",
            "$imei": "868299031886582",
            "$imsi": "",
            "$androidid": "ebd2264bae8230e5",
            "$channel": "9990999099"
        },
        "appinfo": {
            "$app_version": "1.1",
            "$version_code": "2",
            "$package_name": "cn.m4399.analy.demo"
        },
        "env": {
            "root": false,
            "emulator": false,
            "xposed": false,
            "$network_type": "WIFI",
            "$model": "ALP-AL00",
            "$useragent": "system:9_28",
            "$screen_width": 1080,
            "$screen_height": 1920
        },
        "event": "AutoActivityViewScreen",
        "client_timestamp": 1558597913873,
        "properties": {
            "$element_class": "cn.m4399.analy.demo.MainActivity",
            "$element_title": "4399分析SDK"
        }
    }

在线实时调试

准备

配置入口 Activity

<activity
    android:name=".MainActivity"
    android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <!-- 在线实时调试配置 -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.BROWSABLE" />
        <category android:name="android.intent.category.DEFAULT" />

        <data
            android:host="analy.m4399.cn"
            android:scheme="debug" />
    </intent-filter>
</activity>

然后打包,安装应用到手机上

操作

注意使用新二维码扫描打开DEBUG模式,需要重启应用。

上述步骤完成后, 开发者可以进行正常应用操作,并观察实时发送到后台的数据

五、附录

附录一:API 详情

查看 analytics.javadoc-sdk-1.2.11+26

附录二:FAQ

A:是否支持eclipse + adt 方式接入?
Q:暂时不支持

A:当使用SNAPSHOT版本时,依赖不能更新怎么办?
Q:使用以下方法之一

// app是使用依赖的module,dependencies是任务名称,也可以换成build、assemble等
gradlew -p app dependencies --refresh-dependencies

A:开启r8优化后埋点插件异常
Q: r8优化尚不成熟,可以禁用它

// 在根项目的gradle.properties中
android.enableR8=false