Advanced Features (Android)
|
Collect
1. Attribute Plugins
Attribute pluginization is an advanced feature provided by the Sensors Analytics Android SDK version 6.4.3 and later, which is used to modify the properties of track-type events. Users can add and delete properties for specific events or add and delete properties for specific event types through attribute plugins.
1.1. Interface Introduction
The SDK provides SAConfigOptions.registerPropertyPlugin() during initialization and SensorsDataAPI.registerPropertyPlugin() after initialization to register custom attribute plugins, which are implemented through SAPropertyPlugin to add properties to specified events. Note that registering in SAConfigOptions at an earlier time ensures that the corresponding properties are added to all filtered events, while registering through SensorsDataAPI may not add the corresponding properties to startup events triggered by delayed initialization.
Introduction to SAPropertyPlugin Class:
Method Name | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
properties(SAPropertiesFetcher fetcher) | Used to modify properties. Get the property JSONObject collection through fetcher.getProperties() and then modify the properties as needed. Introduction to SAPropertiesFetcher Class:
| ||||||||||
isMatchedWithFilter(SAPropertyFilter filter) | Used to specify the scope of the attribute plugin. The default value is to apply to track-type events. Introduction to SAPropertyFilter Class:
| ||||||||||
SAPropertyPluginPriority priority() | The priority of the property plugin, default value is "Default" (500), the higher the value, the higher the level of property modification | ||||||||||
getName() | Used to set the name of the property plugin, ensure that the name is unique and not repeatable, the default value is the fully qualified name of the class |
1.2. Example
In the example below, filter out the specified event and then add custom properties
saConfigOptions.registerPropertyPlugin(new SAPropertyPlugin() { @Override public boolean isMatchedWithFilter(SAPropertyFilter filter) { // 示例,筛选指定事件名添加属性,默认筛选条件是 track 事件类型 return "指定事件名称".equals(filter.getEvent()); } @Override public void properties(SAPropertiesFetcher fetcher) { try { // 给符合筛选条件的事件添加属性 fetcher.getProperties().put("自定义属性","自定义属性名称"); //fetcher.getProperties().remove(key) 删除执行属性 } catch (JSONException e) { e.printStackTrace(); } } });
2. Intercept event storage
v3.2.10 and later versions, the SDK can filter event data by using the setTrackEventCallBack() method. The SDK decides whether to store the event based on the return value of the onTrackEvent interface. If it returns true, the current event will be stored and reported normally. If it returns false, it means that the event is discarded.
SensorsDataAPI.sharedInstance().setTrackEventCallBack(new SensorsDataTrackEventCallBack() { /** * 事件回调接口 * * @param eventName 事件名称 * @param eventProperties 要修改的事件属性 * @return true 表示事件将入库, false 表示事件将被抛弃 */ @Override public boolean onTrackEvent(String eventName, JSONObject eventProperties) { if(eventName.equals("BuyProduct")){ // 不要这个埋点了 returen false; } // return true; } });
3. Custom caching and encryption
In the basic API introduction document, the SDK cache encryption is encrypted using AES by default. If you need to use other encryption methods, you need to customize it through the cache encryption plugin.
3.1. Interface Introduction
Call the registerStorePlugin interface to register a custom encryption plugin during SDK initialization to enable it.
StorePlugin Class Introduction:
Method Name | Description |
---|---|
setString(String key, String value) | Store String type data, and implement the corresponding storage logic |
getString(String key) | Get String type data based on the specified key, and implement the retrieval logic |
setBool(String key, boolean value) | Store boolean type data, and implement the corresponding storage logic |
getBool(String key) | Get boolean type data based on the specified key, and implement the retrieval logic |
setInteger(String key, int value) | Store int type data, and implement the corresponding storage logic |
getInteger(String key) | Get int type data based on the specified key, and implement the retrieval logic |
setFloat(String key, float value) | Store float type data, and implement the corresponding storage logic |
getFloat(String key) | Get float type data according to the specified key and implement the retrieval logic |
setLong(String key, long value) | Store long type data and implement the corresponding storage logic |
getLong(String key) | Get long type data according to the specified key and implement the retrieval logic |
remove(String key) | Delete the specified key and implement the corresponding logic |
type() | The name of the attribute plugin, need to implement the corresponding logic |
isExists(String key) | Check if the specified key exists in the storage file and implement the corresponding logic |
When customizing the cache encryption storage plugin, developers need to implement the storage and retrieval of corresponding data types.
3.2. Usage Example
In the following example, the custom encryption plugin is used to implement the GM algorithm encryption.
public class SM4StorePlugin implements StorePlugin { private static final String FILE_NAME = "com.sensorsdata.storePlugin"; private static final String SM4_SECRET = "sm4_key"; private byte[] mSM4KeyBytes; private final SharedPreferences mSPreferences; static { try { Class<?> provider = Class.forName("org.spongycastle.jce.provider.BouncyCastleProvider"); Security.addProvider((Provider) provider.newInstance()); } catch (Exception e) { e.printStackTrace(); } } public SM4StorePlugin(Context context) { mSPreferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); try { if (mSPreferences.contains(SM4_SECRET)) { mSM4KeyBytes = Base64Coder.decode(mSPreferences.getString(SM4_SECRET, null)); } if (mSM4KeyBytes == null) { mSM4KeyBytes = generateSymmetricKey(); mSPreferences.edit().putString(SM4_SECRET, new String(Base64Coder.encode(mSM4KeyBytes))).apply(); } } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } @Override public void upgrade(StorePlugin oldPlugin) { // 升级时的处理操作 } @Override public void setString(String key, String value) { mSPreferences.edit().putString(key, sm4Encrypt(value)).apply(); } @Override public void setBool(String key, boolean value) { mSPreferences.edit().putBoolean(key, value).apply(); } @Override public void setInteger(String key, int value) { mSPreferences.edit().putInt(key, value).apply(); } @Override public void setFloat(String key, float value) { mSPreferences.edit().putFloat(key, value).apply(); } @Override public void setLong(String key, long value) { mSPreferences.edit().putLong(key, value).apply(); } @Override public String getString(String key) { return sm4Decrypt(mSPreferences.getString(key, null)); } @Override public Boolean getBool(String key) { return mSPreferences.getBoolean(key, false); } @Override public Integer getInteger(String key) { return mSPreferences.getInt(key, 0); } @Override public Float getFloat(String key) { return mSPreferences.getFloat(key, 0); } @Override public Long getLong(String key) { return mSPreferences.getLong(key, 0); } @Override public void remove(String key) { mSPreferences.edit().remove(key).apply(); } @Override public boolean isExists(String key) { return mSPreferences.contains(key); } @Override public String type() { return FILE_NAME; } private byte[] generateSymmetricKey() throws NoSuchAlgorithmException { KeyGenerator keyGen = KeyGenerator.getInstance("SM4"); keyGen.init(128); SecretKey aesKey = keyGen.generateKey(); return aesKey.getEncoded(); } /** * 使用 SM4 进行加密 * @return 加密后的数据 */ private String sm4Encrypt(String content) { if (mSM4KeyBytes == null) { return content; } try { Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding"); byte[] ivBytes = new byte[16]; SecretKeySpec secretKeySpec = new SecretKeySpec(mSM4KeyBytes, "SM4"); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(ivBytes)); byte[] encryptedBytes = cipher.doFinal(content.getBytes("UTF-8")); return new String(Base64.encode(encryptedBytes)); } catch (Exception ex) { SALog.printStackTrace(ex); } return content; } private String sm4Decrypt(String content) { try { if (mSM4KeyBytes == null) { return content; } Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding"); byte[] ivBytes = new byte[16]; SecretKeySpec secretKeySpec = new SecretKeySpec(mSM4KeyBytes, "SM4"); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(ivBytes)); return new String(cipher.doFinal(Base64Coder.decode(content)), "UTF-8"); } catch (Exception e) { e.printStackTrace(); } return content; } }
4. Restrict SDK from reading sensitive attributes
This function is used to set sensitive device identifier values for the SDK on the app side and can be used to solve the problem of multiple calls to device identifiers.Currently, the SDK caches information such as the carrier, Android ID, device ID, and MAC address. The cached data is used when the retrieval is successful, and another retrieval attempt is made if it is empty.
This operation is a dangerous operation. Please consult the on-duty colleague for guidance before use.
4.1. Interface Description
Interface Name | Parameter Description | Purpose of the interface |
---|---|---|
registerLimitKeys(Map<String, String> limitKeys) | Set the collection of restrictive attributes | Replace the corresponding interface call by setting the preset value of the restrictive attribute, used to avoid sensitive API calls |
Android preset LimitKey
Name | Description |
---|---|
ANDROID_ID | Android ID, used for $device_id property collection and user identification in anonymous state (distinct_id, AnonymousId). When Android ID is disabled, uuid is used as the user identifier. Dangerous operation, please make sure the value is correct. |
CARRIER | Carrier, carrier information. Dangerous operation, please make sure the value is correct. |
IMEI | IMEI number, used for channel matching. Dangerous operation, please make sure the value is correct. |
MAC | Mac address, used for channel matching. Dangerous operation, please make sure the value is correct. |
OAID | OAID used for channel matching. Dangerous operation, please make sure the value is correct. |
MEID | MEID number, used for channel matching. Dangerous operation, please make sure the value is correct. |
4.2. Usage Example
注意
AndroidID involves user identification, please make sure to pass it correctly. It is recommended to obtain AndroidID through the interface for obtaining AndroidID provided by Sensors Analytics.
SAConfigOptions configOptions = new SAConfigOptions(SA_SERVER_URL); // 设置限制性属性 Map<String, String> map = new HashMap<>(); map.put(LimitKey.ANDROID_ID, SensorsDataUtils.getIdentifier(this)); map.put(LimitKey.CARRIER, SensorsDataUtils.getOperator(this)); configOptions.registerLimitKeys(map); //传入 SAConfigOptions 对象,初始化神策 SDK SensorsDataAPI.startWithConfigOptions(this, configOptions);
5. Prohibited to acquire the IMEI number
If you do not want to collect IMEI, you can configure it not to collect through the following configuration. After configuration, the Sensors Analytics plug-in will remove the related code that obtains IMEI during the compilation period.
Configure in the main module's build.gradle:
// 禁止获取 IMEI 号 sensorsAnalytics { sdk { disableIMEI = true } }
- disableIMEI has a default value of false. If set to true, the IMEI will not be collected, which will affect channel tracking.
- This configuration is only applicable to plug-in version v3.0.0 and above.
- In the environment before Android Grdle Plugin 3.2.0 (Android Studio 3.2), if you want to use this configuration, you need to manually enable D8 desugaring in gradle.properties: android.enableD8.desugaring = true
6. Prohibited to acquire Android ID
If you do not want to collect Android ID, you can configure it not to collect through the following configuration. After configuration, the Sensors Analytics plug-in will remove the related code that obtains Android ID during the compilation period.
Configure in the main module's build.gradle:
// 禁止获取 Android ID sensorsAnalytics { sdk { disableAndroidID = true } } // 开启获取 Android ID sensorsAnalytics { sdk { disableAndroidID = false } }
- disableAndroidID has a default value of false. If set to true, the Android ID will not be collected, which will affect the $device_id event property and channel tracking.
- This configuration is only applicable to plug-in version v3.0.0 and above.
- In the environment before Android Grdle Plugin 3.2.0 (Android Studio 3.2), if you want to use this configuration, you need to manually enable D8 desugaring in gradle.properties: android.enableD8.desugaring = true
7. Prohibited to acquire OAID
If not collect OAID, the following configurations do not collect data, This configuration deletes the contents of OaidHelper.getOAID, uniformly returning an empty string 。
Inmain Module build.gradle configure:
// 禁止获取 OAID sensorsAnalytics { sdk { disableOAID = true } }
- disableOAID default value is false,If setted as true ,OAID will not be collected.
- This configuration is only applicable to plugin version v3.4.7 and above.
- In the environment of Android Grdle Plugin 3.2.0 (Android Studio 3.2) and earlier versions, you need to manually enable the desugaring configuration in gradle.properties: android.enableD8.desugaring = true
8. Prohibit obtaining the MacAddress.
If you do not want to collect MacAddress, you can configure it to not collect it. After configuration, the Sensors Analytics plugin will remove the relevant code for obtaining the mac address during compilation.
Configure in the main Module's build.gradle:
// 禁止获取 MacAddress sensorsAnalytics { sdk { disableMacAddress = true } }
- The default value of disableMacAddress is false. If set to true, the mac address will not be collected, which will affect channel tracking.
- This configuration is only applicable to plugin version v3.0.0 and above.
- In the environment of Android Grdle Plugin 3.2.0 (Android Studio 3.2) and earlier versions, you need to manually enable the desugaring configuration in gradle.properties: android.enableD8.desugaring = true
Note: The content of this document is a technical document that provides details on how to use the Sensors product and does not include sales terms; the specific content of enterprise procurement products and technical services shall be subject to the commercial procurement contract.