1. 權限設定說明

SDK 共需要四個權限:

權限

用途

INTERNET必須權限,允許應用傳送統計數據,SDK 傳送埋點數據需要此權限
ACCESS_NETWORK_STATE必須權限,允許應用檢測網路狀態,SDK 會根據網路狀態選擇是否傳送數據
READ_PHONE_STATE

可選權限,允許應用取得裝置 IMEI,採用 APP 內推廣和採集 $carrier 屬性時會用到此權限

ACCESS_WIFI_STATE

可選權限,允許應用取得 MAC 網址,採用 APP 內推廣時會用到此權限

SDK 為簡化整合步驟,預設在 AndroidManifest.xml 中註冊了以上四個權限。如果想要去除 SDK 註冊的權限,可以使用 tools:node="remove" 設定。關於 ools:node="remove" 的詳細說明可參考Google官方文件,設定程式碼參考:

<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
XML

2. 開啟螢幕方向的自動採集

v1.10.1 及以後的版本可以透過 enableTrackScreenOrientation() 方法開啟螢幕方向屬性的收集,螢幕方向資訊記錄在事件的 $screen_orientation 屬性中。

SAConfigOptions saConfigOptions = new SAConfigOptions(SA_SERVER_URL);
//利用初始化的 SAConfigOptions 物件開啟螢幕方向屬性的收集
saConfigOptions.enableTrackScreenOrientation(true);

SensorsDataAPI.startWithConfiguration(this, saConfigOptions);
JAVA

3. 開啟位置資訊自動採集

v1.10.1 及以後的版本可以透過 setGPSLocation() 方法,把第三方定位取得到的經緯度資訊設定給 SDK,設定之後經緯度資訊記錄在事件的 $longitude$latitude 屬性中。

//設定經緯度
SensorsDataAPI.sharedInstance().setGPSLocation(latitude,longitude);
JAVA

4. 事件時長

可以透過計時器統計事件的持續時間。首先,在事件開始時呼叫(v1.10.6 及以後版本支援) trackTimerStart("Event") ,該方法並不會真正傳送事件;在事件結束時,呼叫 trackTimerEnd("Event", properties),SDK 會觸發 "Event" 事件,並自動將事件持續時間記錄在事件屬性 "$event_duration" 中。例如記錄用戶瀏覽商品頁面的時間:

// 進入商品頁面
// 呼叫 trackTimerStart("ViewProduct") 標記事件啟動時間
SensorsDataAPI.sharedInstance().trackTimerStart("ViewProduct");

// ... 用戶瀏覽商品

// 離開商品頁
try {
  // 在屬性中記錄商品 ID
  JSONObject properties = new JSONObject();
  properties.put("product_id", PRODUCT_ID);
  // 呼叫 track,記錄 ViewProduct 事件,並在屬性 event_duration 中記錄用戶瀏覽商品的時間
  SensorsDataAPI.sharedInstance().trackTimerEnd("ViewProduct", properties);
} catch (JSONException e) {
  e.printStackTrace();
}
JAVA

多次呼叫 trackTimerStart("Event") 時,事件 "Event" 的開始時間以最後一次呼叫時為準。

從 v3.1.5 版本開始,統計事件時長支援暫停和恢復,透過呼叫 trackTimerPause(String eventName) 和 trackTimerResume(String eventName) 來分別實作暫停和恢復。

4.1. 同名事件交叉的時長統計

預設情況下,時長的統計以事件名作為標識,相同的事件名會自動匹配 start-end,如果兩個同名事件在時間上有交叉部分,會造成錯誤匹配。為了解決此問題,從 v3.2.11 版本開始 SDK 支援同名事件交叉的時長統計,開發者需要保存 trackTimerStart() 的回傳值,以便後續針對性地進行暫停、恢復或停止。

// 開始第一個事件計時
String timer1 = SensorsDataAPI.sharedInstance().trackTimerStart("testTimer");

// 開始第二個事件計時
String timer2 = SensorsDataAPI.sharedInstance().trackTimerStart("testTimer");

//如果需要暫停第一個事件計時
SensorsDataAPI.sharedInstance().trackTimerPause(timer1);

//如果需要恢復第一個事件計時
SensorsDataAPI.sharedInstance().trackTimerResume(timer1);

// 結束第一個事件計時
SensorsDataAPI.sharedInstance().trackTimerEnd(timer1);

// 結束第二個事件計時
SensorsDataAPI.sharedInstance().trackTimerEnd(timer2);
JAVA

5. 取得預設屬性

v1.8.17 及以後的版本可以呼叫 getPresetProperties() 方法取得預設屬性。
伺服器端埋點需要 App 端的一些預設屬性時,可以透過此方法取得 App 端的預設屬性,再傳給伺服器端。

//取得預設屬性
JSONObject presetProperties=SensorsDataAPI.sharedInstance().getPresetProperties();
JAVA

6. 設定動態公共屬性

Android SDK v2.0.1 及以後的版本可以透過 registerDynamicSuperProperties() 方法設定動態公共屬性,設定之後 SDK 會自動取得 getDynamicSuperProperties() 中的屬性增加到觸發的事件中。

// 初始化 SDK 後,設定動態公共屬性
SensorsDataAPI.sharedInstance().registerDynamicSuperProperties(new SensorsDataDynamicSuperProperties() {
    @Override
    public JSONObject getDynamicSuperProperties() {
        try {
            // 比如 isLogin() 是用於取得用戶當前的登入狀態,SDK 會自動取得 getDynamicSuperProperties 中的屬性增加到觸發的事件中。
            boolean bool = isLogin();
            return new JSONObject().put("isLogin",bool);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
});
JAVA

呼叫 registerDynamicSuperProperties() 方法設定的動態公共屬性,不能用 unregisterSuperProperty() 方法刪除

7. 取得用戶 ID

神策中每個事件都會關聯到一個ID 上,用於標識該事件所對應的用戶或裝置資訊,我們稱之為distinct_id,此值在未呼叫 SDK 中 login() 方法前,取得的是預設的 SDK 分配的匿名IDv1.10.5 及以後的版本預設使用 AndroidId 作為匿名ID),呼叫 login() 方法後取得的是 login() 方法中傳入的值。

您可以透過 getDistinctId() 方法取得該ID:

//取得當前用戶的distinctId
String distinctId=SensorsDataAPI.sharedInstance().getDistinctId();
JAVA

您也可以透過 getAnonymousId() 方法 取得神策分析 SDK 分配的匿名 ID:

//取得當前用戶的匿名id
String AnonymousId=SensorsDataAPI.sharedInstance().getAnonymousId();
JAVA

8. 用戶屬性設定

8.1. 記錄初次設定的用戶屬性

對於只在首次設定時有效的屬性,我們可以使用 profileSetOnce() 記錄這些屬性。與 profileSet() 方法不同的是,如果被設定的用戶屬性已存在,則這條記錄會被忽略而不會覆蓋已有數據,如果屬性不存在則會自動建立。因此,profileSetOnce() 適用於為用戶設定首次啟動時間、首次註冊時間等屬性。例如:

try {
    JSONObject properties = new JSONObject();
    properties.Put("AdSource", "XXX Store");

    //  設定用戶管道為,"developer@sensorsdata.cn" 的 "AdSource" 屬性值為 "XXX Store"
    SensorsDataAPI.SharedInstance().ProfileSetOnce(properties);

    JSONObject newProperties = new JSONObject();
    newProperties.Put("AdSource", "Email");

    // 再次設定用戶管道,設定無效,"developer@sensorsdata.cn" 的 "AdSource" 屬性值仍然是 "XXX Store"
    SensorsDataAPI.SharedInstance().ProfileSetOnce(newProperties);
} catch (JSONException e) {
    e.PrintStackTrace();
}
JAVA

8.2. 數值型別的屬性

對於數值型的用戶屬性,可以使用 profileIncrement() 對屬性值進行累加。常用於記錄用戶付費次數、付費額度、積分等屬性。例如:

// 將用戶遊戲次數屬性增加一次
SensorsDataAPI.sharedInstance().profileIncrement("GamePlayed", 1);

// 增加用戶付費次數和積分
Map<String, Number> properties = new HashMap<String, Number>();
properties.put("UserPaid", 1);
properties.put("PointEarned", 12.5);

SensorsDataAPI.sharedInstance().profileIncrement(properties);
JAVA

8.3. 列表型別的屬性

對於用戶喜愛的電影、用戶評價過的餐廳等屬性,可以記錄列表型屬性,例如:

Set<String> movies = new HashSet<String>();
movies.add("Sicario");
movies.add("Love Letter");

// 設定用戶觀影列表屬性,設定後屬性 "Movies" 為: ["Sicario", "Love Letter"]
SensorsDataAPI.sharedInstance().profileAppend("Movies", movies);

// 再次設定該屬性,屬性 "Movies" 為: ["Sicario", "Love Letter", "Dead Poets Society"]
SensorsDataAPI.sharedInstance().profileAppend("Movies", "Dead Poets Society");
JAVA

需要注意的是,列表型屬性中的元素必須為 String  型別,且元素的值會自動去重。關於列表型限制請見數據格式

9. 開啟點擊分析功能

版本要求

  • 神策分析 1.13+
  • 此功能依賴於全埋點中點擊事件採集的開啟
  • 使用此功能前,確保您的 App 中設定了當前專案的 Scheme,詳細操作可參考 設定 Scheme

v1.9.0+ 版本的 SDK 支援 App 點擊分析功能,SDK 初始化前呼叫 SAConfigOptions 實例的 enableHeatMap() 方法,並且參數傳入 true 即可開啟 SDK 的點擊分析功能:

saConfigOptions.enableHeatMap(true);
JAVA

開啟 App 點擊分析後,該功能預設對所有頁面上的點擊生效,如果您只是想部分頁面進行熱力圖,可以透過 addHeatMapActivity()addHeatMapActivities() 方法設定:

//開啟某個 Activity 的點擊圖
SensorsDataAPI.sharedInstance().addHeatMapActivity(Class<?> activity);
//開啟多個 Activity 的點擊圖
SensorsDataAPI.sharedInstance().addHeatMapActivities(List<Class<?>> activitiesList);
JAVA

10. 埋點數據的加密功能

為了加強埋點數據的安全性,神策分析支援對埋點數據進行加密,並以密文的形式對數據進行儲存和傳送。

本功能需要伺服器端的配合,可以聯繫神策客戶成功/專案經理協助開通伺服器端解密功能。預設使用 RSA 類型的私鑰,可指定使用 EC 類型私鑰。

10.1. SDK 端開啟加密

對於 4.2.0+ 版本 SDK,初始化前進行如下設定,即可開啟 SDK 的加密功能:

// 開啟加密
configOptions.enableEncrypt(true);
JAVA

對於 v4.4.0+ 版本的 SDK 開始支持 EC 算法加密。在使用 enableEncrypt() 開啟加密的基礎上增加如下依賴,即可切換到 EC 算法加密:

dependencies {
   // 增加 EC 演算法函式庫依賴
   implementation 'com.sensorsdata.provider:SensorsAnalyticsProvider:0.0.1'
}
XML

注意

SensorsAnalyticsProvider 封裝了支持 Android 系統的 v1.58.0.0 版本的 EC 演算法函式庫(您也可以從 GitHub 上整合此庫),該庫大小為 5MB 左右。同時該倉庫中包含眾多方法,對於大型專案,可能會遇到方法數超過 64K 的問題,需要參照 Android 官方設定文件開啟 multiDexEnabled 設定項

10.2. 加密私鑰的驗證

使用此功能前,確保您的 App 中設定了當前專案的 Scheme,詳細操作可參考 設定 Scheme

在神策分析平台中,進入私鑰管理功能,進入路徑:「更多」 → 「基本設定」 → 「數據接入」 → 「私鑰管理」

點擊「私鑰管理」按鈕進入私鑰管理頁面 

點擊對應私鑰的 QR Code 圖示,用瀏覽器掃描 QR Code 打開 App 進行私鑰驗證。

  • 驗證一致,則 App 端提示 "私鑰驗證通過,所選私鑰與 App 端私鑰相同"
  • 驗證不一致:則 App 端提示 “私鑰驗證不通過,所選私鑰與 App 端私鑰不相同。所選私鑰版本:v1,App 端私鑰版本:v2”
  • 如果本地私鑰為空:則 App 端提示 “私鑰驗證不通過,App 端私鑰為空”
  • 如果掃描私鑰為空:則 App 端提示 “私鑰驗證不通過,所選私鑰無效”

11. 開啟除錯模式動態設定功能

在神策 Android SDK (3.0.3+) 中,可以透過掃描網頁 QR Code 的方式,開啟該裝置的「除錯模式」。除錯模式的設定請參考除錯模式動態設定

12. 啟動事件與退出事件 30 秒 session 說明

神策 SDK 為了應對多處理程序、強制退出等場景,在 v2.0.3 版本加入了30 秒的 session 機制,用戶退出 App 到後台 30 秒的時候,才會觸發退出事件,之後再啟動 App,才會觸發啟動事件,用戶如果在30 秒內打開了App,那麼是沒有對應的退出事件與啟動事件的。

另外,如果在退出 App 到後台 30 秒內,處理程序還沒有被殺掉,那麼此時會觸發退出事件並嘗試上報,如果處理程序被殺掉了,那麼退出事件會在下一次啟動時補發。所以在查看數據時,一般退出事件比啟動事件少。

13. 自定義上報策略

需要更精細地控制神策分析可以透過以下選項設定數據採集功能。

13.1. 數據採集

在每次呼叫 track()login()profileSet() 等方法時,神策分析 SDK 會將事件與屬性保存在 App 的儲存空間中,並會檢查如下條件,以判斷是否向伺服器上傳數據:

  1. 是否是WIFI/2G/3G/4G/5G網路條件
  2. 是否滿足傳送條件之一:
    1. 與上次傳送的時間間隔是否大於 flushInterval
    2. 本地快取 log 數量是否大於 flushBulkSize
    3. 事件類型為 login() 方法觸發的 $SignUp 事件

預設的 flushBulkSize 為100 條,預設的 flushInterval 為 15 秒。滿足條件後,神策分析 SDK 會將數據 gzip 壓縮後,批量傳送到神策分析。

如果追求數據採集的時效性,可以呼叫 flush() 方法,強制將數據傳送到神策分析,例如:

// 記錄用戶登入事件
SensorsDataAPI.sharedInstance().track("UserLogin");

// 強制傳送數據
SensorsDataAPI.sharedInstance().flush();
JAVA

在App進入後台狀態時,SDK會呼叫 flush() 方法,將快取的數據傳送到神策分析。

13.2. 設定同步數據時的網路策略

預設情况下,在 WIFI/3G/4G/5G 網路條件下,SDK 都會嘗試去同步數據。v1.7.2 及之後的版本支援可以自定義同步數據的網路策略。
透過 setFlushNetworkPolicy() 方法來指定傳送數據的網路策略。例如:

//網路模式選項
//SensorsDataAPI.NetworkType.TYPE_2G     2G網路下傳送數據
//SensorsDataAPI.NetworkType.TYPE_3G     3G網路下傳送數據
//SensorsDataAPI.NetworkType.TYPE_4G     4G網路下傳送數據
//SensorsDataAPI.NetworkType.TYPE_5G     5G網路下傳送數據
//SensorsDataAPI.NetworkType.TYPE_WIFI   WIFI網路下傳送數據
//SensorsDataAPI.NetworkType.TYPE_ALL    2G/3G/4G/5G/WIFI網路下傳送數據
//SensorsDataAPI.NetworkType.TYPE_NONE   所有網路下都不傳送數據

//指定只在 3G/4G/WIFI 條件下傳送數據。
SensorsDataAPI.sharedInstance().setFlushNetworkPolicy(SensorsDataAPI.NetworkType.TYPE_3G|SensorsDataAPI.NetworkType.TYPE_4G|SensorsDataAPI.NetworkType.TYPE_WIFI);
JAVA

13.3. 設定本地快取上限值

SDK 本地數據庫預設快取數據的上限值為 32MB。 v1.7.4 及以後的版本支援透過 setMaxCacheSize() 方法來設定快取數據的上限值。參數單位 byte

SAConfigOptions saConfigOptions = new SAConfigOptions(SA_SERVER_URL);
//在初始化時,利用 SAConfigOptions 設定本地數據快取上限值為16MB
saConfigOptions.setMaxCacheSize(16 * 1024 * 1024);
JAVA

v3.1.0 及之前的版本,設定快取方式:

//設定本地數據快取上限值為16MB
SensorsDataAPI.sharedInstance().setMaxCacheSize(16 * 1024 * 1024);
JAVA

當儲存數量達到上限時,會依次丟掉舊數據,保留最新的數據

13.4. 修改 SDK 設定參數

修改 app/src/main/AndroidManifest.xml,在 <application> 標籤中,增加 <meta-data> 項,可以修改 SDK 的預設參數,支援的選項如下:

  • com.sensorsdata.analytics.android.FlushInterval - 設定 SDK 的 flushInterval,單位毫秒,預設值為 15 秒;
  • com.sensorsdata.analytics.android.FlushBulkSize - 設定 SDK 的 flushBulkSize,預設值為 100;
  • com.sensorsdata.analytics.android.ResourcePackageName - 設定 App 的 Package Name,預設值為 Application 物件的 Package Name,當 App 的 R.* class 的 Package Name 與 Application 不同時,需要手動填入該設定;

例如,設定神策分析 SDK 的 flushInterval 為 30 秒,flushBulkSize 為 50 條,關閉 Toast 提示:

<application>
    <meta-data
        android:name="com.sensorsdata.analytics.android.FlushInterval"
        android:value="30000" />
    <meta-data
        android:name="com.sensorsdata.analytics.android.FlushBulkSize"
        android:value="50" />
    <meta-data
        android:name="com.sensorsdata.analytics.android.ShowDebugInfoView"
        android:value="false" />
</application>
XML

也可以利用程式碼,修改 FlushInterval 和 FlushBulkSize

SAConfigOptions saConfigOptions = new SAConfigOptions(SA_SERVER_URL);
//在初始化時,利用 SAConfigOptions 設定相關參數
// 每快取 50 條 log 傳送一次
saConfigOptions.setFlushBulkSize(50);
// 設定每 30 秒傳送一次
saConfigOptions.setFlushInterval(30000);
JAVA

v3.1.0 及之前的版本,設定相關參數:

// 每快取 50 條 log 傳送一次
SensorsDataAPI.sharedInstance().setFlushBulkSize(50);

// 設定每 30 秒傳送一次
SensorsDataAPI.sharedInstance().setFlushInterval(30000);

//打開自動追蹤
SensorsDataAPI.sharedInstance().enableAutoTrack();
JAVA

14. 清空本地快取事件

v3.1.5 及之後的版本可以透過 deleteAll() 方法,刪除 App 本地儲存的所有事件。

如果不是特殊要求,請不要呼叫此方法。

//刪除 App 本地儲存的所有事件
SensorsDataAPI.sharedInstance().deleteAll();
JAVA

15. 設定自簽憑證

v3.1.2 及以後的版本可以透過 setSSLSocketFactory() 方法設定自簽憑證,設定自簽憑證後,SDK 內所有的 HTTPS 請求會進行此介面設定的憑證校驗。以 DER 格式的憑證為例:

try {
    //構建 SSLSocketFactory 實體
    SSLSocketFactory sslSocketFactory ;
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    // 其中 R.raw.ca 是您這邊自簽憑證的公鑰
    InputStream in = getResources().openRawResource(R.raw.ca);
    Certificate ca = cf.generateCertificate(in);
    try {
        in.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    keystore.load(null, null);
    keystore.setCertificateEntry("ca", ca);
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    tmf.init(keystore);
    // Create an SSLContext that uses our TrustManager
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), null);
    sslSocketFactory = sslContext.getSocketFactory();
    //將實體傳入神策
    SensorsDataAPI.sharedInstance().setSSLSocketFactory(sslSocketFactory);
} catch (Exception e) {
    e.printStackTrace();
}

JAVA

關於 SSL 的更多内容可以参考Google使用文件

16. 追蹤並進行管道匹配和回傳

從 Android v4.1.0 開始 SDK 支援 track 方法觸發的自定義事件增加管道屬性的邏輯。

16.1. 使用方法:

在初始化 SDK 的時候呼叫 SAConfigOptions.enableAutoAddChannelCallbackEvent(true) 方法來開啟功能,此功能預設是關閉的。範例如下:

private void initSensorsDataAPI() {
        SAConfigOptions configOptions = new SAConfigOptions(SA_SERVER_URL);
        configOptions.setAutoTrackEventType(SensorsAnalyticsAutoTrackEventType.APP_START |
                SensorsAnalyticsAutoTrackEventType.APP_END |
                SensorsAnalyticsAutoTrackEventType.APP_VIEW_SCREEN |
                SensorsAnalyticsAutoTrackEventType.APP_CLICK)
                .enableTrackAppCrash()
                .enableAutoAddChannelCallbackEvent(true) //開啟新管道功能
        SensorsDataAPI.startWithConfigOptions(this, configOptions);
    }
JAVA

16.2. 效果:

可以使用 SensorsDataAPI.shareInstance().track(eventName) 來對特定的事件進行管道追溯。

  • 當次安裝、首次觸發回傳事件,記錄事件並進行管道匹配和回傳。
  • 當次安裝、再次觸發回傳事件,記錄事件並進行管道匹配,匹配結果不進行回傳。
  • 移除重裝、首次觸發回傳事件,記錄事件並進行管道匹配和回傳。

p.s. 上述規則適用於同名事件,不同事件之間不相互影響。

17. 入庫前修改事件資訊

v3.2.10 及以後版本,SDK 可以透過 setTrackEventCallBack() 方法過濾埋點的事件數據。

SensorsDataAPI.sharedInstance().setTrackEventCallBack(new SensorsDataTrackEventCallBack() {
/**
     * 事件回呼介面
     *
     * @param eventName 事件名稱
     * @param eventProperties 要修改的事件屬性
     * @return true 表示事件將入庫, false 表示事件將被拋棄
     */
	@Override
	public boolean onTrackEvent(String eventName, JSONObject eventProperties) {
		// 移除 BuyProduct 事件的 productID 屬性
		if(eventName.equals("BuyProduct")){
			eventProperties.remove("productID");
		}
		//
		return true;
	}
});
JAVA

18. 開啟 Crash 資訊的自動採集

v1.8.12 及以後的版本支援 Crash 資訊收集,App Crash 時,會觸發 AppCrashed 事件,堆疊資訊記錄在 app_crashed_reason 屬性中。

SAConfigOptions saConfigOptions = new SAConfigOptions(SA_SERVER_URL);
//利用初始化的 SAConfigOptions 物件開啟 crash 資訊採集
saConfigOptions.enableTrackAppCrash();
SensorsDataAPI.startWithConfiguration(this, saConfigOptions);
JAVA

v3.1.0 及之前的版本,開啟 Crash 採集:

//開啟 crash 資訊收集
SensorsDataAPI.sharedInstance().trackAppCrash();
JAVA

19. 自定義匿名 ID

預設情況下,SDK 會產生匿名 ID 並可以保證該 ID 的唯一性,如果需要替換神策預設分配的匿名 ID ,可以在初始化 SDK 之後立即呼叫 identify(“用戶自定義匿名 ID ”) 方法進行替換。

//設定自定義匿名 ID,在初始化 SDK 之後立即呼叫
SensorsDataAPI.sharedInstance().identify(“用戶自定義匿名 ID ”);
JAVA

20. 關於 MultiDex

如果使用了 MultiDex ,請確保神策 Android SDK 的程式碼都指定到主 DEX 中。可以透過在 multiDexKeepProguard  裡增加如下設定:

-keep class com.sensorsdata.analytics.android.** { *; }
GROOVY

21. 取得應用程式簽名

在本地使用 keytool -list -v -keystore 【簽名路徑】