# 集成要求
# 合规说明
请注意,在贵司的App中集成同盾提供的SDK产品时:
1.1 根据《网络安全法》《电信条例》《电信和互联网用户个人信息保护规定》等相关法律法规要求及监管实践中的标准,在贵司的最终用户首次启动App并在贵司开始采集信息之前,贵司应以交互界面或设计(如隐私政策弹窗等)向最终用户完整告知收集、使用、与第三方共享最终用户个人信息的目的、方式和范围,并征得最终用户的明示同意。
1.2 为向贵司提供业务安全和风控服务,同盾SDK将采集、处理、使用用户的手机终端唯一标志信息(IMEI/IDFA)、Android ID、IMSI、MEID、MAC 地址、SIM 卡序列号、设备序列号、设备类型、设备型号、系统类型、地理位置、登录 IP 地址等设备信息。为确保贵司使用相关服务的合规性,前述隐私政策应涵盖对同盾SDK提供服务并采集、处理、使用相关信息的授权,以下条款内容供贵司参考,具体表述可由贵司根据贵司隐私协议的整体框架和内容自行确定:
同盾SDK:为了业务安全和风控,我司使用了同盾 SDK,该 SDK 需要获取您的手机终端唯一标志信息(IMEI/IDFA)、Android ID、IMSI、MEID、MAC 地址、SIM卡序列号、设备序列号、设备类型、设备型号、系统类型、地理位置、登录 IP 地址、应用程序列表、运行中进程信息、传感器(光传感器、重力传感器、磁场传感器、加速度传感器、陀螺仪传感器)相关设备信息,用于设备欺诈风险识别。 |
同盾隐私协议:https://www.tongdun.cn/other/privacy/id=1 (opens new window)
# 环境要求
条目 | 说明 |
---|---|
兼容版本 | 支持主流机型,Android 4.4及以上系统 |
支持架构 | armeabi-v7a, arm64-v8a, x86 |
# 集成步骤
# 集成SDK
注意: 已经在⼯程libs中集成SDK的客户,在升级新版本SDK时,请先删除旧版 SDK,如有旧版本集成的so库也需要同时删除。
SDK接入示例代码(sample): https://github.com/trustdecision/mobrisk-android-sample (opens new window)
# 添加仓库
首先, 请在项目根目录的 build.gradle
加入maven库的配置
allprojects {
repositories {
...
mavenCentral()
}
}
如果您的 Gradle 版本是 7 或更高版本,请将这些行添加到您的 settings.gradle
repositories {
...
mavenCentral()
}
# 添加依赖
在项目的 app/build.gradle
中加上依赖,如图:
dependencies {
// 设备指纹
implementation 'com.trustdecision.android:mobrisk:4.2.4.2'
}
如果遇到合规性问题,我们也可以在依赖阶段排除相关模块的采集,如下:
dependencies {
// 设备指纹
implementation('com.trustdecision.android:mobrisk:4.2.4.2'){
// 移除后sdk不获取安装包列表
exclude group: 'com.trustdecision.android', module: 'packagelist'
// 移除后sdk不会收集READ_PHONE_STATE相关信息
exclude group: 'com.trustdecision.android', module: 'readphone'
}
}
# ABI类型
SDK目前支持 armeabi-v7a、arm64-v8a、x86三种ABI类型,建议接入方在 app/build.gradle
文件内添加 abiFilters
配置选择所需要的架构类型,示例
defaultConfig {
........
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
}
具体架构,请以您自己需要支持的架构为准!
# 文件配置 AndroidManifest.xml
在应⽤module下的 AndroidManifest.xml ⽂件中声明以下权限
<manifest>
<!--必选权限-->
<!--网络通信-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--获取网络状态-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--获取WIFI状态-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--以下权限是可选权限,不声明此部分权限将放弃部分设备信息的采集,对数据分析及设备指纹的精准度有一定影响-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- Android11及以上获取安装包列表需要该权限,采集安装包列表涉及到⻛险合规,是否需要该权限业务⽅⾃⾏选
择 -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
</manifest>
动态申请权限: Android 6.0 及以上版本需要动态申请权限,动态申请权限代码必须放在初始化 SDK 前,代码示例如下:
//以下权限不是必须申请. 可根据业务情况选择性权限申请
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.READ_PHONE_STATE
}, 100);
}
# SDK 的使用方法
注意事项
确保在用户同意隐私协议后,再进行SDK初始化,避免出现用户未同意隐私协议就进行SDK初始化采集,引发合规风险。
SDK配置
TD的sdk使用TDRisk.Builder方法对sdk初始参数进行配置设置,并将设置结果作为初始化参数提供给sdk初始化方法initWithOptions()使用。
TDRisk.Builder必须参数配置如下
配置 key | 定义 | 说明 | 示例代码 |
---|---|---|---|
partner | 合作方编码 | 同盾的合作方编码,请联系同盾运营获取 | builder.partnerCode("partner") |
appKey | 应用标识 | 同盾生成的应用标识,和app绑定,用于校验app的有效性,请联系同盾运营获取 appkey创建需要用户提供应用包名、小写的sha256 签名。 ⚠️不同应用的包名签名不要使用相同的值 | builder.appKey("appKey") |
appName | 应用名称 | 同盾平台注册的应用名称,请联系同盾运营获取 | builder.appName("appName") |
country | 国家地区 | TDRisk.COUNTRY_US 北美 TDRisk.COUNTRY_FRA 欧洲 TDRisk.COUNTRY_SG 新加坡 TDRisk.COUNTRY_CN 中国 | builder.country(TDRisk.COUNTRY_CN) |
我们也提供了可选参数配置,详情可以见附表(初始化配置可选参数列表)
SDK使用方法示例代码:
在应用启动的时候,比如在应用的 application 的 onCreate 方法中(Android 6.0 及以上版本应确保已经申请过权限)调用以下方法:
# 方式一(推荐的方式): 通过getBlackBox() 方法获取blackbox
// SDK初始化配置
TDRisk.Builder builder = new TDRisk.Builder()
/*************************** 必传 ***************************/
.partnerCode("demo") // 同盾的合作⽅编码,如demo,请填写⾃身的合作⽅编码
.appName("appName") // 同盾平台注册的应⽤名称,请联系同盾运营获取
.appKey("appKey") // 配置AppKey,请联系同盾运营获取
.country(TDRisk.COUNTRY_CN); // 国家地区参数,如cn、sg、us、fra
/*************************** 必传 ***************************/
// 初始化态势感知SDK
if(⽤户同意隐私协议){
TDRisk.initWithOptions(getApplicationContext(), builder);
}
⚠️注意事项:必须保证 initWithOptions
后 调用 getBlackBox
。
在业务需要的时候获取blackbox。
String blackbox = TDRisk.getBlackBox();
# 方式二: 通过回调方法callback,在onEvent中获取blackbox
// SDK初始化配置
TDRisk.Builder builder = new TDRisk.Builder()
/*************************** 必传 ***************************/
.partnerCode("demo") // 同盾的合作⽅编码,如demo,请填写⾃身的合作⽅编码
.appName("appName") // 同盾平台注册的应⽤名称,请联系同盾运营获取
.appKey("appKey") // 配置AppKey,请联系同盾运营获取
.country(TDRisk.COUNTRY_CN) // 国家地区参数,如cn、sg、us、fra
/*************************** 必传 ***************************/
// 回调结果
.callback(new TDRiskCallback() {
@Override
public void onEvent(String blackbox) {
// 此处回调在⼦线程
// ⽹络正常的情况下,会在200-300ms内返回结果。
// ⽹络异常的情况下,会在超时时间(默认最长15s)后返回。
// 请在下⽅添加您对blackbox的处理逻辑
Log.i("TDRiskDemo", "blackbox: " + blackbox);
}
});
// 初始化态势感知SDK
if(⽤户同意隐私协议){
TDRisk.initWithOptions(getApplicationContext(), builder);
}
# 两种方式的差异
- 方式一是同步获取blackbox,优点是可以保证会获取到blackbox(一些情况下为降级blackbox),如果在主线程调用 getBlackBox需要注意耗时问题。
- 方式二是异步获取blackbox,优点是不会阻塞进程,无耗时问题,缺点是调用getBlackBox方式时初始化尚未完成,无法获得blackbox。需要注意 回调结果不是在主线程,禁止在回调中操作UI。
SDK上报数据成功后,正常情况下,getBlackbox()返回的结果长度为26位字符串. 如: rWPGX1678775227I9NCwcuVJCb
。
异常情况下,长度为5000字符左右. 详情可查看总览 (opens new window)
执行initWithOptions初始化成功会在 logcat中打印以下log:
TD_JAVA: Tongdun sdk load success
TD_JAVA: Tongdun sdk init success
# 获取SDK版本号
示例代码
// 获取SDK版本号
TDRisk.getSDKVersion()
# 其他说明
混淆打包 如果开发者需要使用 proguard 进行混淆打包,请在 proguard 配置文件添加如下代码:
#TONGDUN
-keep class cn.tongdun.**{*;}
# 初始化配置可选参数列表
配置 key | 定义 | 说明 | 示例代码 |
---|---|---|---|
setHttpTimeout | SDK超时时间配置(单位:毫秒) | SDK初始化采集上报后,网络请求回调的超时时间,SDK默认为15 * 1000ms | builder.httpTimeout(5000) |
callback | SDK异步回调配置 | SDK初始化采集上报后,根据网络请求结果返回blackbox。请求成功:返回非降级blackbox 请求失败:返回降级blackbox | builder.callback() |
collectLevel | 降级blackbox采集字段长度配置 | 降级的blackbox会较长。通过此配置可控制降级的blackbox长度 1.TDRisk.COLLECT_LEVEL_L(默认值, 降级长度为5000字符左右) 2.TDRisk.COLLECT_LEVEL_M(降级长度为2000字符左右) | builder.collectLevel(TDRisk.COLLECT_LEVEL_L) |
blackBoxMaxSize | blackbox 最大长度 | 默认长度为 Integer.MAX_VALUE, 根据实际设备情况会有上浮 | builder.blackBoxMaxSize(3000) |
customProcessName | 自定义进程名 | 更改进程的名称 | builder.customProcessName("td") |
forceTLSVersion | https是否强制使用TLS-v1.1版本 | 默认不强制,开发者根据具体情况进行对应设置 | builder.forceTLSVersion(true) |
disableDebugger | 是否允许调试 | 集成SDK后App默认允许调试,开发者根据具体情况进行对应设置 | builder.disableDebugger() |
disableRunningTasks | 是否允许获取正在运行的任务 | 默认采集运行任务, 可以调用此方法进行关闭 | builder.disableRunningTasks() |
disableGPS | 不采集GPS相关信息 | 如果需要不采集定位相关信息,可通过该方法取消定位相关信息的采集。配置该选项后,应用拥有定位权限,SDK也不会去采集定位相关信息。 | builder.disableGPS() |
disableSensor | 不采集传感器信息 | 如果需要不采集传感器相关信息,可通过该方法取消采集相关信息 | builder.disableSensor() |
disableReadPhone | 不采集READ_PHONE_STATE相关信息 | 默认采集需要READ_PHONE_STATE权限的信息, 可以调用此方法进行关闭 | builder.disableReadPhone() |
disableInstallPackageList | 不采集安装包列表 | 默认采集安装包列表, 可以调用此方法进行关闭 | builder.disableInstallPackageList() |
# FAQ
Q1:为什么获取的 blackbox 字段比较长?
A1:正常情况下 blackbox 长度为 26字节,但是由于网络情况较差或者函数 TDRisk.initWithOptions()和 TDRisk.getBlackBox()调用间隔时间较短时,blackbox 会附带一些设备信息长度将增大到 1500-3000 字节。
Q2:为什么事件中部分信息为空?
A2:可能由于从 SDK 初始化到获取设备数据间隔时间过短,造成设备信息获取失败。切勿初始化之后立即获取设备信息。
Q3:为何部分事件的真实 IP 是空的?
A3:当 SDK 上传设备信息失败(超时或者网络被屏蔽)时,将自动转为离线模式,此种情况下同盾无法获取真实 IP。
Q4:为何在某些架构的手机上 app 会崩溃?
A4:SDK 支持多种架构,如果 app 因此崩溃,可能是对应架构的 so 目录没有导入对应的 so 文件,请注意你的 ndk 支持的架构。