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

Coraool iOS SDK 开发指南

1.集成流程

1.1 SDK

将Framework.zip解压

把CoraoolLib.bundle 拷贝到应用的 目录下,并引入到项目中

把framework拷贝到应用的 目录下,添加到项目中并引入framework,并设置Do not Embed

VersionDateRelease NotesSDK
202407131.增加AB能力(详见第五章)
主要新增以下3个方法:
获取单实验分桶getABTest
获取单实验分桶对象getABTestObject
获取全部实验分桶getABTestListAll
2.提高系统稳定性,优化SDK性能
3.增加内部脏值检测
coraool-ios-sdk-1.0.9.zip
20240619修复sdk版本coraool-ios-sdk-1.0.8.zip
20240526修复缓存逻辑coraool-ios-sdk-1.0.7.zip
20240518提示输入App Security keycoraool-ios-sdk-1.0.6.zip

1.2 配置SDK

1.2.1 权限授予

权限权限用途

1.3 初始化步骤

1.3.1申请AK

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

1.3.2 SDK初始化

SDK为单一类,直接使用设置对应数据

/// 获取实例
+(CoraoolLib *)getInstance;


/// 【必须】设置app 的appId
///
/// 使用例子:
/// [[CoraoolLib getInstance] setAppId:@"c18"];
///
/// @param appId :设置app 的appId
-(void)setAppId:(NSString *)appId;

/// 【必须】设置appKey
///
/// 使用例子:
/// [[CoraoolLib getInstance] setAppKey:@"appKey"];
///
/// @param appKey 设置的appKey
-(void)setAppKey:(NSString *)appKey;


/// 【必须】设置app 安全appSec
///
/// 使用例子:
/// [[CoraoolLib getInstance] setAppSec:@"appSec"];
///
/// @param appSec UserTracker :设置appSec
-(void)setAppSec:(NSString *)appSec;

初始化示例:

CoraoolLib *coraoolLib =  [CoraoolLib getInstance];
[coraoolLib setAppId:@"your app id"];
[coraoolLib setAppKey:@"your appKey"];
[coraoolLib setAppSec:@"your appSec"];

let coraoolLib = CoraoolLib.getInstance()
coraoolLib?.setAppId("your app id")
coraoolLib?.setAppKey(""your appKey")
coraoolLib?.setAppSec("your appSec")

1.4 其他API

1.4.1 登录用户ID

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

/// 【必须】设置app 的userId
///
/// 使用例子:
/// [[CoraoolLib getInstance] setUserId:@"1234"];
///
/// @param userId :设置app 的登录用户的userId
-(void)setUserId:(NSString *)userId;

使用示例:

/// 设置app 的userId
///
/// 使用例子:
/// [[CoraoolLib getInstance] setUserId:@"1234"];
///
/// @param userId :设置app 的登录用户的userId
-(void)setUserId:(NSString *)userId;

1.4.2 日志开关

开发阶段会打开日志,release 包会自动关闭日志

1.4.3 严格模式

2.埋点接口

2.1 Tracking埋点

2.1.1 埋点提交

接口定义

@interface CoraoolUTBuilder : NSObject

/// UserTracker :发送日志

/// @param eventData 发送的数据,字典类型

-(void)track:(NSDictionary *)eventData;

参数说明:

参数解释说明
eventData埋点数据Map通过CoraoolUTBuilder子类构建的埋点数据,不建议手动构造,容易出错

2.1.2 控制埋点

CoraoolLib *coraoolLib =  [CoraoolLib getInstance];
CoraoolUTControlBuilder *builder = [[CoraoolUTControlBuilder alloc] initWithEventName:@"PAGE_MAIN"];
NSMutableDictionary *properties = [NSMutableDictionary new];
[properties setValue:@"业务参数value1" forKey:@"业务参数key1"];
[builder setProperties:properties];
[builder setProperty:@"updatePagePropKey1" value:@"updatePagePropVal1"];
[coraoolLib track:builder.build];
字段类型是否必须解释说明
eventNamestring事件名称标识用户在页面上操作的位置
propertiesMap<String, Object>事件参数和当前事件关联的业务参数,用于离线分析
property_keystring事件参数key和当前事件关联的业务参数,用于离线分析
property_valuestring事件参数value和当前事件关联的业务参数,用于离线分析

2.1.3 曝光埋点

CoraoolLib *coraoolLib =  [CoraoolLib getInstance];
CoraoolUTExposeBuilder *builder = [[CoraoolUTExposeBuilder alloc] initWithEventName:@"PAGE_MAIN"];
NSMutableDictionary *properties = [NSMutableDictionary new];
[properties setValue:@"业务参数value1" forKey:@"业务参数key1"];
[builder setProperties:properties];
[builder setProperty:@"updatePagePropKey1" value:@"updatePagePropVal1"];
[coraoolLib track:builder.build];
字段类型是否必须解释说明
eventNamestring事件名称标识用户在页面上操作的位置
propertiesMap<String, Object>事件参数和当前事件关联的业务参数,用于离线分析
property_keystring事件参数key和当前事件关联的业务参数,用于离线分析
property_valuestring事件参数value和当前事件关联的业务参数,用于离线分析

2.1.4 自定义埋点

CoraoolLib *coraoolLib =  [CoraoolLib getInstance];
CoraoolUTCustomBuilder *builder = [[CoraoolUTCustomBuilder alloc] initWithEventName:@"PAGE_MAIN"];
NSMutableDictionary *properties = [NSMutableDictionary new];
[properties setValue:@"业务参数value1" forKey:@"业务参数key1"];
[builder setProperties:properties];
[builder setProperty:@"updatePagePropKey1" value:@"updatePagePropVal1"];
[coraoolLib track:builder.build];
字段类型是否必须解释说明
eventNamestring事件名称标识用户在页面上操作的位置
eventPagestring事件关联页面自定义埋点也必须指定关联页面参数
propertiesMap<String, Object>事件参数和当前事件关联的业务参数,用于离线分析
property_keystring业务参数key和当前事件关联的业务参数,用于离线分析
property_valuestring业务参数value和当前事件关联的业务参数,用于离线分析

2.1.5 页面埋点

2.1.5.1 手动埋点

接口定义

1. 页面展现的时候调用

/// UserTracker :页面埋点

/// page 埋点,trackPageStart 和trackPageEnd 成对出现,建议在viewDidAppear

/// 设计思路:

/// 在start的时候,启动以页面对象为key的数据

/// 在end的时候,会上传日志信息

///

/// 使用例子:

/// [[CoraoolLib getInstance] trackPageStart:self pageName:@"FirstViewController"];

///

/// @param pageObject 当前页面实例

/// @param pageName 页面名称

-(void)trackPageStart:(id)pageObject pageName:(NSString *)pageName;

2. 页面退出的时候调用

/**

UserTracker :页面埋点

page 埋点,start 和end 成对出现,建议在viewDidDisappear

*/

/// UserTracker :页面结束埋点,会传参数

///

/// 使用例子:

/// [[CoraoolLib getInstance] trackPageEnd:self];

///

/// @param pageObject 当前页面实例

-(void)trackPageEnd:(id)pageObject;

参数说明:

方法名称参数解释说明
trackPageStartpageObject页面Activity对象
pageName自定义页面名称
trackPageEndpageObject页面Activity对象
pageName自定义页面名称
-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [[CoraoolLib getInstance] trackPageStart:self pageName:@"FirstViewController"];
}

-(void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
    [[CoraoolLib getInstance] trackPageEnd:self];

}

2.1.6 获取设备id

获取设备id

示例代码

NSString *deviceId = [CoraoolLib  deviceId];
字段类型是否必须解释说明
resultstring设备id获取设备id

2.2 GTX埋点协议

3. Invoke API接口

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

3.1 构造Response

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对象内

参数样例

#define SYSTEM_ERROR -2
#define REQUEST_ERROR -3
#define RESPONSE_ERROR -4
@interface CoraoolResponse : NSObject

@property bool success;
@property int code;
@property (strong,nonatomic)NSString  *message;
@property long connectTimeout;
@property (strong,nonatomic)NSDictionary *result;
@end

3.2 构造Request

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

参数说明:

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

示例代码:

    CoraoolRequest *request = [CoraoolRequest new];
    request.apiVersion = @"1.0.0";
    request.apiName = @"open.coraool.bingoplus.home.game.ranking";
    NSMutableDictionary *dict = [NSMutableDictionary new];
    [dict setValue:@"登录用户ID" forKey:@"userId"];
    [dict setValue:@"appsFlyer的ID" forKey:@"afId"];
    [dict setValue:@"设备I" forKey:@"deviceId"];
    [request setData:dict];

3.3 发起请求

SDK的请求API分为同步请求和异步请求,统一封装在 CoraoolLib 的接口类下

3.3.1 同步请求

接口定义:

/**
 同步请求
 */
-(id )syncInvoke:(Class)modelClass
         request:(CoraoolRequest *)request;
/**
 同步请求
 */
-(void )syncInvoke:(Class)modelClass
         request:(CoraoolRequest *)request
        callback:(void (^)(CoraoolResponse *response))callback;

参数说明:

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

返回值说明:

返回值类型解释说明
responseCoraoolResponse返回对象类对应第一步Reponse的对象实例

示例说明:

-(void)testSyncNetwork
{
    CoraoolRequest *request = [CoraoolRequest new];
    request.apiVersion = @"1.0.0";
    request.apiName = @"open.coraool.bingoplus.home.game.ranking";
    NSMutableDictionary *dict = [NSMutableDictionary new];
    [dict setValue:@"123" forKey:@"userId"];
    [dict setValue:@"afId" forKey:@"afId"];
    [dict setValue:@"1234" forKey:@"deviceId"];
    [request setData:dict];
    request.connectTimeout = 5;
    CoraoolLib *coraoolLib =  [CoraoolLib getInstance];
    CoraoolResponse *response = [coraoolLib syncInvoke:[CoraoolResponse class] request:request];
}

3.3.2 异步请求

接口定义:

/// 异步请求
/// @param modelClass 返回后的类型
/// @param request 请求参数
/// @param success 成功后的block
/// @param failed 失败后的block
/// @param systemError 系统错误的block
-(void )asyncInvoke:(Class)modelClass
            request:(CoraoolRequest *)request
            success:(void (^)(CoraoolResponse *response))success
             failed:(void (^)(CoraoolResponse *response))failed
        systemError:(void (^)(CoraoolResponse *response))systemError;

参数说明:

参数名类型解释说明
clzClass返回对象类的Class对应第一步Reponse对象类的Class
requestCoraoolRequest请求参数对应第二步请求参数对象
successresponse返回对象的类型请求被正确处理的时候返回,对应 success=true
onFailedcodeint请求错误码对应success=false的场景,如果签名错误、无效token等
messagestring错误描述
onSystemErrorcodeint请求错误码各类系统错误,如网络未连接、授权错误、数据解析异常等
messagestring错误描述

示例说明:

-(void)testAsyncNetwork
{
    CoraoolRequest *request = [CoraoolRequest new];
    request.apiVersion = @"1.0.0";
    request.apiName = @"open.coraool.bingoplus.home.game.ranking";
    NSMutableDictionary *dict = [NSMutableDictionary new];
    [dict setValue:@"123" forKey:@"userId"];
    [dict setValue:@"afId" forKey:@"afId"];
    [dict setValue:@"1234" forKey:@"deviceId"];
    [request setData:dict];
    CoraoolLib *coraoolLib =  [CoraoolLib getInstance];
    [coraoolLib asyncInvoke:[NSDictionary class] request:request success:^(CoraoolResponse *response) {
        NSLog(@"testAsyncNetwork success");
    } failed:^(CoraoolResponse *response) {
        NSLog(@"testAsyncNetwork failed");
    } systemError:^(CoraoolResponse *response) {
        NSLog(@"testAsyncNetwork systemError");
    }];
}

4. Web接入

4.1 容器层接入

4.1.1 初始化代理

例子:

//Coraool 初始化 1:增加 WKScriptMessageHandler
//例子:
@interface WebViewController ()<WKScriptMessageHandler>

@end

4.1.2 初始化代理

- (void)viewDidLoad {
    [super viewDidLoad];

    //Coraool 初始化 2:增加 执行脚本
    [[CoraoolLib getInstance] addJSBridge:self.wkWebView target:self];
    
}

4.1.3 实现代理

//Coraool 初始化 3:实现WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    [[CoraoolLib getInstance] evaluateJS:self.wkWebView target:self userContentController:userContentController didReceiveScriptMessage:message];
}

4.1.4 前端调用

例子:

CoraoolJsLib.js 示例

      
let callbackId = 0;
let callbackMap = {};

class CoraoolJsLib{
    static call(name, params, callback) {
        //生成callbackId
        let cbId = this.genCallbackId();
        //添加到callbackMap
        this.add(cbId, callback);

        //组装方法和参数
        let config = {name: name, params: params, callbackId: cbId};
        let string = JSON.stringify(config);
        window.webkit.messageHandlers.bridgeTest.postMessage(string); 
    }

    //生成callbackId
    static genCallbackId() {
        return `Webview_callback_${callbackId++}`
    }
    //添加callback
    static add(callbackId, callback) {
        callbackMap[callbackId] = {
            callback: callback
        }
    }

};

//注入全局方法,用于Native向h5回调
window.bridgeCallback = function(callbackId, res) {
    let cb = callbackMap[callbackId];
    let callback = cb["callback"];
    if (callback) {
        callback(res);
    }
    delete callbackMap.callbackId
}


js_bridge.html 示例

      
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Apache ECharts Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
    <style>
        .event-button {
            margin-right: 8px;
            background-color: green;
            color: white;
        }
        .page-button {
            margin-right: 8px;
            background-color: blue;
            color: white;
        }
        .verify-button {
            margin-right: 8px;
            background-color: red;
            color: white;
        }
        .dialog-button {
            margin-right: 8px;
            background-color: orange;
            color: white;
        }
    </style>
</head>
<body>
<script type="text/javascript" src="./CoraoolJsLib.js"></script>

<div id="chart" style="width: 350px; height: 200px;"></div>
<script>
var chart = echarts.init(document.getElementById('chart'));
var option = {
    xAxis: {
         data: ["水","金","地","火","木","土","天","海","冥"],
         axisLabel: {//调整width可能会导致标签显示不全
                interval: 0, // 设置标签全部显示
                margin: 10, // 调整标签与轴线之间的距离
                textStyle: {
                    fontSize: 12 // 设置标签字体大小
                }
        },
         axisTick: {show: false},//设置x轴底部标签为虚线
         axisLine: {
            show: false,
            lineStyle: {
                type: 'dashed' // 设置为虚线
            }
        }
    },

    yAxis: {
     axisTick: {show: false},
     axisLine: {
            show: false,
            lineStyle: {
                type: 'dashed' // 设置为虚线
            }
        },
        splitLine: { // 添加此项即可设置中间虚线
            show: true,
            lineStyle: {
                type: 'dashed'
            }
        }

    },
    series: [{
        name: '数据1',
        type: 'bar',
        data: [5, 15, 25, 45, 55, 15, 35, 20, 10],
        itemStyle: {
            color: function(params) {
                var value = params.value;
                //根据区间值来设置不同柱状图的颜色渐变
                if (value < 10) {
                    return new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                        offset: 0,
                        color: '#C8FF9E'
                    }, {
                        offset: 1,
                        color: '#05CC18'
                    }]);
                } else if (value < 20) {
                    return new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                        offset: 0,
                        color: '#10A2FB'
                    }, {
                        offset: 1,
                        color: '#1B5AF7'
                    }]);
                } else {
                    return new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                        offset: 0,
                        color: '#FF8E9B'
                    }, {
                        offset: 1,
                        color: '#FD021E'
                    }]);
                }
            }
        }
    }]
};
chart.setOption(option);
</script>

<script>
    function trackClickLower() {
        CoraoolJsLib.call("track", JSON.stringify({
            "eventType": "click",
            "eventName": "JS_CLICK_EVENT_NAME",
            "eventValue": {
                "key1-lower":"value1",
            }
        }), function(res) {
                console.log("recieve callback")
                console.log(res)
            });
    }
    function trackClick() {
        CoraoolJsLib.call("track", JSON.stringify({
            "eventType": "CLICK",
            "eventName": "JS_CLICK_EVENT_NAME",
            "eventValue": {
                "key1":"value1"
            }
        }), function(res) {
                console.log("recieve callback")
                console.log(res)
            });
    }
    function trackExpose() {
        CoraoolJsLib.call("track", JSON.stringify({
            "eventType": "EXPOSE",
            "eventName": "JS_EXPOSE_EVENT_NAME",
            "eventValue": {
                "key1":"value1",
                "key2":"value2"
            }
        }), function(res) {
                console.log("recieve callback")
                console.log(res)
            });
    }
    function trackCustom() {
        CoraoolJsLib.call("track", JSON.stringify({
            "eventType": "CUSTOM",
            "eventName": "JS_CUSTOM_EVENT_NAME",
            "eventValue": {
                "key1":"value1",
                "key2":"value2"
            }
        }), function(res) {
                console.log("recieve callback")
                console.log(res)
            });
    }
    function trackPageStart() {
        CoraoolJsLib.call("trackPageStart", JSON.stringify({
            "eventType": "PAGE",
            "eventName": "PAGE_NAME_IS_EVENT_NAME",
            "eventValue": {
                "key1":"value1",
                "key2":"value2"
            }
        }), function(res) {
                console.log("recieve callback")
                console.log(res)
            });
    }
    function trackPageEnd() {
        CoraoolJsLib.call("trackPageEnd", JSON.stringify({
            "eventType": "PAGE",
            "eventName": "PAGE_NAME_IS_EVENT_NAME",
            "eventValue": {
                "key3":"value3",
                "key4":"value4"
            }
        }), function(res) {
                console.log("recieve callback")
                console.log(res)
            });
    }
    function updatePageProperties() {
        CoraoolJsLib.call("updatePageProperties", JSON.stringify({"jsProp": "jsValue"}), function(res) {
                console.log("recieve callback")
                console.log(res)
            });
    }
    function getClientInfo() {
        const info = CoraoolJsLib.getClientInfo();
        alert(info)
    }
    function showAlert() {
        alert("ShowAlert");
    }
    function showConfirm() {
        alert("ShowConfirm");
    }
    function showPrompt() {
        alert("ShowPrompt");
    }
</script>

<p>Web javascript bridge</p>
<div>Other Event:</div>
<button onclick="trackClickLower()" class="event-button">trackClickLower</button>
<button onclick="trackClick()" class="event-button">trackClick</button>
<button onclick="trackExpose()" class="event-button">trackExpose</button>
<button onclick="trackCustom()" class="event-button">trackCustom</button>
<div>Page Event:</div>
<button onclick="trackPageStart()" class="page-button">trackPageStart</button>
<button onclick="trackPageEnd()" class="page-button">trackPageEnd</button>
<button onclick="updatePageProperties()" class="page-button">updatePageProperties</button>
<div>Verify Track:</div>
<button onclick="getClientInfo()" class="verify">getClientInfo</button>
<p>Web Dialog</p>
<button onclick="showAlert()" class="dialog-button">ShowAlert</button>
<button onclick="showConfirm()" class="dialog-button">ShowConfirm</button>
<button onclick="showPrompt()" class="dialog-button">ShowPrompt</button>

</body>
</html>

5. Abtest 接口

5.1 初始化Abtest功能

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

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

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

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

5.2 获取单实验分桶

接口定义

-(NSString *)getABTest:(NSString *)experimentName;

参数说明

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

示例代码

let bucket = CoraoolLib.getInstance().getABTest("FEEDS_OLD_USER_BASE");

5.3 获取单实验分桶对象

接口定义

-(CoraoolABTestModel *)getABTestObject:(NSString *)experimentName;

参数说明

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

示例代码

        let model = CoraoolLib.getInstance().getABTestObject("FEEDS_OLD_USER_BASE")

5.4 获取全部实验分桶

接口定义

-(NSArray<CoraoolABTestModel*> *)getABTestListAll;

参数说明

参数解释说明

示例代码

        let models = CoraoolLib.getInstance().getABTestListAll()
Share to
1
0 Likes
Prev page
Next page

Recomm

Comments (0)

Contact