XuqmGroup-RNSDK/docs/SDK-API参考.md

432 行
12 KiB
Markdown

# XuqmGroup RN SDK API 参考
> 版本v0.4.0(待发布) · 最后更新 2026-06-15
> 包名:`@xuqm/rn-common` · `@xuqm/rn-update` · `@xuqm/rn-push` · `@xuqm/rn-im` · `@xuqm/rn-license`
> 设计规范:`XuqmGroup-Docs/design/06-sdk-cross-platform-spec.md`
---
## 1. XuqmSDKcommon
> `import { XuqmSDK } from '@xuqm/rn-common'`
SDK 核心模块。负责从平台拉取服务配置,并作为所有子 SDK 用户状态的统一分发中心。
### 类型定义
```ts
interface XuqmInitOptions {
appKey: string // 应用标识(从租户平台获取)
platformUrl?: string // 平台地址;不传则使用内置默认公有平台地址
debug?: boolean
}
interface XuqmConfig {
appKey: string
apiUrl: string // 通用 API 地址
imWsUrl: string // IM WebSocket 地址
fileServiceUrl: string // 文件服务地址
licenseUrl: string // License 服务地址
debug: boolean
imEnabled: boolean // 是否开通 IM 服务
pushEnabled: boolean // 是否开通推送服务
licenseEnabled: boolean // 是否开通 License 服务
}
interface XuqmUserInfo {
userId: string // 必填
userSig?: string // IM 服务必填;未开通 IM 时可不传
name?: string
phone?: string
avatar?: string
}
```
### 初始化 API
#### `XuqmSDK.initialize(options): Promise<void>`
手动初始化(方式 B。请求平台获取 appKey 专属服务配置(各服务 URL 和开通状态)。
- `platformUrl` 未传时使用内置默认公有平台地址
- **失败时直接抛出错误,不降级**,调用方必须处理异常
```ts
// 公有平台
await XuqmSDK.initialize({ appKey: 'your-app-key', debug: __DEV__ })
// 私有化部署
await XuqmSDK.initialize({
appKey: 'your-app-key',
platformUrl: 'https://your-server.com',
})
```
> 方式 A配置文件自动初始化将加密 `.xuqmconfig` 文件放置到 `src/assets/xuqm/config.xuqmconfig`,SDK 自动读取、解密AES-GCM并调用 `initialize()`,App 无需任何初始化代码。
#### `XuqmSDK.awaitInitialization(): Promise<void>`
等待初始化完成。子 SDK 内部调用,确保配置就绪后再使用。
### 用户认证 API
#### `XuqmSDK.setUserInfo(info): void`
用户认证核心枢纽。**登录后调用一次,所有子 SDK 自动同步**;传 `null` 触发全局登出。
```ts
// 登录
XuqmSDK.setUserInfo({
userId: 'user_001',
userSig: 'sig_from_server', // IM 必填
name: '张三',
phone: '13800138000',
})
// 登出
XuqmSDK.setUserInfo(null)
```
| 子 SDK | `setUserInfo(info)` 触发动作 | `setUserInfo(null)` 触发动作 |
|--------|------------------------------|------------------------------|
| PushSDK | 自动检测厂商 → 获取配置 → 注册设备 → 上报 token | 解绑 token |
| ImSDK | 若 `userSig` 存在且 IM 已开通,自动登录 | 断开 WebSocket 连接 |
| UpdateSDK | 更新 userId用于定向更新 | — |
| LicenseSDK | 更新用户上下文 | — |
#### `XuqmSDK.getUserId(): string | null`
#### `XuqmSDK.getUserInfo(): XuqmUserInfo | null`
### 已移除 API
| 方法 | 移除原因 |
|------|---------|
| `XuqmSDK.init(options): void` | 同步 init 不拉取服务配置,行为不完整 |
| `XuqmSDK.initializeFromLicense(file)` | License 不承担 SDK 初始化职责 |
| `XuqmSDK.initWithConfigFile(encrypted)` | 由自动初始化机制内部调用,不对外暴露 |
---
## 2. UpdateSDKupdate
> `import { UpdateSDK } from '@xuqm/rn-update'`
### 类型定义
```ts
interface PluginRegistration {
moduleId: string // 版本号由 SDK 自动从缓存读取,不需要传入
}
interface AppUpdateInfo {
needsUpdate: boolean
versionName?: string
versionCode?: number
downloadUrl?: string // APK 直接下载地址Android
changeLog?: string
forceUpdate?: boolean
appStoreUrl?: string // iOS App Store 地址
marketUrl?: string // Android 应用商店地址
apkHash?: string | null // APK SHA-256
}
interface PluginUpdateInfo {
needsUpdate: boolean
latestVersion: string
currentVersion: string // SDK 自动填入当前版本
downloadUrl: string
md5: string
minCommonVersion: string
note: string
forceUpdate?: boolean
}
```
### 插件注册
#### `UpdateSDK.registerPlugins(plugins): void`
批量注册插件(推荐)。版本号由 SDK 自动从本地缓存读取(首次为 `0.0.0`)。
```ts
UpdateSDK.registerPlugins([
{ moduleId: 'buz1' },
{ moduleId: 'buz2' },
{ moduleId: 'buz3' },
])
```
#### `UpdateSDK.registerPlugin(meta): void`
单个注册(向后兼容)。`version` 字段已废弃,传入无效。
#### `UpdateSDK.setBundleCallbacks(callbacks): void`
注入宿主 BundleRuntime 的写入和重载能力。宿主在初始化时调用一次。
```ts
import { writeBundleFile, loadBundle } from '@native/BundleRuntime'
UpdateSDK.setBundleCallbacks({
writeBundle: writeBundleFile,
reloadBundle: loadBundle,
})
```
### 插件热更新
#### `UpdateSDK.checkPluginUpdate(moduleId): Promise<PluginUpdateInfo>`
检查指定插件是否有更新,返回版本信息(不执行更新)。
#### `UpdateSDK.updatePlugin(moduleId, options?): Promise<void>`
执行插件更新一步完成。SDK 内部自动:检查 → 下载 → 写文件 → 重载。
```ts
// 静默后台更新(下次启动生效)
await UpdateSDK.updatePlugin('buz1', { silent: true })
// 带进度的前台更新(立即重载)
const info = await UpdateSDK.checkPluginUpdate('buz1')
if (info.needsUpdate) {
const confirmed = info.forceUpdate || (await showConfirm(`发现 ${info.latestVersion},是否更新?`))
if (confirmed) {
await UpdateSDK.updatePlugin('buz1', { onProgress: setProgress })
}
}
```
### App 整包更新
#### `UpdateSDK.checkAppUpdate(bypassIgnore?): Promise<AppUpdateInfo>`
检查 App 整包更新。自动携带当前 versionCode 和 userId定向更新
#### `UpdateSDK.downloadAndInstallApk(url, options?): Promise<void>`
Android 专用。下载 APK 并调起系统安装器。
```ts
await UpdateSDK.downloadAndInstallApk(info.downloadUrl, {
onProgress: (p) => setProgress(p),
sha256: info.apkHash ?? undefined,
})
```
#### `UpdateSDK.openStore(appStoreUrl?, marketUrl?): Promise<void>`
跳转 iOS App Store 或 Android 应用商店。
### 已移除 API
| 方法 | 替代 |
|------|------|
| `UpdateSDK.checkAndCachePlugin(moduleId)` | `updatePlugin(moduleId, { silent: true })` |
| `UpdateSDK.downloadPluginBundle(url)` | 内部实现,不对外暴露 |
| `UpdateSDK.cachePluginBundle(...)` | 内部实现 |
| `UpdateSDK.getCachedPluginBundle(moduleId)` | 内部实现 |
| `PluginMeta.version`(注册时传 version| SDK 自动从缓存读取 |
---
## 3. PushSDKpush
> `import { PushSDK } from '@xuqm/rn-push'`
**无需任何初始化**。`XuqmSDK.setUserInfo(info)` 被调用时,SDK 自动完成:
1. 检测设备厂商(华为/小米/OPPO/vivo/荣耀/FCM/APNs
2. 从平台获取该厂商推送配置
3. 调用厂商 SDK 完成设备注册
4. 收到 token 后自动上报绑定到平台
### API
#### `PushSDK.setOfflinePushEnabled(enabled): Promise<void>`
设置是否接收离线推送。
#### `PushSDK.setQuietHours(start, end): Promise<void>`
设置免打扰时间段24 小时制)。
```ts
await PushSDK.setQuietHours('22:00', '08:00')
```
#### `PushSDK.clearQuietHours(): Promise<void>`
清除免打扰设置。
#### `PushSDK.logout(): Promise<void>`
主动解绑推送 token。通常不需要手动调用,`XuqmSDK.setUserInfo(null)` 会自动触发。
### 已移除 API
| 方法 | 移除原因 |
|------|---------|
| `PushSDK.initialize(userId?)` | 由 `setUserInfo` 触发 |
| `PushSDK.requestNativeRegistration()` | 内部流程 |
| `PushSDK.registerToken(userId, token, vendor?)` | 内部流程 |
| `PushSDK.onPushToken(callback)` | 内部流程 |
| `PushSDK.unregisterToken(userId)` | 由 `setUserInfo(null)` 触发 |
| `PushSDK.setPendingToken / getPendingToken` | 内部状态 |
---
## 4. ImSDKim
> `import { ImSDK } from '@xuqm/rn-im'`
**无需初始化,通常不需要直接调用 `login()`**。`setUserInfo({ userId, userSig })` 自动触发 IM 登录(若租户开通 IM
### 初始化相关
#### `ImSDK.login(userId, userSig): Promise<void>`
手动登录(保留,通常不需要直接调用)。
#### `ImSDK.refreshToken(userSig): Promise<void>`
刷新 IM userSig过期时调用
```ts
const newSig = await api.refreshUserSig()
await ImSDK.refreshToken(newSig)
```
#### `ImSDK.disconnect(): void`
断开 WebSocket 连接(通常不需要直接调用,`setUserInfo(null)` 会自动触发)。
### 消息 API
```ts
await ImSDK.sendTextMessage(toId, chatType, content, mentionedUserIds?)
await ImSDK.sendImageMessage(toId, chatType, localUri, width?, height?)
await ImSDK.sendVideoMessage(toId, chatType, localUri, thumbnailUri?, duration?)
await ImSDK.sendAudioMessage(toId, chatType, localUri, duration)
await ImSDK.sendFileMessage(toId, chatType, localUri, filename, size)
await ImSDK.revokeMessage(messageId)
await ImSDK.editMessage(messageId, content)
```
### 会话 API
```ts
await ImSDK.listConversations()
ImSDK.subscribeConversations(callback) // 返回 unsubscribe 函数
await ImSDK.markRead(targetId, chatType)
await ImSDK.deleteConversation(targetId, chatType)
await ImSDK.getTotalUnreadCount()
```
### 历史消息 API
```ts
await ImSDK.fetchHistory(toId, page, size)
await ImSDK.fetchGroupHistory(groupId, page, size)
await ImSDK.searchMessages({ keyword, msgType, startTime, endTime })
```
### 群组 API
```ts
await ImSDK.createGroup(name, memberIds, groupType)
await ImSDK.listGroups()
await ImSDK.addGroupMember(groupId, userId)
await ImSDK.removeGroupMember(groupId, userId)
await ImSDK.setGroupRole(groupId, userId, role)
```
### 关系链 API
```ts
await ImSDK.listFriends()
await ImSDK.addFriend(friendId)
await ImSDK.removeFriend(friendId)
await ImSDK.sendFriendRequest(toUserId, remark?)
await ImSDK.acceptFriendRequest(requestId)
await ImSDK.addToBlacklist(blockedUserId)
await ImSDK.checkBlacklist(targetUserId)
```
### 事件监听
```ts
ImSDK.addListener({
onConnected: () => {},
onDisconnected: () => {},
onMessage: (msg) => {},
onGroupMessage: (msg) => {},
onRevoke: ({ msgId }) => {},
})
ImSDK.removeListener(listener)
```
---
## 5. LicenseSDKlicense
> `import { checkLicense, getStatus } from '@xuqm/rn-license'`
**无需独立初始化**。内部自动调用 `awaitInitialization()` 等待 `XuqmSDK` 就绪,使用公共 `appKey``licenseUrl`
### API
#### `checkLicense(userInfo?): Promise<LicenseResult>`
验证设备 License。
```ts
const result = await checkLicense()
if (result.type === 'success') {
console.log('License 验证通过:', result.reason)
} else {
console.error('License 验证失败:', result.message)
}
```
#### `getStatus(): Promise<LicenseStatus>`
获取当前 License 状态(`'ok' | 'denied' | 'unknown'`)。
#### `clear(): Promise<void>`
清除本地 License 缓存(调试用)。
### 已移除 API
| 方法 | 移除原因 |
|------|---------|
| `initialize(appKey, options)` | 依赖 XuqmSDK,无需独立初始化 |
| `initializeFromFile(encrypted)` | License 文件不承担 SDK 初始化职责 |
---
## 内部机制说明
### 用户信息分发_registerUserInfoHandler
`XuqmSDK.setUserInfo()` 内部维护一个订阅者列表。各子 SDK 在模块加载时注册处理器:
```
setUserInfo(info)
├── PushSDK检测厂商 → 获取厂商配置 → 注册 token
├── ImSDK若 userSig 存在且 imEnabled,自动登录
├── UpdateSDK更新 userId
└── LicenseSDK更新用户上下文
```
该机制为内部实现,业务侧只需调用 `setUserInfo`,无需关心具体分发逻辑。
### 配置文件解密
`.xuqmconfig` 文件格式:`XUQM-CONFIG-V1.{salt}.{iv}.{ciphertext}`Base64URL 编码)
SDK 使用 `react-native-quick-crypto` 的 SubtleCrypto 进行 PBKDF2 派生密钥 + AES-GCM 解密,详见 `packages/common/src/configCrypto.ts`
解密后包含:`{ appKey, platformUrl/serverUrl }`,SDK 自动调用 `initialize()` 完成远程配置拉取。