Shiply Harmony 远程配置 SDK 集成
一、隐私安全说明
SDK 名称:Shiply Harmony SDK
版本:1.1.17
包名:shiply
更新时间:2025-09-04
MD5值:837a76c44a9fd1741f2ebde4f5f47bcd
SDK介绍:为移动开发者提供专业的资源分发能力,帮助开发者动态下载远程资源文件。
服务提供方:深圳市腾讯计算机系统有限公司
接入指引:《Shiply配置发布SDK接入指引》
隐私保护规则:《Shiply配置发布SDK个人信息保护规则》
合规使用指南:《Shiply配置SDK合规使用指南》
前置概念:接入前请先阅读 通用概念,了解各平台共用的
appId/appKey/userId/deviceId/logicEnvironment/custom_properties等核心概念,避免跨平台混淆。
二、Harmony SDK 简介
Shiply Harmony 版本 SDK,支持在鸿蒙系统上进行远程配置下发、远程资源下发。
支持丰富的下发条件(允许自定义条件)
支持灰度发布、全量发布、定时发布
支持测试、验证、发布审批等流程
差量省流技术(iOS/Android 支持,鸿蒙版本后续支持)
三、使用配置下发 SDK
请先参考:集成 ShiplyPro Harmony SDK 完成 SDK 集成
初始化 SDK
import { RDelivery, RDeliveryConfig, RDeliveryData } from '@ohos/shiply'
let config: RDeliveryConfig = new RDeliveryConfig();
config.logicEnvironment = "";
// 请替换成你在 Shiply 平台注册的产品 app id 和 app key
config.appId = "xxx";
config.appKey = "xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx";
// 用户账号
config.userId = "your_app_user_id";
config.deviceId = "your_app_device_id";
config.language = "en";
config.appVersion = "1.0.0";
config.osVersion = "16.2";
config.bundleId = "com.tencent.rdelivery.cpp";
let logOutput = (level: number, log: string) => {
hilog.info(0x0000, 'ShiplyLog', '%{public}s', log);
};
RDelivery.ExpectOnLocalDataInitComplete((error_code: number) => {
hilog.info(0x0000, 'ShiplyLog', 'ExpectOnLocalDataInitComplete error_code: %{public}s', error_code);
});
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;
RDelivery.SdkStart(filesDir, config, logOutput);
拉取全量配置
/// 请求远端全量配置
/// - Parameters:
/// - custom_properties: 自定义属性
/// - callback: 回调
RDelivery.RequestFullRemoteData(custom_properties, (error_code: number, configList: Array<RDeliveryData>) => {
})
拉取单个场景下配置
/// 按场景ID请求远端全量配置
/// - Parameters:
/// - scene_id: 场景ID(Shiply网页端创建获取)
/// - custom_properties: 自定义属性
/// - callback: 回调
RDelivery.RequestBatchRemoteDataByScene(scene_id, custom_properties, (error_code: number, configList: Array<RDeliveryData>) => {
})
拉取多个场景下配置
/// 按多个场景ID请求远端全量配置
/// - Parameters:
/// - scene_ids: 场景ID列表(Shiply网页端创建获取)
/// - custom_properties: 自定义属性
/// - callback: 回调
let scene_ids = [100780, 100782, 100699]
RDelivery.RequestBatchRemoteDataByScenes(scene_ids, custom_properties, (error_code: number, configList: Array<RDeliveryData>) => {
})
拉取单个配置
/// 按配置Key请求远程配置信息
/// - Parameters:
/// - key: 配置Key
/// - custom_properties: 自定义属性
/// - callback: 回调
RDelivery.RequestSingleRemoteDataByKey(key, custom_properties, (error_code: number, configList: Array<RDeliveryData>) => {
})
拉取多个配置
/// 按多个配置Key请求远程配置信息
/// - Parameters:
/// - keys: 配置Key列表
/// - custom_properties: 自定义属性
/// - callback: 回调
let keys = ["test_active_user_report", "test_cpp_report"];
RDelivery.RequestRemoteDataByKeys(keys, custom_properties, (error_code: number) => {
})
同步读取单个配置
/// 同步读取单个配置
/// - Parameter key: 配置Key
const data: RDeliveryData = RDelivery.SyncGetRDeliveryDataByKey("mellow_test");
异步读取单个配置
/// 异步读取单个配置
/// - Parameters:
/// - key: 配置Key
/// - callback: 回调
let callback = (errorCode: number, data: RDeliveryData) => {
};
RDelivery.GetRDeliveryDataByKey("mellow_test", callback);
同步读取所有配置
/// 同步读取本地所有配置信息
const configMap: Map<string, RDeliveryData> = RDelivery.SyncGetRDeliveryAllDataMap();
configMap.forEach((item, key) => {
if (item.value) {
hilog.info(0x0000, 'ShiplyLog', 'sync get key: %{public}s value: %{public}s', key, item.value);
}
});
异步读取所有配置
/// 异步读取所有配置信息
/// - Parameter callback: 回调
let callback = (errorCode: number, configMap: Map<string, RDeliveryData>) => {
for (let [key, data] of Object.entries(configMap)) {
hilog.info(0x0000, 'ShiplyLog', 'async get key: %{public}s values: %{public}s', key, data.value);
}
};
RDelivery.GetRDeliveryAllDataMap(callback);
同步读取所有开关
/// 同步读取本地所有开关信息
const configMap: Map<string, RDeliveryData> = RDelivery.SyncGetRDeliveryAllDataMap();
configMap.forEach((item, key) => {
if (item.value) {
hilog.info(0x0000, 'ShiplyLog', 'sync get key: %{public}s value: %{public}s', key, item.value);
}
});
SDK 版本号
const version = RDelivery.SdkVersion();
异步读取所有开关
/// 异步读取所有配置信息
/// - Parameter callback: 回调
let callback = (errorCode: number, configMap: Map<string, RDeliveryData>) => {
configMap.forEach((item, key) => {
hilog.info(0x0000, 'ShiplyLog', 'async get key: %{public}s value: %{public}s', key, item.value);
});
};
RDelivery.GetRDeliveryAllDataMap(callback);
切换账号
注意
切换账号后,使用方需要主动调用拉取配置!!!
/// 切换用户
/// - Parameters:
/// - user_id: 用户Id
/// - callback: 回调
let userId = "another_user_2"
const ok = RDelivery.SwitchUserId(userId, (error_code: number) => {
// error_code=0 成功,返回 false 表示未初始化
})
if (!ok) {
// 未初始化,需先初始化 SDK
}
let custom_properties: CustomProperties = {age: 100};
RDelivery.RequestFullRemoteData(custom_properties, (error_code: number, configList: Array<RDeliveryData>) => {
})
切换环境
注意
切换环境后,使用方需要主动调用拉取配置!!!
/// 切换环境
/// - Parameters:
/// - env: 环境ID("" 空字符串为正式环境,"1" 为默认测试环境,其他自定义环境请前往Shiply网页端获取ID)
/// - callback: 回调
let env = "1"
const ok = RDelivery.SwitchEnvironment(env, (error_code: number) => {
// error_code=0 成功,返回 false 表示未初始化
})
let custom_properties: CustomProperties = {age: 100};
RDelivery.RequestFullRemoteData(custom_properties, (error_code: number) => {
})
四、枚举值参考
RDUpdateStrategy(更新策略,位掩码)
| 值 | 名称 | 说明 |
|---|---|---|
| 0 | None | 不自动更新 |
| 1 | SdkInit | SDK 初始化时更新 |
| 2 | Schedual | 定时更新(源码拼写为 Schedual,非标准 Scheduled) |
| 4 | EnterForceground | 热启动更新(退后台超 30s 切回前台) |
| 8 | NetworkReconnect | 断网重连时更新 |
RDValueType(配置值类型)
| 值 | 名称 | 说明 |
|---|---|---|
| 0 | String | 字符串 |
| 1 | Json | JSON |
| 2 | Int | 整数 |
| 3 | Bool | 布尔 |
| 4 | Float | 浮点数 |
| 5 | List | 列表 |
| 6 | Map | 字典 |
RDSwitchState(开关状态)
| 值 | 名称 | 说明 |
|---|---|---|
| 0 | NoSwitch | 非开关 |
| 1 | On | 开 |
| 2 | Off | 关 |
五、注意事项
SdkStart返回值不可当实例用:返回bigint(内部 C++ 指针),外部无需持有;所有后续 API 都是RDelivery的静态方法,用RDelivery.<method>调用,不要instance.<method>。- dbPath 必填:
SdkStart第一个参数是 MMKV 存储路径,通常传context.filesDir。 - logger 传 null:可走无日志模式,但建议传入业务日志回调便于排查。
- logicEnvironment 是字符串:
""=正式,"1"=测试,不要传数字类型。 - SdkStart 内部默认 sdk_version:封装层内部固定填
"0.1.1",调试场景如需对齐版本号注意此点。 - 底层是 C++:复杂场景参考 C++ 核心 API 文档。
- 无 remove/unregister 方法:
ExpectOnDataChange、ExpectOnDataDelete、ExpectOnLocalDataInitComplete是 set-only 操作。再次调用会覆盖之前的回调,而非追加。 - 无线程控制:RDelivery 不提供任何线程控制。所有回调经 NAPI TSFN 内部派发,不要假设回调在特定线程上执行。
Schedual拼写:源码中枚举值RDUpdateStrategy.Schedual为Schedual(非标准Scheduled),接入时使用RDUpdateStrategy.Schedual以匹配源码。
RDeliveryConfig 参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
appId / appKey | string | 是 | 应用凭证 |
userId | string | 是 | 用户 ID(guid) |
deviceId | string | 是 | 设备 ID(qimei) |
appVersion | string | 是 | App 版本 |
osVersion | string | 是 | 系统版本 |
bundleId | string | 是 | 包名 |
logicEnvironment | string | 否 | 逻辑环境:""=正式,"1"=测试,其他=环境数字 ID |
language | string | 否 | 语言 |
devModel / devManufacturer | string | 否 | 型号/厂商 |
updateStrategy | number | 否 | 更新策略位掩码 |
updateInterval | number | 否 | 定时更新间隔(秒),默认 4×3600 |
skip_mmkv_init | boolean | 否 | 不初始化 MMKV(宿主已初始化),默认 false |
is_debugPackage | boolean | 否 | 是否调试包 |
target | RDPullTarget | 否 | 拉取目标:Project=0(按项目),App=1(按应用) |
custom_properties | Record<string, string> | 否 | 自定义属性 |
fixed_after_hit_keys | string[] | 否 | 命中后不再更新的配置 key 集合 |
custom_server_url | string | 否 | 独立部署域名 |
六、事件监听
通过 RDelivery 静态方法注册回调,配置变更/拉取结果经 NAPI 回调到 ArkTS:
// 数据变更监听
RDelivery.ExpectOnDataChange((key, old_data, new_data) => {
// key 对应配置发生变更,old_data/new_data 为变更前后的数据
});
// 数据删除监听
RDelivery.ExpectOnDataDelete((key) => {
// key 对应配置被删除
});
这些回调是 set-only 操作,再次调用会覆盖之前的回调,而非追加。
七、文档与实现差异
- AKI 依赖已移除:使用指南文档仍引用 AKI,但 SDK 自 v2.2.1 起已移除 AKI,改用原生 NAPI 桥接。不要按旧文档引入 AKI。
- 版本:源码 oh-package.json5 为 2.2.19,cpp-sdk 1.2.15。