Shiply Android 远程资源 SDK 集成
一、隐私安全说明
Shiply 资源发布 Android SDK
版本:1.8.19-RC02
更新时间:2024年6月18日
SDK介绍:为移动开发者提供专业的资源分发能力,帮助开发者动态下载远程资源文件。
服务提供方:深圳市腾讯计算机系统有限公司
接入指引:《Shiply资源发布SDK接入指引》
隐私保护规则:《Shiply资源发布SDK个人信息保护规则》
合规使用指南:[《Shiply资源SDK合规使用指南》](/document/remote-resource/compliance/
二、接入SDK
1. 在项目根目录下的 build.gradle
中配置 Maven 仓库
allprojects {
repositories {
maven { url "https://tencent-tds-maven.pkg.coding.net/repository/shiply/repo" }
}
}
2. 在主 module 的 build.gradle
中添加运行时 SDK
dependencies {
implementation "com.tencent.shiply:reshub-sdk:1.8.19-RC02" // ResHub核心SDK
implementation "com.tencent.shiply:reshub-net:1.8.19-RC02" // 可选,默认网络下载实现
implementation "com.tencent.shiply:reshub-report:1.8.19-RC02" // 可选,默认上报SDK
implementation "com.tencent.shiply:reshub-patch-sdk:1.8.19-RC02" // 可选,差量更新SDK
}
3. 初始化 SDK,建议在 Application.onCreate
方法中初始化
// 构造初始化参数 ,建议将 ResHubParams.multiProcessMode 设置为true
ResHubParams params = new ResHubParams(
"1.0.0", // 应用版本号
"your_user_id" // 用户ID
);
// 初始化 SDK
ResHubCenter.INSTANCE.init(
getApplication(),
params,
new ResHubDefaultDownloadImpl(), // 默认下载器实现
new HttpsURLConnectionNetwork(this), // 默认网络请求实现
new ResHubDefaultReportImpl() // 默认数据上报实现
);
// 注入差量包处理器
List<AbsProcessor> processorList = new ArrayList<>();
processorList.add(new TryPatchProcessor());
ResHubCenter.INSTANCE.injectProcessor(processorList);
// 设置日志代理,建议参考AbsLog实现,对接到业务方自己的日志接口
ResHubCenter.INSTANCE.setLogDelegate(new SystemLog());
// 获取 SDK 实例
IResHub reshub = ResHubCenter.INSTANCE.getResHub("${appId}", "${appKey}",
TargetType.AndroidApp, ResHubCenter.ENV_ONLINE);
ResHubParams各参数字段说明:
data class ResHubParams @JvmOverloads constructor (
/**
* 宿主应用版本号
*
* 格式规范参考:https://semver.org/lang/zh-CN/
*/
val appVersion: String,
/**
* 设备标识,业务方根据自己的策略注入(推荐使用 qimei36)
*
* 注意: 取值不能为空
*/
val deviceId: String,
/**
* 是否是debug测试包,为true时可拉取到未发布的资源
*/
val isRdmTest: Boolean = false,
/**
* 存放内置资源的根目录
*/
val localPresetPath: String = ResHubCenter.LOCAL_PRESET_PATH_DEFAULT,
/**
* onComplete回调是否在主线程进程
*
* (默认是,方便使用方进行UI相关处理)
*/
val completeCallbackOnMainThread: Boolean = true,
/**
* onProgress回调是否要求在主线程进行
*
* (默认为否,该回调可能频率较高)
*/
val progressCallbackOnMainThread: Boolean = false,
/**
* 存储路径额外前缀
*
* 用于隔离存储的文件路径,一般不用改
* (应用举例:比如想隔离32和64位的资源,可以添加个 64bit 的路径)
*/
val configStoreSuffix: String = ResHubCenter.CONFIG_STORE_SUFFIX_DEFAULT,
/**
* 自定义配置请求规则参数,影响配置下发的规则匹配
*/
val variantMap: Map<String, String> = mapOf(),
/**
* 全量配置自动更新策略
*
* 取值参考@RDeliverySetting.UpdateStrategy, 可设置为多个值(对值进行或运算)
*
* 常用可选策略:
* 启动时拉取全量配置: UpdateStrategy.START_UP
* 按照固定时间间隔,周期拉取全量配置: UpdateStrategy.PERIODIC
* App切换后台超过30秒,再切回前台时拉取全量配置: UpdateStrategy.HOT_RELOAD
* 断网重连时拉取全量配置: UpdateStrategy.NETWORK_RECONNECT
*
* 默认为: 启动时/定时3小时后更新
*/
val configUpdateStrategy: Int = defaultConfigUpdateStrategy,
/**
* 全量配置定时自动更新时的时间间隔,单位为秒
*
* 注意: 更新策略包括 RDeliverySetting.UpdateStrategy.PERIODIC 才有效
* 默认10800秒(3小时)
*/
val configUpdateInterval: Int = defaultConfigUpdateInterval,
/**
* 是否启用ResHub多进程模式
*
* 开启后:
* 1. 默认会使用MMKV(的多进程模式)来保存配置,不同进程同一个ResHub的资源和配置保证是同步的。
* 2. 不同进程对同一个ResHub的同一资源的文件操作(下载/解压/解密/Patch)会使用文件锁保证互斥。
*
* 注意: ResHub的多进程模式默认依赖"MMKV"(来完成多进程配置同步),所以:
* 1. 如果开启了多进程模式
* 必须在初始化ResHubCenter之前,确保已经自行调用了"MMKV.initialize()"以完成它的全局初始化。
* 2. 如果未开启多进程模式(默认不开启),则无需关心。
* ResHub默认会使用SharedPreferences存储配置。(见DefaultConfigStorageDelegateImpl)
*/
val multiProcessMode: Boolean = false,
/**
* 是否是64位设备;注入该参数后,才可以在平台上使用系统内置的'是否64位'判断条件
*/
val is64Bit: Boolean? = null,
/**
* 是否要记录配置key最近一次发送远程网络请求时的时间戳,回包成功时记录
*/
val enableRecordLastRequestTime: Boolean? = null,
/**
* 是否懒加载内部的配置信息,用来优化性能,默认不开启
*/
val enableLazyLoadInnerConfig: Boolean = false,
/**
* 当pullTarget为[TargetType.AndroidApp]时,是否要额外拉取项目级别的配置信息
*/
val fetchProjectWhenAppOnly: Boolean = false,
/**
* 是否跳过内置资源复制到磁盘后文件完整性校验操作,默认不跳过
*/
val skipIntegrityCheckAfterPresetResCopy: Boolean = false
)
/**
* 默认的全量配置自动更新策略
*/
val defaultConfigUpdateStrategy =
// 启动时拉取全量配置
RDeliverySetting.UpdateStrategy.START_UP.value or
// 按照固定时间间隔,周期拉取全量配置
RDeliverySetting.UpdateStrategy.PERIODIC.value
/**
* 默认的全量配置定时自动更新时间间隔: 10800秒(3小时)
*
* 更新策略包括 RDeliverySetting.UpdateStrategy.PERIODIC 才有效
*/
const val defaultConfigUpdateInterval = 10800
三、使用SDK
1. 异步获取远端资源
// 拉取资源(并锁定特定版本)
reshub.load("your_res_key", callback)
// 拉取最新资源
reshub.loadLatest("your_res_key", callback)
// 批量拉取资源(并锁定特定版本)
reshub.batchLoad(setOf("your_res_key1", "your_res_key2"), batchCallback)
// 批量拉取最新资源
reshub.batchLoadLatest(setOf("your_res_key1", "your_res_key2"), batchCallback)
2. 同步获取本地资源
// 获取本地资源(并锁定特定版本)
IRes res = = reshub.get("testResId1")
// 获取本地最新资源
IRes res = reshub.getLatest("testResId1")
四、QA
4.1 锁定版本是什么意思?
调用load/get接口都会锁定版本,锁定是指同一个进程生命周期内多次调用load返回的版本号不会变化,即使远端发布了更高的版本。
4.2 下载后的文件如何保持原来的后缀?
sdk默认会给下载的文件添加.res后缀,也支持设置使用原文件后缀:在初始化的时候设置ResHubCenter.downloadStorageDelegate = OriginDownloadStorageDelegateImpl()。
4.3 如果资源有更新,本地之前下载的产物是否会被删除?
sdk更新新版本资源后,会将旧版本资源标记为待删除,下次进程启动时再执行删除。
4.4 ResHubParams.isRdmTest 有什么作用?
表示当前是debug包,与前端资源发布任务体验号码设置中的内部测试包规则配合使用。
4.5 反复调用ResHubCenter.getResHub是否会返回多个实例?
实例是根据 appid+env隔离的,appid 和 env不变时,返回的是同一个实例。
4.6 如果一个资源key下的所有任务都被删除,端上loadLatest回调返回的是什么?
回调中isSuccess是false, result会返回本地缓存的制品。
4.7 loadLatest回调返回的isSuccess是false时,怎么区分是请求失败了才false,还是因为资源下的任务都删除了才false?
可以通过error: IResLoadError 区分,errCode是1003,errMsg是「config result empty」时表示请求成功,但是任务不匹配。
errCode错误码:
const val SUCCESS = 0
// 配置拉取相关
const val FETCH_CONFIG_BAD_RESULT_ERROR = 1003 // 接口返回错误(如ret不为0),对应的errMsg包括:「config not found」:表示远端不存在对应的资源key;「config result empty」:表示远端资源key存在,但是任务不匹配;「SocketTimeoutException」: 表示网络异常导致配置拉取失败;
const val FETCH_CONFIG_INVALID_RESULT_ERROR = 1005 // 接口返回数据校验失败
const val FETCH_CONFIG_PARAMETER_ERROR = 1006 // 接口入参错误
const val FETCH_CONFIG_EMPTY_RESOURCE_ERROR = 1007 // 接口返回资源为空
const val FETCH_CONFIG_REDIS_ERROR = 1008 // 接口返回访问Redis资源失败
const val FETCH_CONFIG_INVALID_RESID_ERROR = 1009 // 请求的资源ID不合法
const val FETCH_CONFIG_CDN_OVERLOAD_ERROR = 1010 // CDN高负载状态,放弃下载
// 完整资源下载相关
const val DOWNLOAD_HTTP_ERROR = 2001 // 全量文件下载HTTP错误
const val DOWNLOAD_NETWORK_ERROR = 2002 // 全量文件下载其他网络错误
const val DOWNLOAD_NET_LIMIT_ERROR = 2003 // 全量文件下载网络状态限制
const val DOWNLOAD_NO_ENOUGH_SPACE_ERROR = 2004 // 全量文件下载空间不足
const val DOWNLOAD_FILE_OPERATE_ERROR = 2005 // 全量文件下载文件操作错误,文件(创建/移动/重命名)失败
const val DOWNLOAD_MD5_CHECK_ERROR = 2006 // 全量文件MD5校验失败
const val DOWNLOAD_DECRYPT_ERROR = 2007 // 全量文件解密失败
// 按照压缩方式下发的资源下载相关
const val COMPRESSED_DOWNLOAD_HTTP_ERROR = 2101 // 按照压缩方式下发的资源下载HTTP错误
const val COMPRESSED_DOWNLOAD_NETWORK_ERROR = 2102 // 按照压缩方式下发的资源下载其他网络错误
const val COMPRESSED_DOWNLOAD_NET_LIMIT_ERROR = 2103 // 按照压缩方式下发的资源下载网络状态限制
const val COMPRESSED_DOWNLOAD_NO_ENOUGH_SPACE_ERROR = 2104 // 按照压缩方式下发的资源下载空间不足
const val COMPRESSED_DOWNLOAD_FILE_OPERATE_ERROR = 2105 // 按照压缩方式下发的资源下载文件操作错误,文件(创建/移动/重命名)失败
const val COMPRESSED_DOWNLOAD_MD5_CHECK_ERROR = 2106 // 按照压缩方式下发的资源MD5校验失败
const val COMPRESSED_DOWNLOAD_DECRYPT_ERROR = 2107 // 按照压缩方式下发的资源解密失败
// 解压相关
const val UNZIP_ERROR = 3001 // 解压失败
const val UNZIP_MD5_CHECK_ERROR = 3002 // 解压后文件校验失败
const val COMP_ORIG_FILE_UNZIP_ERROR = 3101 // 以压缩方式下发的资源解压失败
const val COMP_ORIG_FILE_UNZIP_MD5_CHECK_ERROR = 3102 // 以压缩方式下发的资源解压后文件校验失败
// 配置更新相关
const val UPDATE_CONFIG_ERROR = 4001 // 更新本地资源配置时发生异常
const val READ_LOCAL_RES_ERROR = 4002 // 读取到的本地资源是关闭状态
// 差量下载相关
const val PATCH_HTTP_ERROR = 5001 // 差量文件下载HTTP错误
const val PATCH_NETWORK_ERROR = 5002 // 差量文件下载其他网络错误
const val PATCH_NET_LIMIT_ERROR = 5003 // 差量文件下载网络状态限制
const val PATCH_NO_ENOUGH_SPACE_ERROR = 5004 // 差量文件下载空间不足
const val PATCH_FILE_OPERATE_ERROR = 5005 // 差量文件下载文件操作错误
const val PATCH_MD5_CHECK_ERROR = 5006 // 差量文件MD5校验失败
const val PATCH_APPLY_ERROR = 5007 // 差量文件Patch失败
const val PATCH_TOTAL_MD5_CHECK_ERROR = 5008 // Patch后文件MD5校验失败