日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

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.4' # 建議使用最新版本
    pod 'AliyunLogNetworkDiagnosis', '4.3.8' # 建議使用最新版本

    更多版本信息,請參見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方式獲取,參考文檔:采集-搭建移動端日志直傳服務
    // 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。更多信息,請參見創建接入端應用

  4. Apple的Local Network Privacy(本地網絡隱私)政策適配。

    1. 適用場景。

      從iOS14開始,Apple對訪問本地網絡的隱私政策進行了升級。如果您的應用使用了我們SDK提供的以下功能,可能會觸發Local Network Privacy政策:

      • 使用DNS(域名解析)探測功能:當您使用我們的SDK進行DNS探測,以下兩種情形都會觸發Local Network Privacy政策。

        • 調用者指定DNS服務器(域名解析服務器):當您指定的DNS服務器為私有IP地址(什么是私有地址)時。

        • 調用者不指定DNS服務器:當設備網絡處于WiFi環境下時。

      • 使用pingmtrtcppingudpping等其他探測接口時,目標地址為私有IP地址時。

    2. 如何適配本地網絡隱私政策?

      當您的使用場景會觸發Local Network Privacy政策時,集成步驟中需要確保執行如下措施以避免在提交App Store時被審核拒絕。

      在應用的Info.plist中增加如下鍵值對:

      <key>NSLocalNetworkUsageDescription</key>
      <string>您的應用需要訪問本地網絡的目的說明</string>
      說明

      網絡本地網絡目的需要符合您提供的應用的實際場景,關鍵要點包括:

      1. 說明訪問本地網絡的目的,列舉具體的功能和服務場景,表明對用戶有實際價值和意義。

      2. 承諾會尊重用戶隱私,經授權、在必要時才訪問,不獲取隱私數據,讓審核人員放心。

      3. 語氣真誠友好,希望得到理解支持,體現對審核的重視,有利于通過。

    3. Apple的Local network privacy政策介紹(官方Local Network Privacy FAQ)。

      Apple的Local network privacy(本地網絡隱私)是iOS 14、iPadOS 14、tvOS 14和watchOS 7引入的一項新隱私保護功能。其主要目的在于讓您了解哪些應用程序正在局域網內與其他設備通信,以防止應用程序在未經用戶許可的情況下濫用本地網絡。以下是關于這一功能的詳細解釋:

      1. 本地網絡訪問權限:當應用程序首次嘗試在局域網內與其他設備通信時,系統會向用戶顯示一個彈窗,詢問是否允許該應用訪問本地網絡。您可以選擇是或者否。這為您提供了對應用程序網絡行為更多的控制和了解。

      2. 本地網絡應用程序指示器:當應用程序在局域網內與其他設備通信時,狀態欄會顯示一個指示器(通常是一個帶箭頭的圓點),以提示您當前有應用程序正在使用本地網絡,增加了透明度。

      3. 微調隱私設置:您可以在系統設置的隱私部分查看和管理哪些應用程序被授予了訪問本地網絡的權限。隨時撤銷或重新授予權限。

      4. 影響范圍:任何使用Bonjour、mDNS或其他局域網通信技術的應用程序都會受到本地網絡隱私的影響。常見的場景包括局域網多人游戲、文件共享、智能家居設備控制等。

      5. 開發者適配:為確保應用程序在新的隱私策略下正常工作,開發者需要正確處理本地網絡訪問權限的請求和結果。未經授權的網絡訪問可能會導致應用程序無法正常運行。

      6. 教育:在系統升級過程中,Apple會向您介紹新功能,而應用程序開發者也有責任向您解釋他們需要訪問本地網絡的原因,以及如何妥善處理您的隱私關切。

      Local network privacy提升了用戶對應用網絡活動的可見性和掌控度,有效阻止惡意應用的數據竊取或網絡資源濫用行為。這同時也向開發者提出了更高要求,需在功能實現與用戶隱私保護間尋找平衡。

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.6@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方式獲取,參考文檔:采集-搭建移動端日志直傳服務
    // 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。

    建議您遵循最小化原則,按需授予RAM用戶必要的權限。關于授權的具體操作,請參見創建RAM用戶及授權RAM自定義授權示例

    accessKeySecret

    具備訪問日志服務Logstore權限的AccessKey Secret。

    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平臺依賴的庫。

  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方式獲取,參考文檔:采集-搭建移動端日志直傳服務
    // 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接入

下載地址

單擊Windows SDK,下載Windows SDK包。

重要
  • 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
  • WindowsSDK支持x64/x86模式下多種集成方式,請根據項目需求選擇對應的文件夾:

    • DLL-MD:動態庫,運行時庫MD;

    • DLL-MT:動態庫,運行時庫MT;

    • LIB-MD:靜態庫,運行時庫MD;

    • LIB-MT:靜態庫,運行時庫MT;

  • 上報日志到日志服務時需使用阿里云賬號或RAM用戶的AccessKey,用于鑒權及防篡改。為避免將AccessKey保存在代碼中,造成安全風險,推薦您使用移動端日志直傳服務配置AccessKey。具體操作,請參見采集-搭建移動端日志直傳服務

集成方式

隱式加載

  1. SDK集成準備:

    1. /lib目錄下的庫文件和/include目錄下的頭文件添加到項目中。

    2. 配置附加庫目錄路徑。

    3. 在集成動態庫的過程中,需要將alinetworkdiagnosisMD.dll(根據集成方式的不同,文件后綴可能有所變化)同步到生成目錄中。

  2. SDK初始化:

    #include "api.h"
    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}"); 
    
        //必填,日志上報logstore的AccessKey設置,下述兩種方式二選一
        config.setSlsCredential("{your_access_key_id}","{your_access_key_secret}");
        //或
        //對于通過STS方式獲取AccessKey,使用如下方式初始化AccessKey并設置token失效回調,支持攜帶自定義參數。
        config.setSlsCredential("{your_access_key_id}","{your_access_key_secret}","your_security_token");
        config.setTokenExpiredCallback(on_token_ex);
      	
        //或
        const char* s = "it's user's context";
        config.setTokenExpiredCallback(on_token_ex_ctx, (void*)s);
      
        //可選,設置設備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);
        
        //初始化SDK。
        config.init();
    
        //或者預初始化SDK,見“隱私合規”
        config.preInit();
        
        //初始化完成。
        printf("end init sdk\n");            
    }
    
    // 請求AccessKey信息。
    void requestAccessKey() {
        // 推薦您先使用移動端日志直傳服務配置AccessKey信息。
        // ...
        // 獲取AccessKey信息后,完成更新。
        updateAccessKey(accessKeyId, accessKeySecret, securityToken);
    }
    
    // token失效回調,用于更新AccessKey信息。
    void updateAccessKey(std::string accessKeyId, std::string accessKeySecret, std::string securityToken) {
        // 通過STS服務獲取的AccessKey包含securitToken,需要使用以下方式更新。
        config.setSlsCredential(accessKeyId, accessKeySecret, securityToken);
    }

顯式加載

  1. SDK集成準備:需要將alinetworkdiagnosisMD.dll(根據集成方式的不同,文件后綴可能有所變化)同步到生成目錄中。

  2. SDK初始化:

    #include <stdio.h>
    #include <windows.h>
    
    // 其他方法及參數說明,詳見"api.h"
    typedef void (*DLLInit)(const char* secret_key, const char* device_id, const char* accessKeyId, const char* accessKeySecret, const char* securityToken, const char** extensions, int extLength);
    
    // 或定義預初始化函數
    typedef void (*DLLPreInit)(const char* secret_key, const char* device_id, const char* accessKeyId, const char* accessKeySecret, const char* securityToken, const char** extensions, int extLength);
    
    int init() {
        // 獲取動態庫句柄,具體后綴視集成方式而定
        HINSTANCE hdll = LoadLibrary(L"alinetworkdiagnosisMD.dll");
        if (hdll == NULL) {
            // 加載庫失敗,返回錯誤碼
            fprintf(stderr, "Failed to load library.\n");
            return -11;
        }
      
        // 獲取函數地址
        DLLInit _ipa_init = (DLLInit)GetProcAddress(hdll, "_ipa_init");
        if (_ipa_init == NULL) {
            // 獲取函數地址失敗,釋放庫并返回錯誤碼
            fprintf(stderr, "Failed to get function address from library.\n");
            FreeLibrary(hdll);
            return -1;
        }
    
        // 定義擴展參數
        const char* extensions[] = {
            "Bigkey1", "value1",
            "Bigkey2", "value2",
            "Bigkey3", "value3"
        };
    
        // 調用初始化函數
        _ipa_init("{your_secret_key}",
                  "{your_device_id}",
                  "{your_access_key_id}",
                  "{your_access_key_secret}",
                  "{your_security_token}",
                  extensions,
                  3);
    
        // 成功初始化,返回0
        return 0;
    }

擴展功能

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";

// 可選參數,設置探測級extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");

// 可選參數,設置探測級回調函數
request.complete_callback = (response) => 
{
    Debug.Log("ping->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 發起探測
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";

// 可選參數,設置探測級extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");

// 可選參數,設置探測級回調函數
request.complete_callback = (response) => 
{
    Debug.Log("tcpping->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 發起探測
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 request context id";
request.headerOnly = true;
request.downloadBytesLimit = 1024;

// 可選參數,設置探測級extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");

// 可選參數,設置探測級回調函數
request.complete_callback = (response) => 
{
    Debug.Log("http->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 發起探測
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";

// 可選參數,設置探測級extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");

// 可選參數,設置探測級回調函數
request.complete_callback = (response) => 
{
    Debug.Log("mtr->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 發起探測
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";

// 可選參數,設置探測級extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");

// 可選參數,設置探測級回調函數
request.complete_callback = (response) => 
{
    Debug.Log("dns->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 發起探測
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());
}

設置用戶標簽

用戶將被打上標簽,若其標簽與控制臺配置的探測組標簽存在交集,則相應的探測組規則將會生效。

重要

設置標簽接口可以在任意時刻調用,每次調用會覆蓋原先的設置。

iOS SDK

// 給用戶打上兩個標簽,分別是 "tag_vip", "tag_japan_normal"
NSArray *tags = [[NSArray alloc] initWithObjects:@"tag_vip", @"tag_japan_normal", nil];
[AliNetworkDiagnosis setUserTags:tags];

Android SDK

// 給用戶打上兩個標簽,分別是 "tag_vip", "tag_japan_normal"
String[] tags = {"tag_vip","tag_japan_normal"};
Diagnosis.setUserTags(tags);

更新擴展業務字段

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提供的相關功能在當前進程不再可用,確保在適當的時間調用該接口,并根據需要進行適當的資源管理。

Windows SDK

void unInitSdk() {
 std::cout << "end!" << std::endl;
 AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig();
 //去初始化SDK。
 config.unInit();
}

隱私合規

通過SDK發起網絡探測請求后,SDK會采集網絡信息、App信息、設備信息等。這些信息中主要包含:

  • 用戶設備出口IP、設備私網IP

  • App版本號信息

  • 系統類型及版本號信息

  • 設備型號

為了保障您的App順利通過監管機構的合規檢測,SDK提供了合規使用方案。

  1. 確保您的App有《隱私政策》,并且在用戶首次啟動App時彈出《隱私政策》取得用戶同意。

  2. 務必告知用戶您選擇使用日志服務(SLS)SDK,請在《隱私政策》增加如下參考條款:

    • 使用SDK名稱:日志服務(SLS)SDK。

    • 服務類型:網絡質量數據分析。

    • 手機個人信息類型:設備出口IP、私網 IP,App版本號信息,系統類型及版本號信息,設備型號信息等。

    • 隱私權政策鏈接:日志服務(SLS)SDK隱私權政策

  3. 務必做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)