文档

SDK插件使用说明

更新时间:

集成SDK插件到App后,您只需启动App,网络质量分析器就会自动进行网络探测。本文介绍SDK插件的使用说明。

集成操作步骤

重要

上线前测试阶段,请检查以下几项:

  1. 在控制台配置的网络探测规则是否成功触发,以控制台中看到对应的探测数据为准。

  2. 检查客户端主动发起的探测是否成功上报,以控制台中看到对应的探测数据为准,建议和控制台配置的探测规则的探测目标不同,以便区分。

  3. 针对上述步骤1、2分别检查不同平台,如Android、iOS和Windows等。

  4. 有条件的话,海外和中国内地不同终端都验证下是否能成功上报数据。

iOS SDK接入

  1. 在Podfile文件中添加以下配置。

    source 'https://gitee.com/aliyun-sls/Specs.git'
    pod 'AliyunLogProducer', '4.3.2' # 建议使用最新版本
    pod 'AliyunLogNetworkDiagnosis', '4.3.2' # 建议使用最新版本

    更多版本信息,请参见aliyun-log-ios-sdk

  2. 在AppDelegate类中引入如下头文件。

    #import <AliyunLogNetworkDiagnosis/AliyunLogNetworkDiagnosis.h>
  3. 在AppDelegate类的application: didFinishLaunchingWithOptions:方法中添加如下SDK初始化代码。

    重要

    上报日志到日志服务时需使用阿里云账号或RAM用户的AccessKey,用于鉴权及防篡改。为避免将AccessKey保存在移动端应用中,造成安全风险,推荐您使用移动端日志直传服务配置AccessKey。具体操作,请参见采集-搭建移动端日志直传服务

    SLSCredentials *credentials = [SLSCredentials credentials];
    // endpoint和project不支持动态更新,请在初始化SDK时指定
    credentials.endpoint = @"<your endpoint>";
    credentials.project = @"<your project>";
    
    // AccessKey建议通过STS方式获取,参考下面的文档:
    // https://help.aliyun.com/zh/sls/user-guide/build-a-service-to-upload-logs-from-mobile-apps-to-log-service
    // AccessKey在初始化时可以先不填,后续通过[[SLSCocoa sharedInstance] setCredentials:credentials];方法可以更新,参考后面的updateSDK方法实现
    credentials.accessKeyId = @"<your accessKeyId>"";
    credentials.accessKeySecret = @"<your accessKeySecret>";
    credentials.securityToken = @"<your accessKey securityToken>"; // 仅当AccessKey是通过STS服务获取时需要
    
    SLSNetworkDiagnosisCredentials *networkCredentials = [credentials createNetworkDiagnosisCredentials];
    //secretKey不支持动态更新,请在初始化时指定
    networkCredentials.secretKey = self.secretKey;
    
    // (可选)设置业务扩展字段。仅对新产生的探测数据生效。
    // 不支持动态更新,请在SDK初始化时设置。
    [networkCredentials putExtension:@"custom_value" forKey:@"custom_key"];
    
    // 用户接受隐私协议之前,先调用preInit完成SDK初始化。
    [[SLSCocoa sharedInstance] preInit:credentials configuration:^(SLSConfiguration * _Nonnull configuration) {
    	configuration.enableNetworkDiagnosis = YES;
    }];
    
    // 用户接受隐私协议之后,再调用initialize完成SDK的完整初始化。
    [[SLSCocoa sharedInstance] initialize:credentials configuration:^(SLSConfiguration * _Nonnull configuration) {
    	configuration.enableNetworkDiagnosis = YES;
    }];
    
    // (可选)设置设备ID,可在任何时机调用,仅对新产生的探测数据生效。
    [SLSUtdid setUtdid:@"<your device id"];
    
    // (可选)配置用户信息,可在任何时机调用。仅对新产生的探测数据生效。
    SLSUserInfo *userInfo = [SLSUserInfo userInfo];
    userInfo.uid = @"<your user id>";
    userInfo.channel = @"<your user channel";
    [userInfo addExt:@"ext_value" key:@"ext_key"];
    [[SLSCocoa sharedInstance] setUserInfo:userInfo];

    更多SDK使用示例请参考:Demo示例

    重要参数说明如下表所示。

    字段

    是否必填

    说明

    secretKey

    接入端应用的密钥。更多信息,请参见创建接入端应用

    putExtension

    设置自定义信息,支持设置多个键值对。设置后,探测数据中将附加这些信息。

    endpoint

    日志服务Project所属的Endpoint,必须以https://开头。如何获取,请参见公网

    project

    您在创建接入端应用时指定的Project。更多信息,请参见创建接入端应用

Android SDK接入

  1. 在根build.gradle文件中添加以下配置。

    repositories {
      google()
      jcenter()
      mavenCentral()
      maven { url 'https://maven.aliyun.com/repository/public/' }
    }
  2. 添加如下依赖。

    implementation 'io.github.aliyun-sls:aliyun-log-android-sdk:2.7.1@aar' // 建议使用最新版本
    implementation 'io.github.aliyun-sls:sls-android-core:1.0.10@aar' // 建议使用最新版本
    implementation 'io.github.aliyun-sls:sls-android-ot:1.0.8.1@aar' // 建议使用最新版本
    implementation 'io.github.aliyun-sls:sls-android-network-diagnosis:2.2.2@aar' // 建议使用最新版本
    implementation 'com.squareup.okhttp3:okhttp:3.11.0' // (可选)最低兼容3.10.0版本,HTTP探测时必须

    更多版本信息,请参见aliyun-log-android-sdk

  3. 添加如下初始化代码。

    Credentials credentials = new Credentials();
    // (必填)endpoint和project不支持动态更新,请在初始化SDK时指定
    credentials.endpoint = "<your endpoint>";
    credentials.project = "<your project>";
    
    // AccessKey建议通过STS方式获取,参考下面的文档:
    // https://help.aliyun.com/zh/sls/user-guide/build-a-service-to-upload-logs-from-mobile-apps-to-log-service
    // AccessKey在初始化时可以先不填,后续通过SLSAndroid.setCredentials(credentials);方法可以更新,参考后面的updateSDK方法实现
    credentials.accessKeyId = "<your accessKeyId>";
    credentials.accessKeySecret = "<your accessKeySecret>";
    //credentials.securityToken = "<your accessKey securityToekn>"; // 仅当AccessKey是通过STS服务获取时需要
    
    NetworkDiagnosisCredentials networkDiagnosisCredentials = credentials.getNetworkDiagnosisCredentials();
    // (必填)secretKey不支持动态更新,请在初始化时设置。
    networkDiagnosisCredentials.secretKey = secretKey;
    // (可选)设置业务扩展字段。仅对新产生的探测数据生效。
    // 不支持动态更新,请在SDK初始化时设置。
    networkDiagnosisCredentials.extension.put("custom_key", "custom_value");
    
    SLSAndroid.initialize(
      getApplicationContext(),
      credentials,
      configuration -> configuration.enableNetworkDiagnosis = true
    );
    
    // (建议)注册探测数据上报回调
    SLSAndroid.registerCredentialsCallback((feature, result) -> {
      if (LogProducerResult.LOG_PRODUCER_SEND_UNAUTHORIZED == result ||
          LogProducerResult.LOG_PRODUCER_PARAMETERS_INVALID == result) {
        // 处理AccessKey过期、失效等鉴权问题
        Credentials credentials = new Credentials();
        credentials.accessKeyId = "<your accessKeyId>";
    		credentials.accessKeySecret = "<your accessKeySecret>";
    		credentials.securityToken = "<your accessKey securityToekn>"; 
    
        SLSAndroid.setCredentials(credentials);
      }
    });
    
    // (可选)设置设备ID,可在任何时机调用,仅对新产生的探测数据生效。
    SLSAndroid.setUtdid(getApplicationContext(), "<your device id");
    
    // (可选)配置用户信息,可在任何时机调用。仅对新产生的探测数据生效。
    UserInfo userInfo = new UserInfo();
    userInfo.uid = "<your user id>";
    userInfo.channel = "<your user channel>";
    userInfo.addExt("ext_key", "ext_value");
    SLSAndroid.setUserInfo(userInfo);

    更多SDK使用示例请参考:Demo示例

    字段

    是否必填

    说明

    secretKey

    接入端应用的密钥。更多信息,请参见创建接入端应用

    extension.put

    设置自定义信息,支持设置多个键值对。设置后,探测数据中将附加这些信息。

    endpoint

    日志服务Project所属的Endpoint,必须以https://开头。如何获取,请参见公网

    project

    您在创建接入端应用时指定的Project。更多信息,请参见创建接入端应用

    accessKeyId

    具备访问日志服务Logstore权限的AccessKey ID。如何获取,请参见访问密钥

    accessKeySecret

    具备访问日志服务Logstore权限的AccessKey Secret。如何获取,请参见访问密钥

    securityToken

    访问密钥的Token。使用STS方式接入时,需要配置。如何获取,请参见AssumeRole - 获取扮演角色的临时身份凭证

Unity插件接入

  1. 下载并导入Unity插件到您的Unity工程。

    下载最新版本的Unity插件,双击.unitypackage文件,导入插件相关的文件到您的Unity工程中。

    插件包目录说明:

    • Assets/Plugins/Unity4SLS: Plugin脚本。

    • Assets/Plugins/Unity4SLS/Android/libs:Android平台依赖的SDK和NDK。

    • Assets/Plugins/Unity4SLS/iOS/:iOS平台依赖的Framework和静态库。

    • Assets/Plugins/Unity4SLS/Windows/:Windows平台依赖的库。

    • Assets/Scenes/:示例Scenes,实际集成时可以删除。

    • Assets/Scripts/:示例Scripts,实际集成时可以删除。

  2. 初始化插件。

    重要

    上报日志到日志服务时需使用阿里云账号或RAM用户的AccessKey,用于鉴权及防篡改。为避免将AccessKey保存在移动端应用中,造成安全风险,推荐您使用移动端日志直传服务配置AccessKey。具体操作,请参见采集-搭建移动端日志直传服务

    using AliyunSLS;
    
    Credentials credentials = new Credentials();
    // (必填)endpoint和project不支持动态更新,请在初始化SDK时指定
    credentials.endpoint = "<your endpoint>";
    credentials.project = "<your project>";
    credentials.secretKey = "<your secretKey>";
    
    // (可选)AccessKey建议通过STS方式获取,参考下面的文档:
    // https://help.aliyun.com/zh/sls/user-guide/build-a-service-to-upload-logs-from-mobile-apps-to-log-service
    // AccessKey在初始化时可以先不填,后续通过SLSAndroid.setCredentials(credentials);方法可以更新,参考后面的updateSDK方法实现
    credentials.accessKeyId = accessKeyId;
    credentials.accessKeySecret = accessKeySecret;
    //credentials.securityToken = "<your accessKey securityToekn>"; // 仅当AccessKey是通过STS服务获取时需要
    
    // (可选)设置业务扩展字段。仅对新产生的探测数据生效。
    credentials.extension = new Dictionary<string, string>();
    extensions.Add("key_from_unity", "value_from_unity");
    
    // (可选)设置设备ID
    credentials.deviceId = "<your device id>";
    
    // 初始化SDK。
    Unity4SLS.Initialize(credentials);
    
    //(可选)配置用户信息,可在任何时机调用,仅对新产生的探测数据生效。
    UserInfo info = new UserInfo();
    info.uid = "12312123123123";
    info.channel = "dev_debug";
    info.ext.Add("u_key1", "u_value1");
    Unity4SLS.SetUserInfo(info);

    字段

    是否必填

    说明

    secretKey

    接入端应用的密钥。更多信息,请参见创建接入端应用

    extensions.Add

    设置自定义信息,支持设置多个键值对。设置后,探测数据中将附加这些信息。

    endpoint

    日志服务Project所属的Endpoint,必须以https://开头。如何获取,请参见公网

    project

    您在创建接入端应用时指定的Project。更多信息,请参见创建接入端应用

Windows SDK接入

集成方式

SDK以MD动态库的形式提供,您可按照集成动态库的形式进⾏Windows SDK接入。

  1. /lib目录下的库文件和/include目录下的头文件添加到项目中。

  2. 配置附加库目录路径。

  3. 将alinetworkdiagnosis.dll库同步到⽣成⽬录。

  4. 使⽤时,使用#include "api.h"指令。

重要

MD模式下,发布应用前请检查项目中是否缺少VCRuntime系列dll和Visual C++ Redistributable for Visual Studio相关动态库文件,网络质量分析器 Windows SDK所需的动态库文件参考以下目录

msvcp140.dll
msvcp140_codecvt_ids.dll
ucrtbase.dll
vcruntime140.dll
vcruntime140_1.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-core-localization-l1-2-0.dll
api-ms-win-core-processthreads-l1-1-1.dll
api-ms-win-core-file-l1-2-0.dll
api-ms-win-core-timezone-l1-1-0.dll
api-ms-win-core-file-l2-1-0.dll
api-ms-win-core-synch-l1-2-0.dll
api-ms-win-crt-heap-l1-1-0.dll
api-ms-win-core-string-l1-1-0.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-convert-l1-1-0.dll
api-ms-win-crt-time-l1-1-0.dll
api-ms-win-crt-utility-l1-1-0.dll
api-ms-win-crt-filesystem-l1-1-0.dll
api-ms-win-crt-environment-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll

下载地址

单击Windows SDK,下载Windows SDK包。

重要
  • WindowsSDK支持x64/x86模式下多种集成方式,请根据项目需求选择对应的文件夹:

    • DLL-MD:动态库,运行时库MD;

    • DLL-MT:动态库,运行时库MT;

    • LIB-MD:静态库,运行时库MD;

    • LIB-MT:静态库,运行时库MT;

SDK初始化

重要

上报日志到日志服务时需使用阿里云账号或RAM用户的AccessKey,用于鉴权及防篡改。为避免将AccessKey保存在代码中,造成安全风险,推荐您使用移动端日志直传服务配置AccessKey。具体操作,请参见采集-搭建移动端日志直传服务

void logcallback(const char* s) {
    printf("[demo-logcallback]  %s", (char*)s);
}
void on_token_ex() {
    printf("[demo-token-expired-callback] ----------------------token expired callback excited----------------\n");
}
void on_token_ex_ctx(void* ctx) {
  	printf("[demo-token-expired-callback] ----------------------context : %s ----------------------\n",(char*)ctx);
    printf("[demo-token-expired-callback] ----------------------token expired callback excited----------------\n");
}
void demoInit(){
    //开始初始化。
    printf("start init sdk\n");                   
    AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig();

    //必填,接入端应用的密钥。
    config.setSecKey("{your_secret_key}"); 

    //可选,设置设备ID。     
    config.setDeviceId("{your_device_id}");

    //可选,设置用户自定义拓展信息,用于业务自定义标识。
    std::map<std::string, std::string> mp;
    mp.insert(make_pair("key", "value"));
    config.setExtension(mp);                    

    //设置最大并发线程数。
    config.setThreadPool(20);    

    //设置日志回调。               
    config.setLogback(logcallback);//默认输出log_debug及以上等级的日志
  	config.setLogCallback(logcallback, Log_Level::log_error);//设置日志输出最低等级

    //设置token失效回调,支持携带自定义参数
    config.setTokenExpiredCallback(on_token_ex);
  	//或
    const char* s = "it's user's context";
    config.setTokenExpiredCallback(on_token_ex_ctx, (void*)s);
  
    //初始化SDK。
    config.init();

    //或者预初始化SDK。
    config.preInit();
    
    //初始化完成。
    printf("end init sdk\n");            
}

// 请求AccessKey信息。
void requestAccessKey() {
    // 推荐您先使用移动端日志直传服务配置AccessKey信息。
    // ...

    // 获取AccessKey信息后,完成更新。
    updateAccessKey(accessKeyId, accessKeySecret, securityToken);
}

// 更新AccessKey信息。
void updateAccessKey(std::string accessKeyId, std::string accessKeySecret, std::string securityToken) {
    // 通过STS服务获取的AccessKey包含securitToken,需要使用以下方式更新。
    config.setSlsCredential(accessKeyId, accessKeySecret, securityToken);
}

重要参数说明如下表所示。

字段

是否必填

说明

SecKey

接入端应用的密钥。更多信息,请参见创建接入端应用

扩展功能

AccessKey自定义策略最佳实践

提供给SDK用于上报日志的凭证:AccessKey或者STS Token,需要分配SLS LogStore的访问策略。按照最小权限原则,我们需要指定凭证的访问策略范围为对应logstore的只写权限。请参考如下代码:

说明

代码块中your-projectyour-logstore分别替换为应用详情中的project和原始探测数据Logstore,关于应用详情,请参见查看应用详情

{
    "Effect":"Allow",
    "Action":[
        "log:PostLogStoreLogs"
    ],
    "Resource":[
        "acs:log:*:*:project/your-project/logstore/your-logstore"
    ]
}

处理AccessKey失效

在初始化SDK配置AccessKey时,如果AccessKey是通过STS方式获取到的,则AccessKey可能会面临失效的问题。在AccessKey失效时,SDK支持通过配置回调的方式来接收AccessKey失效信息。

iOS SDK

[[SLSCocoa sharedInstance] registerCredentialsCallback:^(NSString * _Nonnull feature, NSString * result) {
	if ([@"LogProducerSendUnauthorized" isEqualToString:result] || 
      	[@"LogProducerParametersInvalid" isEqualToString:result]) {
        
        //处理token过期,AccessKey失效等鉴权类型问题。
	      //获取到新的token后,调用如下代码更新token。
	      SLSCredentials *credentials = [SLSCredentials credentials];
	      credentials.accessKeyId = accessKeyId;
	      credentials.accessKeySecret = accessKeySecret;
	      credentials.securityToken = securityToken; //可选,STS方式获取的token必须要填。
        
        //更新凭证信息。
	      [[SLSCocoa sharedInstance] setCredentials:credentials];
	}
}];

Android SDK

SLSAndroid.registerCredentialsCallback((feature, result) -> {
  if (LogProducerResult.LOG_PRODUCER_SEND_UNAUTHORIZED == result ||
  LogProducerResult.LOG_PRODUCER_PARAMETERS_INVALID == result) {
  	
    // 处理token过期,AccessKey失效等鉴权类问题。
    Credentials credentials = new Credentials();
    credentials.accessKeyId = accessKeyId;
    credentials.accessKeySecret = accessKeySecret;
    credentials.securityToken = securityToken;

    SLSAndroid.setCredentials(credentials1);
  }
});

Unity

/// <summary>
/// 设置回调。
/// </summary>
public void setCredentialsCallback()
{
    callback_delegate callback = new callback_delegate(credentialsCallback);
    Unity4SLS.RegisterCredentialsCallback(callback);
}

// 处理AccessKey过期或无效。
public void credentialsCallback(string feature, string result)
{
    if ("LogProducerSendUnauthorized" == result || 
        "LogProducerParametersInvalid" == result ||
        "LOG_PRODUCER_SEND_UNAUTHORIZED" == result ||
        "LOG_PRODUCER_PARAMETERS_INVALID" == result) 
    {
        Credentials credentials = new Credentials();
        credentials.accessKeyId = accessKeyId;
        credentials.accessKeySecret = accessKeySecret;

        Unity4SLS.SetCredentials(credentials);
    }

}

Windows SDK

void on_token_ex() {
    //获取配置类。
    AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig();
    //设置AccessKeyId、AccessKeySecret、Token。
    config.setSlsCredential(accessKeyId, accessKeySecret, securityToken);
    printf("[token-expired-callback] token expired callback excited\n");
}

主动探测

SDK 支持 PING、TCPPING、HTTP、MTR、DNS等多种探测方式的主动发起。您可以调用以下API发起主动探测。

PING

iOS SDK

SLSPingRequest *request = [[SLSPingRequest alloc] init];
request.domain = @"www.example.com";
//可选参数。
request.context = @"<your ping context id>";
request.parallel = YES;
//可选参数。
request.extention = @{
    @"custom_key": @"custom_value_ios"
};
[[SLSNetworkDiagnosis sharedInstance] ping2:request callback:^(SLSResponse * _Nonnull response) {
    NSLog(@"ping result: %@", response.content);
}];

Android SDK

PingRequest request = new PingRequest();
request.domain = "www.example.com";
//可选参数。
request.multiplePortsDetect = true; //启用多网卡探测。
request.context = "<your ping context id>";
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
    {
        put("custom_key", "custom_value");
    }
};

NetworkDiagnosis.getInstance().ping(request, response -> {
    SLSLog.d(TAG, String.format("ping result: %s", response.content));
});

Unity

PingRequest request = new PingRequest();
request.domain = "www.example.com";
//可选参数。
request.context = "your ping request context id";

Unity4SLS.Ping(request);

Windows SDK

//必选,初始化探测参数(任务ID(可为空字符串)、探测目标、DNS解析(0~3分别代表v4优先、v6优先、v4 only、v6 only)、探测端口)。
PingConfig* pingConfig = new PingConfig("0", "www.example.com", 0, 80);
//可选,修改探测目标。
pingConfig->setTarget("www.example.com");
//可选,修改探测任务ID。
pingConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
pingConfig->setInterval(100);
//可选,修改探测超时时间。
pingConfig->setTimeout(2000);
//可选,设置探测结束时的回调
pingConfig->setCallback(demo_ping_callback);
//发起探测。
pingConfig->Detect();
//另:demo_ping_callback 范例:
void demo_ping_callback(void* context, char* json_result) {
    std::string* ctx = static_cast<std::string*>(context);
    printf("[探测结果回调 demo-ping-callback] %s, context : %s\n", json_result, ctx->c_str());
}

TCPPING

iOS SDK

SLSTcpPingRequest *request = [[SLSTcpPingRequest alloc] init];
request.domain = @"www.example.com";
request.port = 80;
//可选参数。
request.context = @"<your tcpping context id>";
//可选参数。
request.extention = @{
    @"custom_key": @"custom_value_ios"
};
[[SLSNetworkDiagnosis sharedInstance] tcpPing2:request callback:^(SLSResponse * _Nonnull response) {
    NSLog(@"ping result: %@", response.content);
}];

Android SDK

TcpPingRequest request = new TcpPingRequest();
request.domain = "www.example.com";
request.port = 80;
//可选参数。
request.context = "<your tcp ping context id>";
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
    {
        put("custom_key", "custom_value");
    }
};

NetworkDiagnosis.getInstance().tcpPing(request, response -> {
    SLSLog.d(TAG, String.format("tcp ping result: %s", response.content));
});

Unity

TcpPingRequest request = new TcpPingRequest();
request.domain = "www.example.com";
request.port = 80;
//可选参数。
request.context = "your tcpping request context id";

Unity4SLS.TcpPing(request);

Windows SDK

//必选,初始化探测参数(任务ID(可为空字符串)、探测目标、DNS解析(0~3分别代表v4优先、v6优先、v4 only、v6 only)、探测端口)
TcppingConfig* tcppingConfig = new TcppingConfig("", "www.example.com", 1, 80);
//可选,修改探测目标。
tcppingConfig->setTarget("www.example.com");
//可选,修改探测任务ID。
tcppingConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
tcppingConfig->setInterval(100);
//可选,修改探测超时时间。
tcppingConfig->setTimeout(2000);
//可选,设置探测结束时的回调
tcppingConfig->setCallback(demo_tcpping_callback);
//发起探测。
tcppingConfig->Detect();

//另:demo_tcpping_callback 范例:
void demo_tcpping_callback(void* context, char* json_result) {
    std::string* ctx = static_cast<std::string*>(context);
    printf("[探测结果回调 demo-tcpping-callback] %s, context : %s\n", json_result, ctx->c_str());
}

HTTP

iOS SDK

SLSHttpRequest *request = [[SLSHttpRequest alloc] init];
request.domain = @"https://demo.ne.aliyuncs.com";
//可选参数。
request.context = @"<your http context id>";
request.headerOnly = YES;
request.downloadBytesLimit = 128 * 1024; // 128KB
//可选参数,证书检验回调。getHttpCredential的配置参考下文。
request.credential = ^NSURLCredential * _Nullable(NSString * _Nonnull url) {
    return [self getHttpCredential:url];
};
//可选参数。
request.extention = @{
    @"custom_key": @"custom_value_ios"
};

[[SLSNetworkDiagnosis sharedInstance] http2:request callback:^(SLSResponse * _Nonnull response) {
    NSLog(@"ping result: %@", response.content);
}];

Android SDK

HttpRequest request = new HttpRequest();
//可选参数。
request.context = "<your http context id>";
request.headerOnly = true;
request.downloadBytesLimit = 1024;
//可选参数,证书检验回调。getSSLContext的配置参考下文。
request.credential = new HttpCredential(getSSLContext(context), null);
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
    {
        put("custom_key", "custom_value");
    }
};

request.domain = "https://www.example.com";
NetworkDiagnosis.getInstance().http(request, response -> {
    SLSLog.d(TAG, String.format("http result: %s", response.content));
});

Unity

HttpRequest request = new HttpRequest();
request.domain = "https://www.example.com";
//可选参数。
request.context = "<your http context id>";
request.headerOnly = true;
request.downloadBytesLimit = 1024;

Unity4SLS.Http(request);

Windows SDK

//必选,初始化探测参数(任务ID,探测目标,DNS解析(0~3分别代表v4优先、v6优先、v4 only、v6 only))
HttpDetectionConfig* httpConfig = new HttpDetectionConfig("", "http://www.example.com", 1);
//可选,修改探测目标。
httpConfig->setTarget("http://www.example.com");
//可选,修改探测任务ID。
httpConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
httpConfig->setInterval(100);
//可选,修改探测超时时间。
httpConfig->setTimeout(2000);
//可选,设置探测结束时的回调
httpConfig->setCallback(demo_http_callback);
//发起探测。
httpConfig->Detect();

//demo_http_callback 范例:
void demo_http_callback(void* context, char* json_result) {
    std::string* ctx = static_cast<std::string*>(context);
    printf("[探测结果回调 demo-http-callback] %s, context : %s\n", json_result, ctx->c_str());
}

MTR

iOS SDK

SLSMtrRequest *request = [[SLSMtrRequest alloc] init];
request.domain = @"www.example.com";
//可选参数。
request.context = @"<your mtr context id>";
request.parallel = YES;
request.protocol = SLS_MTR_PROROCOL_ALL;
//可选参数。
request.extention = @{
    @"custom_key": @"custom_value_ios"
};

[[SLSNetworkDiagnosis sharedInstance] mtr2:request callback:^(SLSResponse * _Nonnull response) {
    NSLog(@"ping result: %@", response.content);
}];

Android SDK

MtrRequest request = new MtrRequest();
request.domain = "www.example.com";
//可选参数。
request.protocol = Protocol.ICMP;
request.context = "<your mtr context id>";
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
    {
        put("custom_key", "custom_value");
    }
};

NetworkDiagnosis.getInstance().mtr(request, response -> {
    SLSLog.d(TAG, String.format("mtr result: %s", response.content));
});

Unity

MtrRequest request = new MtrRequest();
request.domain = "www.example.com";
//可选参数。
request.context = "your mtr request context id";

Unity4SLS.Mtr(request);

Windows SDK

//必选,初始化探测参数。
MtrDetectionConfig* mtrConfig = new MtrDetectionConfig("", "www.example.com", "ICMP", 1);
//可选,修改探测目标。
mtrConfig->setTarget("www.example.com");
//可选,修改探测任务ID。
mtrConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
mtrConfig->setInterval(100);
//可选,修改探测超时时间。
mtrConfig->setTimeout(2000);
//可选,设置探测结束时的回调
mtrConfig->setCallback(demo_mtr_callback);
//发起探测。
mtrConfig->Detect();

//demo_mtr_callback 范例:
void demo_mtr_callback(void* context, char* json_result) {
    std::string* ctx = static_cast<std::string*>(context);
    printf("[探测结果回调 demo-mtr-callback] %s, context : %s\n", json_result, ctx->c_str());
}

DNS

iOS SDK

SLSDnsRequest *request = [[SLSDnsRequest alloc] init];
request.domain = @"www.example.com";
//可选参数。
request.context = @"<your dns context id>";
//可选参数。
request.extention = @{
    @"custom_key": @"custom_value_ios"
};

[[SLSNetworkDiagnosis sharedInstance] dns2:request callback:^(SLSResponse * _Nonnull response) {
    NSLog(@"ping result: %@", response.content);
}];

Android SDK

DnsRequest request = new DnsRequest();
request.domain = "www.example.com";
//可选参数。
request.context = "<your dns context id>";
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
    {
        put("custom_key", "custom_value");
    }
};
NetworkDiagnosis.getInstance().dns(request, response -> {
    SLSLog.d(TAG, String.format("dns result: %s", response.content));
});

Unity

DnsRequest request = new DnsRequest();
request.domain = "www.example.com";
// 可选参数。
request.context = "your dns request context id";

Unity4SLS.Dns(request);

Windows SDK

//必选,初始化探测参数。
DnsDetectionConfig* dnsConfig = new DnsDetectionConfig("", "www.example.com", 2000, 0, "223.5.5.5", "A");
//可选,修改探测目标。
dnsConfig->setTarget("www.example.com");
//可选,修改探测任务ID。
dnsConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
dnsConfig->setInterval(100);
//可选,修改探测超时时间。
dnsConfig->setTimeout(2000);
//可选,修改DNS服务器。
dnsConfig->setServers("30.30.XX.XX");
//可选,修改DNS解析选项。
dnsConfig->setType(1);
//可选,设置探测结束时的回调
dnsConfig->setCallback(demo_dns_callback);
//发起探测。
dnsConfig->Detect();

//demo_mtr_callback 范例:
void demo_dns_callback(void* context, char* json_result) {
    std::string* ctx = static_cast<std::string*>(context);
    printf("[探测结果回调 demo-dns-callback] %s, context : %s\n", json_result, ctx->c_str());
}

UDP

Windows SDK

//必选,初始化探测参数,"7564"为UDP报文负载,为十六进制字符串(Hex String)格式,
UdpConfig* udpConfig = new UdpConfig("0", "www.example.com", 0, 4000, "7564");
//可选,修改探测目的
udpConfig->setTarget("www.example.com");
//可选,修改探测任务id
udpConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔(ms)
udpConfig->setInterval(100);
//可选,修改探测超时时间
udpConfig->setTimeout(2000);
//可选,设置探测结束时的回调
udpConfig->setCallback(demo_udp_callback);
//发起探测。
udpConfig->Detect();

//demo_udp_callback 范例:
void demo_udp_callback(void* context, char* json_result) {
    std::string* ctx = static_cast<std::string*>(context);
    printf("[探测结果回调 demo-udp-callback] %s, context : %s\n", json_result, ctx->c_str());
}

更新扩展业务字段

SDK支持在任何时机更新扩展业务字段。更新后的扩展业务字段仅对新产生的探测数据生效。

例如,应用初始化的时候可能未获取到用户ID,可以在用户登录成功后通过此接口更新,传入的key需设置为userId

iOS SDK

[[SLSNetworkDiagnosis sharedInstance] updateExtensions:@{
    @"key1": @"value1",
    @"key2": @"value2"
}];

Android SDK

NetworkDiagnosis.getInstance().updateExtensions(new HashMap<String, String>(){
    {
        put("key1", "value1");
        put("key2", "value2");
    }
});

Unity

Dictionary<string, string> extensions = new Dictionary<string, string>();
extensions.Add("key_from_unity", "value_from_unity");

Unity4SLS.UpdateExtensions(extensions);

Windows SDK

//获取配置类。
AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig();

//自定义Extension信息。
std::map<std::string, std::string> mp;
mp.insert(make_pair("key1", "value1"));
mp.insert(make_pair("key2", "value2"));
mp.insert(make_pair("key3", "value3"));

//更新扩展信息。
config.updateExtension(mp); 

配置策略下发域名

一般情况下无需调用此接口,仅当不希望直连阿里云IP地址时,通过这个接口可以套一层域名。

重要

如果要使用该功能,需在SDK初始化之前完成设置。

iOS SDK

[[SLSNetworkDiagnosis sharedInstance] setPolicyDomain:@"your custom domain"];

Android SDK

NetworkDiagnosis.getInstance().setPolicyDomain("your custom domain");

Unity

Unity4SLS.SetPolicyDomain("your custom domain");

Windows SDK

config.setPolicyDomain("yourpolicydomain"); 

配置证书校验全局回调

当时HTTP探测,且为控制台下发的策略出发的探测时,支持通过全局回调函数来获取凭证。

iOS SDK

//注册HTTP探测证书校验回调。
[[SLSNetworkDiagnosis sharedInstance] registerHttpCredentialDelegate:^NSURLCredential * _Nullable(NSString * _Nonnull url) {
    return [self getHttpCredential:url];
}];

//处理证书校验。
-(NSURLCredential*) getHttpCredential:(NSString*)url {
    if (![url containsString:@"demo.ne.aliyuncs.com"]) {
        return nil;
    }
    
    NSString *p12WithBase64 = @"your p12 infomation";
    NSData *p12Data = [[NSData alloc] initWithBase64EncodedString:p12WithBase64 options:0];
    CFDataRef inPKCS12Data = (__bridge CFDataRef)p12Data;
        
    SecIdentityRef identity = NULL;
    NSString *pass = @"123";
    OSStatus status = [self extractIdentity:inPKCS12Data identity:&identity pass:pass];
    if(status != 0 || identity == NULL) {
        return nil;
    }
        
        SecCertificateRef certificate = NULL;
        SecIdentityCopyCertificate (identity, &certificate);
        const void *certs[] = {certificate};
        CFArrayRef arrayOfCerts = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
        
        //NSURLCredentialPersistenceForSession:创建URL证书,在会话期间有效。
        NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)arrayOfCerts persistence:NSURLCredentialPersistenceForSession];
        
        if(certificate) {
            CFRelease(certificate);
        }
        
        if (arrayOfCerts) {
            CFRelease(arrayOfCerts);
        }
    if (credential) {
        return [credential copy];
    }
    
    return nil;
}

Android SDK

//注册HTTP探测证书校验回调。
final HttpCredential credential = new HttpCredential(getSSLContext(context), null);
NetworkDiagnosis.getInstance().registerHttpCredentialCallback((url, context) -> credential);


//处理证书校验。
@RequiresApi(api = VERSION_CODES.O)
private SSLContext getSSLContext(Context context) {
    try {
        //服务器端需要验证的客户端证书。
        String KEY_STORE_TYPE_P12 = "PKCS12";
        KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);

        String p12Str = "your p12 infomation";
        byte[] p12Data = Base64.getDecoder().decode(p12Str);

        InputStream ksIn = new ByteArrayInputStream(p12Data);
        try {
            keyStore.load(ksIn, "your password".toCharArray());
        } catch (Exception e) {
            Log.e("Exception", e.getMessage(), e);
        } finally {
            try {
                ksIn.close();
            } catch (Exception ignore) {
            }
        }
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
            TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init((KeyStore)null);

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
        keyManagerFactory.init(keyStore, "your password".toCharArray());
        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
        return sslContext;
    } catch (Exception e) {
        Log.e("tag", e.getMessage(), e);
    }
    return null;
}

隐私合规

通过SDK发起网络探测请求后,SDK会采集网络信息、App信息、设备信息等。这些信息中主要包含:

  • 用户设备出口IP、设备私网IP

  • App版本号信息

  • 系统类型及版本号信息

  • 设备型号

为了保障您的App顺利通过监管机构的合规检测,SDK提供了合规使用方案。

第一步:确保您的App有《隐私政策》,并且在用户首次启动App时弹出《隐私政策》取得用户同意。

第二步:务必告知用户您选择使用日志服务(SLS)SDK,请在《隐私政策》增加如下参考条款:

  • 使用SDK名称:日志服务(SLS)SDK。

  • 服务类型:网络质量数据分析。

  • 手机个人信息类型:设备出口IP、私网 IP,App版本号信息,系统类型及版本号信息,设备型号信息等。

  • 隐私权政策链接:日志服务(SLS)SDK隐私权政策

第三步:务必做SDK延迟初始化配置,确保用户同意《隐私政策》之后,再初始化SDK。

为保证您正在集成SDK之后,能够满足工信部相关合规要求,您应确保在App安装后首次冷启动时按照如下方式进行SDK的初始化。

  1. 在合适的位置调用预初始化函数(可参考上文SDK接入章节)。预初始化函数不会采集设备信息。

    iOS SDK

    // 预初始化,功能可正常使用,但敏感信息不会采集
    [[SLSCocoa sharedInstance] preInit:credentials configuration:configuration];

    Android SDK

    // 预初始化,功能可正常使用,但敏感信息不会采集
    SLSAndroid.preInit(this, credentials, optionConfiguration);

    Windows SDK

    void demoPreInit(){
        //开始初始化。
        printf("start preInit sdk\n");                   
        AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig();
      	//设置其他参数...
    
        //预初始化SDK,功能可正常使用,但敏感信息不会采集
        config.preInit();
        
        //初始化完成。
        printf("end preInit sdk\n");            
    }

  2. 确保App首次冷启动时,在用户阅读您的《隐私政策》 并取得用户授权之后,才调用正式初始化函数。正式初始化函数调用后,SDK会采集设备IP、设备型号等相关信息。如果用户不同意《隐私政策》授权,则不能调用正式初始化函数。

    iOS SDK

    [[SLSCocoa sharedInstance] initialize:credentials configuration:configuration];

    Android SDK

    SLSAndroid.initialize(context, credentials, optionConfiguration)
  • 本页导读 (1)
文档反馈