Current Path:Home » Documents » API Docs » The text

Coraool Android SDK 开发指南

1. 集成流程

1.1 从MavenCentral引入SDK

点开 MavenCentral中心仓库 ,并搜索关键字 coraool-android-sdk,如下图:

1.1.1 Gradle项目

在build.gradle增加指定版本的依赖

1. 项目中添加从 mavenCentral() 仓库获取依赖

2. 添加依赖
dependencies {
    implementation 'com.coraool:coraool-android-sdk:2.1.1'
}

1.1.2 Maven项目

在pom.xml中增加指定版本的依赖

<dependency>
    <groupId>com.coraool</groupId>
    <artifactId>coraool-android-sdk</artifactId>
    <version>${version}</version>
</dependency>

1.2 从本地Lib库引入SDK

把sdk拷贝到应用的 libs 目录下,在对应模块的 build.gradle 中添加aar包的依赖

implementation files("libs/coraool-android-sdk-2.1.1.aar")
SDK VersionVersionDateRelease NotesAssets
2.0.920240820Native+Jsbridge埋点功能远程接口调用ABTest功能GTX流量追踪

1.3 配置SDK

1.3.1 权限授予

权限权限用途
ACCESS_NETWORK_STATE检测联网方式,在网络异常状态下避免数据发送,节省流量和电量。
INTERNET允许应用程序联网和发送统计数据的权限,以便提供统计分析服务。
ACCESS_FINE_LOCATION(可选)通过获取位置信息,为开发者提供反作弊功能,剔除作弊设备;同时校正用户的地域分布数据,使报表数据更加准确。
ACCESS_COARSE_LOCATION(可选)通过获取位置信息,为开发者提供反作弊功能,剔除作弊设备;同时校正用户的地域分布数据,使报表数据更加准确。
<uses-sdk android:minSdkVersion="8"></uses-sdk>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

1.3.1 配置混淆

如果您的应用使用了代码混淆,请添加如下配置,避免SDK被错误混淆

-keep class com.coraool.** { *; }
-keepclassmembers class * {
   public <init> (org.json.JSONObject);
}

1.4 初始化步骤

1.4.1 申请AK

每个app接入前,需要申请 AppId、AppKey、AppSecret

1.4.2 SDK初始化

SDK对外提供的接口类名为 com.coraool.CoraoolSDK,所有的方法都通过这个类对外提供服务。

首先在Application的onCreate方法中,使用Coraool分配的Token对SDK进行初始化:

/**
 * Call this method to initialize Coraool SDK when launch the application.
 *
 * @param application   application object
 * @param paramProvider interface
 */
public void initialize(Application application, IParamProvider paramProvider);

初始化化示例:

public class CApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        
        // 用户身份标识请在SDK初始化之前设置,因为后续初始化过程需要用到
        CoraoolSDK.setting.setUserId("your_user_id");
        CoraoolSDK.setting.setCustomDeviceId("my_unique_device_id");
        CoraoolSDK.initialize(this, new IParamProvider() {
            @Override
            public String getAppId() {
                return "${coraool_appId}";     // 在coraool申请
            }

            @Override
            public String getAppKey() {
                return "${coraool_appKey}";    // 在coraool申请
            }

            @Override
            public String getAppSec() {
                return "${coraool_appSec}";    // 在coraool申请
            }

            @Override
            public boolean isEnableLog() {
                return true;
            }
        });
        Logger.getLogger("Application").info("Init coraool sdk done");
    }
}

1.5 其他SDK配置

SDK配置相关的API统一由 CoraoolSDK.setting 接口对象管理

1.5.1 登录用户ID

用户登录、退出的时候,需要实时更新登录信息

/**
 * Call this api to update the login account whenever login, logout or switch account.
 *
 * @param userId login user id
 */
public void setUserId(String userId);

1.5.2 日志开关

开发阶段建议打开日志开关,方便检查SDK的关键流程,以及打点日志的内容。线上发布前请关闭此开关,避免日志打印影响到APP性能

/**
 * Turn on this switch in DEBUG mode to trace sdk logs in different levels.
 * Turn it off before publishing app to ensure better performance in production situation.
 *
 * @param enableLog switch
 */
public void setEnableLog(boolean enableLog);

1.5.3 严格模式

开发阶段的debug模式建议打开,用于检查各类埋点参数使用是否合理。线上发布前请关闭,保证App的稳定性。

/**
 * Enable [StrictMode] will check all api criteria while running and throw errors if wrong.
 * It is recommended to turn on strict mode in DEBUG mode and turn it off before publish.
 * This will make sure all usages are correct and make the data engineering easier.
 *
 * @param strictMode default false
 */
public void setStrictMode(boolean strictMode);

2. 埋点接口

2.1 Tracking埋点

埋点相关的API统一由 CoraoolSDK.tracker 接口对象管理。

2.1.1 点击埋点

接口定义:为点击事件增加埋点

/** * Track click event * @param eventName Event name * @param eventValue Event value map */ public void click(String eventName, Map<String, Object> eventValue);

参数说明:

字段类型是否必须解释说明
eventNamestring事件名称标识用户在页面上操作的位置
eventValueMap<String, Object>事件参数和当前事件关联的业务参数,用于离线分析
eventValue_keystring事件参数key和当前事件关联的业务参数,用于离线分析
eventValue_valuestring事件参数value和当前事件关联的业务参数,用于离线分析

示例代码:

Map<String, Object> eventValue = new HashMap<>();
eventValue.put("业务参数key1", 200)
eventValue.put("业务参数key2", "业务参数value2")
CoraoolSDK.tracker.click(String eventName, Map<String, Object> eventValue);

2.1.2 曝光埋点

接口定义:为模块曝光事件增加埋点

/** * Track expose event * @param eventName Event name * @param eventValue Event value map */ public void expose(String eventName, Map<String, Object> eventValue);

参数说明:

字段类型是否必须解释说明
eventNamestring事件名称标识用户在页面上操作的位置
eventValueMap<String, Object>事件参数和当前事件关联的业务参数,用于离线分析
eventValue_keystring事件参数key和当前事件关联的业务参数,用于离线分析
eventValue_valuestring事件参数value和当前事件关联的业务参数,用于离线分析

示例代码:

Map<String, Object> eventValue = new HashMap<>();
eventValue.put("业务参数key1", 200)
eventValue.put("业务参数key2", "业务参数value2")
CoraoolSDK.tracker.expose(String eventName, Map<String, Object> eventValue);

2.1.3 自定义埋点

接口定义:增加自定义埋点

/** * Track custom event * @param eventName Event name * @param eventValue Event value map */ public void custom(String eventName, Map<String, Object> eventValue)

参数说明:

字段类型是否必须解释说明
eventNamestring事件名称标识用户在页面上操作的位置
eventValueMap<String, Object>事件参数和当前事件关联的业务参数,用于离线分析
eventValue_keystring业务参数key和当前事件关联的业务参数,用于离线分析
eventValue_valuestring业务参数value和当前事件关联的业务参数,用于离线分析

示例代码:

Map<String, Object> eventValue = new HashMap<>();
eventValue.put("业务参数key1", 200)
eventValue.put("业务参数key2", "业务参数value2")
CoraoolSDK.tracker.custom(String eventName, Map<String, Object> eventValue);

2.1.4 页面埋点

2.1.4.1 采集模式

接口定义:

public void setPageCollectionMode(int mode);

参数说明:

参数解释说明
mode页面事件的采集方式CoraoolLibConst.PageMode.Manual 手动(默认方式)CoraoolLibConst.PageMode.AUTO 自动

示例代码:

// 自动采集选择:仅支持采集activity,在使用AUTO模式时,可以叠加手动模式,实现方式看#自动埋点API
CoraoolSDK.tracker.setPageCollectionMode(CoraoolLibConst.PageMode.AUTO);

//手动采集选择:支持activity和非activity,默认手动
CoraoolSDK.tracker.setPageCollectionMode(CoraoolLibConst.PageMode.Manual);
2.1.4.2 自动埋点

接口定义:增加页面事件的埋点参数

/** * Add properties to this page which will be submitted in the Page Event. * Example: * When a customer opens a product detail page in a shopping app, we can append * the product itemId to the page event using this method. Later we can do some * analysis based on these properties. * * @param pageObject Activity * @param properties data */ public void updatePageProperties(Object pageObject, Map<String, Object> properties)

参数说明:

方法名称参数解释说明
updatePagePropertiespageObject页面Activity对象
properties更新参数只应用于当前页面

示例代码

/**
 * 添加页面事件的参数,仅对当前页面实例生效
 */
Map<String, Object> properties = new HashMap<>();
eventValue.put("业务参数key1", 200)
eventValue.put("业务参数key2", "业务参数value2")
CoraoolSDK.tracker.updatePageProperties(Object pageObject, Map<String, Object> properties);
2.1.4.3 手动埋点

接口定义

1.1 页面展现的时候调用(onResume)

public void trackPageStart(Object pageObject)

1.2 页面展现的时候调用,并通过API指定页面名称(onResume)

public void trackPageStart(Object pageObject, String customPageName);

1.3页面展现的时候调用,并通过API指定页面名称,仅在页面自动埋点时需要(onResume)

public void trackPageStart(Object pageObject, String customPageName, boolean skipPage)

2. 页面退出的时候调用(onPause)

public void trackPageEnd(Object pageObject);

参数说明:

方法名称参数解释说明
trackPageStartpageObject页面Activity对象
customPageName自定义页面名称
skipPage是否跳过本次的页面事件仅开启页面自动埋点时有用
trackPageEndpageObject页面Activity对象
customPageName自定义页面名称
/**
 * 页面展现的时候调用(onResume)
 */
protected void onResume() {
    super.onResume();
    CoraoolSDK.tracker.trackPageStart(homeActivity);
}

/**
 * 页面退出的时候调用(onPause)
 */
protected void onPause() {
    super.onPause();
    CoraoolSDK.tracker.trackPageEnd(Object pageObjet);
}

2.2 GTX埋点协议

请查看 AndroidGTX对接手册

3. Invoke API接口

Coraool SDK提供了基于API的数据服务,并且定义了一套通用且对调用方非常友好的接口,通过Coraool SDK发起 Invoke 接口调用通常包含以下4个步骤:

3.1 构造Response

com.coraool.CoraoolResponse是对Coraool API协议的封装,包含了3个字段,如果不关心请求的结果,那么直接用这个类接收请求结果即可;如果有业务数据需要处理,则需要继承这个类,并增加 result 字段,并提供getter和setter方法,按照Coraool API协议的约定,API调用返回的业务参数会保存在这个Map结构内。SDK会自动进行反序列化,方便应用层直接使用。

参数说明:

参数类型解释说明
successboolean本次请求是否成功当且仅当这个字段为true时,返回结果才有效
codeint错误码200表示成功,其他值类似http状态的定义,如果返回负数表示SDK自己发生了异常,具体的错误码由CoraoolResponse的常量进行定义
messagestring请求结果的文本描述仅仅用于协助排查请求过程,不能用于业务逻辑的判断。在请求成功的状态下总是返回 "SUCCESS",如果请求出现错误或者异常,则返回对应的错误描述信息,可以根据错误描述信息进行排查或者反馈给技术支持;
resultany自定义的业务数据类型如果需要关注请求的结果,按照Coraool API的协议约定,数据会保存在以 result 为Key的JSON对象内

示例代码:

public class CoraoolRankingResponse extends CoraoolResponse {

    // RankingData表示具体的业务数据
    public RankingData result;
    
    public RankingData getResult() {
        return result;
    }
    
    public void setResult(RankingData result) {
        this.result = result;
    }
}

public class RankingData {
    public JsonArray ranking;
    public JsonObject track;
    public String version;
}

3.2 构造Request

通过创建 CoraoolRequest 类型的对象,构造符合 Coraool API 协议的请求参数

参数说明:

参数类型解释说明
apiNamestring接口名称在Coraool open API 上注册的业务接口,例如open.coraool.home.game.ranking
apiVersionstring接口版本在Coraool open API 上注册的业务版本,例如1.0.0
dataany请求参数具体的请求参数对象
connectTimeoutint链接超时,单位毫秒网络连接超时
readTimeoutint读超时,单位毫秒返回数据流读取超时
callbackOnMainThreadboolean回调主线程的开关是否回调到UI主线程,默认是true,对于非直接显示的数据,建议设置为false,让请求回调到后台线程,方便对数据进行二次处理

示例代码:

CoraoolRequest request = new CoraoolRequest();
request.setApiName("open.coraool.home.game.ranking");
request.setApiVersion("1.0.0");
request.setCallbackOnMainThread(true);
request.setReadTimeout(3 * 1000);
request.setData(new HashMap<String, Object>(){{
    put("userId", "登录用户ID");
    put("afId", "appsFlyer的ID");
    put("deviceId", "设备ID");
}});

3.3 发起请求

SDK的请求API分为同步请求和异步请求,统一封装在 CoraoolSDK.api 的接口对象下

3.3.1 同步请求

接口定义:

/**
 * Send a coraool request synchronously.
 *
 * @param clz Response class type
 * @param request request complies with coraool api protocol
 * @return response complies with coraool api protocol
 * @param <T> { body }
 */
public <T extends CoraoolResponse> T syncInvoke(Class<T> clz, 
                                                CoraoolRequest request)

/**
 * Send a request synchronously. If the callback interface is provided,
 * the interface will be invoked before this method returns.
 *
 * @param clz Response class type
 * @param request request complies with coraool api protocol
 * @param callback callback when done
 * @return response complies with coraool api protocol
 * @param <T> { body }
 */
public <T extends CoraoolResponse> T syncInvoke(Class<T> clz, 
                                                CoraoolRequest request, 
                                                CoraoolNetCallback<T> callback)

参数说明:

参数名类型解释说明
clzClass<T>返回对象类的Class对应第一步Reponse对象类的Class
requestCoraoolRequest请求参数对应第二步请求参数对象
callbackCoraoolNetCallback<T>回调Callback如果提供了Callback接口参数,则本次请求总是会回调到Callback接口中的一个方法,接口方法的定义看下一步

返回值说明:

返回值类型解释说明
response<T extends CoraoolResponse>返回对象类对应第一步Reponse的对象实例,仅当对象无法被反射实例化的时候,才会出现null,所以一定要保留无参构造器

示例说明:

private void syncRequest() {
    CoraoolRequest request = new CoraoolRequest();
    request.setApiName("open.coraool.home.game.ranking");
    request.setApiVersion("1.0.0");
    request.setData(new HashMap<String, Object>(){{
        put("userId", "123");
        put("afId", "afIdx");
        put("deviceId", "devicedevice");
    }});
    
    CoraoolRankingResponse response = CoraoolSDK.api.
            .syncInvoke(CoraoolRankingResponse.class, request);
}

3.3.2 异步请求

接口定义:

/**
 * Send a request asynchronously. If the callback interface is provided,
 * the interface will be invoked before this method returns.
 *
 * @param clz Response class type
 * @param request request complies with coraool api protocol
 * @param <T> { body }
 */
public <T extends CoraoolResponse> void asyncInvoke(Class<T> clz,
                                                    CoraoolRequest request)
                                              
/**
 * Send a request asynchronously. If the callback interface is provided,
 * the interface will be invoked before this method returns.
 *
 * @param clz Response class type
 * @param request request complies with coraool api protocol
 * @param callback callback when done
 * @param <T> { body }
 */
public <T extends CoraoolResponse> void asyncInvoke(Class<T> clz, 
                                                    CoraoolRequest request, 
                                                    CoraoolNetCallback<T> callback)

参数说明:

参数名类型解释说明
clzClass<T>返回对象类的Class对应第一步Reponse对象类的Class
requestCoraoolRequest请求参数对应第二步请求参数对象
callbackCoraoolNetCallback<T>回调Callback如果提供了Callback接口参数,则本次请求总是会回调到Callback接口中的一个方法,接口方法的定义看下一步

示例说明:

private void asyncRequest() {
    CoraoolRequest request = new CoraoolRequest();
    request.setApiName("open.coraool.home.game.ranking");
    request.setApiVersion("1.0.0");
    request.setCallbackOnMainThread(true);
    request.setReadTimeout(5 * 1000);
    request.setData(new HashMap<String, Object>(){{
        put("userId", "123");
        put("afId", "afIdx");
        put("deviceId", "devicedevice");
    }});
    
    CoraoolSDK.api.asyncInvoke(CoraoolRankingResponse.class, request, new CoraoolNetCallback<CoraoolRankingResponse>() {
        @Override
        public void onSuccess(CoraoolRankingResponse response) {
            Log.e("TAG", "Success: " + JSON.toJSONString(response));
        }

        @Override
        public void onFailed(int code, String message) {
            Log.e("TAG", String.format("Failed: code=%d, message=%s", code, message));
        }

        @Override
        public void onSystemError(int code, String message) {
            Log.e("TAG", String.format("Error: code=%d, message=%s", code, message));
        }
    });
}

3.4 接口回调

接口回调用于接收正确和异常的结果

接口参数类型解释说明
onSuccessresponseT返回对象的类型请求被正确处理的时候返回,对应 success=true
onFailedcodeint请求错误码对应success=false的场景,如果签名错误、无效token等
messagestring错误描述
onSystemErrorcodeint请求错误码各类系统错误,如网络未连接、授权错误、数据解析异常等
messagestring错误描述
public interface CoraoolNetCallback<T> {

    /**
     * Totally success including network and business
     *
     * @param response response body {@link CoraoolResponse}
     */
    void onSuccess(T response);

    /**
     * Send request successfully but the response data contains business error, like
     * invalid appKey, signature mismatch, params illegal and so on.
     *
     * @param code error reason code leverages http status definition
     * @param message plaintext explaining the error reason.
     */
    void onFailed(int code, String message);

    /**
     * Errors like network not connected, auth error, protocol error and so on
     *
     * @param code {@link CoraoolLibConst}
     * @param message plaintext explaining the error reason.
     */
    void onSystemError(int code, String message);
}

4. Abtest 接口

ABTest相关的API统一由 CoraoolSDK.ab 接口对象管理。

4.1 初始化Abtest功能

通过重载 com.coraool.IParamProvider 接口的 isEnableAbtest 方法,即可开启Abtest功能。需要注意的事项:

  • Abtest模块的功能默认是打开的;
  • 用户身份标识会用于实验分桶的计算,所以类似userId的参数需要尽早设置,建议在调用initialize方法前完成
public class CApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        
        // 用户身份标识请在SDK初始化之前设置,因为后续初始化过程需要用到
        CoraoolSDK.setting.setUserId("123abc");
        CoraoolSDK.setting.setCustomDeviceId("my_unique_device_id");
        CoraoolSDK.initialize(this, new IParamProvider() {
            ...

            // 通过重载此方法,开始Abtest模块功能
            @Override
            public boolean isEnableAbtest() {
                return true;
            }
        });
    }
}

4.2 获取单实验分桶

接口定义

public String getABTest(String experimentName)

参数说明

参数解释说明
experimentName实验名称在实验平台上创建的实验名称

示例代码

String bucket = CoraoolSDK.ab.getABTest("HP_SEARCH_ENTRY_POS");
if ("bucket_a".equals(bucket)) {
    // do something for a
} else if ("bucket_b".equals(bucket)) {
    // do something for b
}

4.3 获取单实验分桶对象

接口定义

public CoraoolABTest getABTestObject(String experimentName)

参数说明

参数解释说明
experimentName实验名称在实验平台上创建的实验名称

示例代码

CoraoolABTest abtest = CoraoolSDK.ab.getABTestObject("HP_SEARCH_ENTRY_POS");

4.4 获取全部实验分桶

接口定义

List<CoraoolAbtest> getABTestListAll()

参数说明

参数解释说明

示例代码

List<CoraoolABTest> buckets = CoraoolSDK.ab.getABTestListAll();

AndroidGTX对接手册

1. GTP/GTC流量追踪

GTX埋点用于页面流量的追踪和分析,可以解决如下关键业务问题:

  • 统计指定页面的PV、UV等基础指标;
  • 追踪页面流量的来源和去向,分析用户路径的流量漏斗;
  • 基于流量和转化评估,告知业务方,每个页面以及页面内坑位的流量效率;
  • Global Tracking Position(GTP):全局位置跟踪模型,用于追踪位置以及不同位置之间流量的流转;
  • Global Tracking Content(GTC):全局内容跟踪模型,用于跟踪投放内容以及引导转化效率;
  • Global Tracking X (GTX):指代 GTP、GTC 构成的解决方案;
  • pageName:页面事件的事件名

1.1 GTP参数定义

GTP参数定义:a.b.c.d = ${appId}.${pageName}.${module}.${point},GTP需要严格按照如下规范进行构造和使用,UI层通过结构化的数据构造这4层结构(建议用这种方式),也可以通过手动的方式构造。

GTP含义说明
a位${appId}不同端独立分配,对应SDK初始化参数的appId,全局唯一
b位${pageName}由产品指定并申请,在当前 ${app} 内唯一,b位由接入方维护,通过文档或者系统登记
c位${moduleId}页面的楼层或者区块编号,在当前页面 ${pageName} 内唯一
d位${pointId}楼层内细分的点位编号,在当前模块 ${moduleId} 内唯一

1.2 GTC参数定义

GTC参数定义:a.b.c.d = ${sysId}.${algoId}.${algoVer}.${audienceId},GTC也包含4层结构,在不同层级上的定义

GTC含义说明
a位${sysId}投放系统 ID,用来标识不同的内容投放方
b位${algoId}投放算法 ID,用来标识投放系统产生不同内容的投放算法
c位${algoVer}投放算法版本 ID,用来标识投放算法的不同版本
d位${audienceId}投放人群 ID,用来标识不同的投放人群

2.埋点接入

2.1 埋点时机说明

每个页面事件包含: [开始 -> 过程 -> 结束] 这三个阶段,每个阶段需要严格按照文档说明调用CoraoolSDK的API方法,使得每个页面事件的区间完整闭合,最终页面事件会构成一个序列来表述用户的动线。

首先需要定义清楚页面是什么?从用户视角看,页面应该是用户在手机上看到一屏内容,典型的比如:由Activity实现的搜索结果页、由Activity实现的详情页、会场页由Fragment实现多个Tab,每个tab也可以被定义为一个页面,请遵循您的产品或者业务方对页面的定义来进行划分。

下面按不同的页面定义来说明埋点API应该在什么时刻被调用,请关注下图红线的指示:

2.2 GTX传参方式

上面介绍完GTX调用时机,这一节讲解怎么把GTX参数从一个页面传到另一个页面。因为Android系统提供了多种传参方式,不同类型的页面也不尽相同,所以前后两个页面的传参方式需要事先约定好协议,下面分别对Activity和Fragment进行说明。

2.2.1 Activity页面传参

方式1:通过Intent#putExtra(key, value) ,可以把参数从 FromActivity 传递到 ToActivity,对于CoraoolSDK,我们定义了 CoraoolLibConst.KEY_GTPCoraoolLibConst.KEY_GTC两个常量Key作为约定,ToActivity会尝试读取这两个key的值:

findViewById(R.id.you_view_id).setOnClickListener(v -> {
    // 把GTX参数从FromActivity传到ToActivity,这样ToActivity读取KEY_GTP/KEY_GTC就可以知道页面来源
    Intent intent = new Intent(FromActivity.this, ToActivity.class);
    intent.putExtra(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
    intent.putExtra(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前内容");
    FromActivity.this.startActivity(intent);
}

方式2:通过Intent#setData(Uri),可以把参数从FromActivity传递到ToActivity,对于CoraoolSDK,我们定义了 CoraoolLibConst.KEY_GTPCoraoolLibConst.KEY_GTC两个常量Key作为约定,ToActivity会尝试读取这两个key的值:

findViewById(R.id.you_view_id).setOnClickListener(v -> {
    // 执行切换Activity
    Uri uri = Uri.parse("protocol://your.uri?k1=v1&k2=v2").buildUpon()
            .appendQueryParameter(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
            .appendQueryParameter(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前内容");
            .build();
    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
    startActivity(intent);
}

方式3:通过在点击事件上增加gtp,gtc参数,系统会自动捕获点击事件里的gtp,gtc作为页面的来源

findViewById(R.id.you_view_id).setOnClickListener(v -> {
    Map<String, Object> eventValue = new HashMap<>();
    String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
    eventValue.put(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
    eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前页面");
    CoraoolSDK.tracker.click("GotoNextActivity", eventValue);
    
    // 执行切换Activity
    Intent intent = new Intent(FromActivity.this, ToActivity.class);
    FromActivity.this.startActivity(intent);
});

CoraoolSDK同时支持这3种传参方式,使用的时候三选一,如果存在多个,则优先级:方式1 > 方式2 > 方式3

对于大多数场景,第三种的接入方式最优化,只需要关注对应的点击事件即可,第1/2种方式需要用户对GTP/GPC的原理有比较深入的理解;

2.2.2 Fragment页面传参

通过 Framgent.setArguments(Bundle),可以把参数从 FromFragment 传递到 ToFragment,对于CoraoolSDK,我们定义了 CoraoolLibConst.KEY_GTPCoraoolLibConst.KEY_GTC两个常量Key作为约定,ToFragment会尝试读取这两个key的值:

方式1:通过Bundle#putString(key, value) ,可以把参数从 FromFragment 传递到 ToFragment,对于CoraoolSDK,我们定义了 CoraoolLibConst.KEY_GTPCoraoolLibConst.KEY_GTC两个常量Key作为约定,ToFragment会尝试读取这两个key的值:

findViewById(R.id.you_view_id).setOnClickListener(v -> {
    Fragment toFragment = new Fragment();
    Bundle bundle = new Bundle();
    bundle.putString(CoraoolLibConst.KEY_GTP, "四位gtc构成的值,指代当前页面");
    bundle.putString(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前内容");
    toFragment.setArguments(bundle);
    
    // 执行切换Fragment
    getFragmentManager().beginTransaction()
        .replace(R.id.fragment_container, toFragment)
        .commit();
}

方式2:通过在点击事件上增加gtp,gtc参数,系统会自动捕获点击事件里的gtp,gtc作为页面的来源

findViewById(R.id.you_view_id).setOnClickListener(v -> {
    Map<String, Object> eventValue = new HashMap<>();
    String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
    eventValue.put(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
    eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前页面");
    CoraoolSDK.tracker.click("GotoNextFragment", eventValue);
    
    // 执行切换Fragment
    Fragment toFragment = new Fragment();
    getFragmentManager().beginTransaction()
        .replace(R.id.fragment_container, toFragment)
        .commit();
});
2.2.3 TabView传参

以TabView为容器的页面,没有类似Activity和Fragment的标准生命周期,需要以点击的方式增加gtp,gtc参数,类似 #Activity页面传参 的方式3;

方式1:通过在点击事件上增加gtp,gtc参数,系统会自动捕获点击事件里的gtp, gtc作为页面的来源

findViewById(R.id.you_view_id).setOnClickListener(v -> {
    Map<String, Object> eventValue = new HashMap<>();
    String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
    eventValue.put(CoraoolLibConst.KEY_GTP, "四位gtp构成的值,指代当前页面");
    eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值,指代当前页面");
    CoraoolSDK.tracker.click("GotoNextView", eventValue);
    
    // 此处执行切换到下一个TabView的代码实现// 注意:TabView也需要执行在显示和隐藏的时候分别调用 trackPageStart 和 trackPageEnd
    ...
});

2.3 GTX埋点接口

2.3.1 页面开始

接口定义:

/* 记录页面开始 */ public void trackPageStart(Object pageObject); /* 记录页面开始,并自定页面名称 */ public void trackPageStart(Object pageObject, String customPageName); /* 记录页面开始,并自定页面名称,仅在开启自动埋点的时候使用 */ public void trackPageStart(Object pageObject, String customPageName, boolean skipPage);

参数说明:

参数类型解释是否必须说明
pageObjectActivity、Fragment、 WebView当前页面对象如果是 Activity 就传入 Activity 对象实例;如果是 Fragment 就传入 Fragment 对象实例;强烈建议让 Activity 和 Fragment 实现 ICoraoolPage 接口,并在接口方法中定义pageName,统一命名方式
customPageNamestring自定义页面名如果页面对象没有实现 ICoraoolPage 接口,通过这个入参可以自定义页面名称,否则SDK默认会以类名作为页面名,埋点验证时可解释性较差
skipPageboolean是否跳过当前页仅在使用Activity作为页面,并开启自动页面埋点时有意义,其他是否不应该设置该参数

示例代码:

public class MyActivity extends AppCompatActivity implements ICoraoolPage {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        CoraoolSDK.tracke.getInstance().trackPageStart(this);
    }
}
2.3.2 添加页面参数

接口定义:

public void updatePageProperties(Object pageObject, Map<String, Object> properties);

参数说明:

参数类型解释是否必须说明
pageObjectActivity、Fragment、 WebView当前页面对象如果是 Activity 就传入 Activity 对象实例;如果是 Fragment 就传入 Fragment 对象实例;强烈建议让 Activity 和 Fragment 实现 ICoraoolPage 接口,并在接口方法中定义pageName,统一命名方式
propertiesMap<String, Object>自定义业务参数把这些业务参数附加到当前页面事件中,用于离线业务分析,比如当前页面的展示的商品ID、SKU ID等,在页面结束之前,任意时刻都可以调用这个方法来收集运行使用过程中的业务参数。请参考上面的 #埋点时机说明

示例代码:

Map<String, Object> bizProps = new HashMap<String, Object>() {{
    put("例如itemId", "123456789");
    put("例如skuId", "987654321");
}};
CoraoolSDK.tracker.updatePageProperties(this, bizProps);
2.3.3 页面结束

调用这个方法意味着当前页面已经结束了,所有参数已经收集完成,将会触发页面事件提交。

接口定义:

public void trackPageEnd(Object pageObject);

参数说明:

参数类型是否必须解释说明
pageObjectActivity、Fragment、 WebView当前页面对象如果是 Activity 就传入 Activity 对象实例;如果是 Fragment 就传入 Fragment 对象实例;强烈建议让 Activity 和 Fragment 实现 ICoraoolPage 接口,并在接口方法中定义pageName,统一命名方式

示例代码:

public class MyActivity extends AppCompatActivity implements ICoraoolPage {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        CoraoolSDK.tracker.trackPageEnd(this);
    }
}
2.3.4 构造GTP参数

接口定义:

public String buildGtp(String gtp_b, String gtp_c, String gtp_d) ;

参数说明:

参数类型是否必须解释说明
gpt_bstringGTP 的 b 位
gpt_cstringGTP 的 c 位
gpt_dstringGTP 的 d 位

示例代码:

// 构造gtp参数
String gtp = CoraoolSDK.tracker.buildGtp("home", "topbar", "btn_show_number");
String gtp = CoraoolSDK.tracker.buildGtp("home", "topbar", "btn_new_fresh");

// 如果页面对象已经实现了 ICoraoolPage 接口,可以直接调用 getPageName() 获取GTP的B位 
String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_new_fresh");

3. 完整示例

3.1 Activity页面示例

/** 
 * 备注:接入方的App通过定义接口 ICoraoolPage,可以规范各个页面获取名称和ID的方式
 */
public class MyPageActivity extends AppCompatActivity implements ICoraoolPage {

    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_track_home_page);
        
        // 选择方式1:通过putExtra传参
        findViewById(R.id.you_view_id_intent).setOnClickListener(v -> {
            String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_checkin");
            Intent intent = new Intent(HomePageActivity.this, ListPageActivity.class);
            intent.putExtra(CoraoolLibConst.KEY_GTP, gtp);
            intent.putExtra(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
            HomePageActivity.this.startActivity(intent);
        });
        
        // 选择方式2:通过构造Uri传参
        findViewById(R.id.you_view_id_uri).setOnClickListener(v -> {
            String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_checkin");
            Uri uri = Uri.parse("protocol://your.uri?k1=v1&k2=v2").buildUpon()
                    .appendQueryParameter(CoraoolLibConst.KEY_GTP, gtp)
                    .appendQueryParameter(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
                    .build();
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        });
        
        // 选择方式3:在点击事件里增加gtp参数
        findViewById(R.id.you_view_id_click).setOnClickListener(v -> {
            // 先提交点击事件
            String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_checkin");
            Map<String, Object> eventValue = new HashMap<>();
            eventValue.put(CoraoolLibConst.KEY_GTP, gtp);
            eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
            CoraoolSDK.tracker.click("TopbarButtonCheckIn", eventValue);
            
            // 再执行页面跳转
            Intent intent = new Intent(HomePageActivity.this, ListPageActivity.class);
            HomePageActivity.this.startActivity(intent);
        });
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        CoraoolSDK.tracker.trackPageStart(this);
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        CoraoolSDK.tracker.trackPageEnd(this);
    }
    
    @Override
    public String getPageName() {
        return "home"
    }
}

3.2 Fragment页面示例

Fragment切换时的生命周期回调和Activity不同,系统会先调用ToFragment的创建方法并启动,再回调FromFragment的结束和销毁方法,针对这种情况,SDK已经做了兼容处理:

/** 
 * 备注:接入方的App通过定义接口 ICoraoolPage,可以规范各个页面获取名称和ID的方式
 */
public static final class MyPageFragment extends Fragment implements ICoraoolPage {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_track_tab, container, false);
        
        // 选择方式1:通过Bundle传递gtp参数
        findViewById(R.id.you_view_id).setOnClickListener(v -> {
            Bundle bundle = new Bundle();
            String gtp = ;CoraoolSDK.tracker.buildGtp(getPageName(), "topbar", "btn_checkin")
            bundle.putString(CoraoolLibConst.KEY_GTP, gtp);
            bundle.putString(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
            
            MyFragment fragment = new MyFragment();
            fragment.setArguments(bundle);
            getFragmentManager().beginTransaction().replace(R.id.fragment_container, fragment).commit();
        });
        
        // 选择方式2:在点击事件里增加gtp参数
        findViewById(R.id.you_view_id).setOnClickListener(v -> {
            // 先提交点击事件
            Map<String, Object> eventValue = new HashMap<>();
            String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
            eventValue.put(CoraoolLibConst.KEY_GTP, gtp);
            eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
            CoraoolSDK.tracker.click("GotoNextFragment", eventValue);
            
            // 再执行切换Fragment
            Fragment toFragment = new Fragment();
            getFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, toFragment)
                .commit();
        });
        
        
        return root;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onResume() {
        super.onResume();
        CoraoolSDK.tracker.trackPageStart(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        CoraoolSDK.tracker.trackPageEnd(this);
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    @Override
    public String getPageName() {
        return "Category";
    }
}

3.3 TabView页面示例

/** 
 * 备注:接入方的App通过定义接口 ICoraoolPage,可以规范各个页面获取名称和ID的方式
 */
public static final class MyPageTab extends TabLayout implements ICoraoolPage {

    private void onCreateTab() {
        // 选择方式2:在点击事件里增加gtp参数
        findViewById(R.id.you_view_id).setOnClickListener(v -> {
            // 先提交点击事件
            Map<String, Object> eventValue = new HashMap<>();
            String gtp = CoraoolSDK.tracker.buildGtp(getPageName(), "item", "1");
            eventValue.put(CoraoolLibConst.KEY_GTP, gtp);
            eventValue.put(CoraoolLibConst.KEY_GTC, "四位gtc构成的值");
            CoraoolSDK.tracker.click("GotoNextTabt", eventValue);
            
            // 再执行切换TabView
            ...
        });
    }

    /** 在Tab页出现的时候调用此方法 */
    private void viewAppear() {
        CoraoolSDK.tracker.trackPageStart(this);
    }
    
    /** 在Tab页消失的时候调用此方法 */
    private void viewDisappear() {
        CoraoolSDK.tracker.trackPageEnd(this);
    }
}

3.4 H5页面示例

H5页面可以在单个WebView内跳转,而Webview可以使用Activity或Fragment作为容器,SDK无法感知页面的跳转时机,所以对于H5页面的GTP、GTC打点,完全由H5控制,通过JsBridge调用页面事件的API。

Share to
1
2 Likes
Prev page
Next page

Recomm

Comments (0)

Contact