高级功能(Android)
|
收藏
1. 属性插件化
属性插件化是神策 Android SDK 在 v6.4.3 及以后版本提供用于修改 track 类型埋点事件属性的高级功能,用户可通过属性插件实现指定事件的属性新增和删除、特定类型事件的属性新增和删除。
1.1. 接口介绍
SDK 提供了 SAConfigOptions.registerPropertyPlugin() 初始化时和 SensorsDataAPI.registerPropertyPlugin() 初始化后注册自定义属性插件,通过实现自定义 SAPropertyPlugin 属性插件用于给指定的事件添加属性。
SAPropertyPlugin 类介绍:
方法名 | 描述 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
properties(SAPropertiesFetcher fetcher) | 用于对属性进行修改,通过 fetcher.getProperties() 获取属性 JSONObject 集合,然后完成对属性的修改。 SAPropertiesFetcher 类的方法介绍:
| ||||||||||
isMatchedWithFilter(SAPropertyFilter filter) | 用于指定属性插件的生效范围,默认值对 track 类型事件生效。 SAPropertyFilter 类的方法介绍:
| ||||||||||
SAPropertyPluginPriority priority() | 属性插件优先级,默认为 Default(500),取值越高修改属性的等级越高。 | ||||||||||
getName() | 用于设置属性插件的名称,需确保名称唯一不可重复,默认取值为类全路径名称。 |
1.2. 使用示例
在下面的实例中,筛选出指定事件,然后添加自定义属性。
SensorsDataAPI.sharedInstance().registerPropertyPlugin(new SAPropertyPlugin() {
@Override
public boolean isMatchedWithFilter(SAPropertyFilter filter) {
// 示例,筛选指定事件名添加属性,默认筛选条件是 track 事件类型
return "指定事件名称".equals(filter.getEvent());
}
@Override
public void properties(SAPropertiesFetcher fetcher) {
try {
// 给符合筛选条件的事件添加属性
fetcher.getProperties().put("自定义属性","自定义属性名称");
} catch (JSONException e) {
e.printStackTrace();
}
}
});
2. 拦截事件入库
v3.2.10 及以后版本,SDK 可以通过 setTrackEventCallBack() 方法过滤埋点的事件数据。SDK 根据 onTrackEvent 接口的返回值决定埋点事件是否入库,返回 true 则当前事件会入库并正常上报,返回 false 则表示丢弃该条事件。
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;
}
});
3. 自定义缓存加密
在基础 API 介绍文档中, SDK 缓存加密默认是 AES 加密方式,如果需要使用其它加密方式则需要通过缓存加密插件进行自定义。
3.1. 接口介绍
在 SDK 初始化时调用 registerStorePlugin 接口注册自定义加密插件即可开启。
StorePlugin 类介绍:
方法名 | 描述 |
---|---|
setString(String key, String value) | 存储 String 类型数据,需要实现对应的存储逻辑 |
getString(String key) | 根据指定 key 获取 String 类型数据,需实现获取逻辑 |
setBool(String key, boolean value) | 存储 bool 类型数据,需要实现对应的存储逻辑 |
getBool(String key) | 根据指定 key 获取 bool 类型数据,需实现获取逻辑 |
setInteger(String key, int value) | 存储 int 类型数据,需要实现对应的存储逻辑 |
getInteger(String key) | 根据指定 key 获取 int 类型数据,需实现获取逻辑 |
setFloat(String key, float value) | 存储 float 类型数据,需要实现对应的存储逻辑 |
getFloat(String key) | 根据指定 key 获取 float 类型数据,需实现获取逻辑 |
setLong(String key, long value) | 存储 long 类型数据,需要实现对应的存储逻辑 |
getLong(String key) | 根据指定 key 获取 long 类型数据,需实现获取逻辑 |
remove(String key) | 删除指定 key,需实现对应逻辑 |
type() | 属性插件名称,需实现对应逻辑 |
isExists(String key) | 判断指定 key 是否存在存储文件中,需实现对应逻辑 |
在自定义缓存加密存储插件时,需要由开发者来实现对应类型数据的存储与获取。
3.2. 使用示例
在下面的示例中,使用自定义加密插件实现国密算法加密。
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;
}
}
注:本文档内容为神策产品使用和技术细节说明文档,不包含适销类条款;具体企业采购产品和技术服务内容,以商业采购合同为准。