2026-04-27 17:18:56 +08:00
|
|
|
|
# React Native SDK 接入指南
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
**包名**:`@xuqm/rn-sdk` · **版本**:0.3.x(v0.4.0 规划中,将引入 UserSig 鉴权)
|
|
|
|
|
|
|
|
|
|
|
|
> **注意**:v0.4.0 将是 Breaking 版本。`initialize()` 将移除 `serverUrl` 参数,`login()` 将改为 UserSig 鉴权模式,详见[迁移指南](#迁移指南-v03x--v04x)。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
## 功能模块
|
|
|
|
|
|
|
2026-04-27 11:58:17 +08:00
|
|
|
|
| 包 | 功能 |
|
|
|
|
|
|
|----|------|
|
|
|
|
|
|
| `@xuqm/rn-common` | 初始化、网络、设备信息(必须) |
|
2026-04-27 17:18:56 +08:00
|
|
|
|
| `@xuqm/rn-im` | 单聊、群聊、消息收发、本地 DB(WatermelonDB)|
|
2026-04-27 11:58:17 +08:00
|
|
|
|
| `@xuqm/rn-push` | 推送设备 Token 上报 |
|
|
|
|
|
|
| `@xuqm/rn-update` | App 版本检查、RN Bundle 热更新 |
|
|
|
|
|
|
| `@xuqm/rn-sdk` | 以上所有模块的 meta 包(推荐直接使用) |
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
2026-04-24 15:35:24 +08:00
|
|
|
|
## 安装
|
|
|
|
|
|
|
|
|
|
|
|
在项目根目录创建 `.npmrc`:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
2026-04-27 11:58:17 +08:00
|
|
|
|
@xuqm:registry=https://nexus.xuqinmin.com/repository/npm/
|
2026-04-24 15:35:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 11:58:17 +08:00
|
|
|
|
安装 meta 包(包含全部功能):
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
yarn add @xuqm/rn-sdk
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
---
|
2026-04-27 11:58:17 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
## 快速接入(当前 v0.3.x)
|
2026-04-27 11:58:17 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
### 1. 初始化
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
初始化只需传入 `appId`,服务器地址由 SDK 内置,**不需要传 `serverUrl`**。
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
|
import { XuqmSDK } from '@xuqm/rn-sdk'
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// App 入口(如 App.tsx 的顶层)
|
2026-04-27 11:58:17 +08:00
|
|
|
|
await XuqmSDK.initialize({
|
2026-04-27 17:18:56 +08:00
|
|
|
|
appId: 'your_app_id', // 在租户平台创建应用后获得
|
|
|
|
|
|
logLevel: __DEV__ ? 'debug' : 'warn', // 可选
|
2026-04-24 15:35:24 +08:00
|
|
|
|
})
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
> SDK 内部自动处理服务器地址、WebSocket 连接、文件服务等配置,开发者无需关心。
|
2026-04-27 11:58:17 +08:00
|
|
|
|
|
2026-04-24 15:35:24 +08:00
|
|
|
|
### 2. IM 登录
|
|
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
|
import { ImSDK } from '@xuqm/rn-sdk'
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 登录(userId + 用户信息)
|
|
|
|
|
|
// v0.3.x:传入用户信息,本地 DB 按 userId 自动隔离
|
|
|
|
|
|
await ImSDK.login('user_001', 'nickname', 'https://avatar.url')
|
2026-04-27 11:58:17 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 推荐提前在您的服务端生成 UserSig(v0.4.0 正式采用)
|
|
|
|
|
|
// const userSig = await yourApi.getUserSig(userId)
|
|
|
|
|
|
// await ImSDK.login('user_001', userSig)
|
2026-04-24 15:35:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
### 3. 消息收发
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 监听实时消息
|
|
|
|
|
|
ImSDK.addEventListener('message', (msg) => {
|
|
|
|
|
|
console.log('收到消息:', msg.msgType, msg.content)
|
|
|
|
|
|
})
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 发送文本消息
|
|
|
|
|
|
const msg = await ImSDK.sendMessage(
|
|
|
|
|
|
'user_002', // toId
|
|
|
|
|
|
'SINGLE', // chatType: 'SINGLE' | 'GROUP'
|
|
|
|
|
|
'TEXT', // msgType
|
|
|
|
|
|
'Hello!' // content
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// 发送图片(自动上传到 file-service)
|
|
|
|
|
|
const msg = await ImSDK.sendImageMessage(
|
|
|
|
|
|
'user_002', 'SINGLE',
|
|
|
|
|
|
'/path/to/image.jpg', // 本地 URI
|
|
|
|
|
|
800, 600 // 宽高(可选)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// 获取历史消息(单聊)
|
|
|
|
|
|
const history = await ImSDK.fetchHistory('user_002', page, size)
|
|
|
|
|
|
|
|
|
|
|
|
// 获取群历史消息
|
|
|
|
|
|
const groupHistory = await ImSDK.fetchGroupHistory('group_xxx', page, size)
|
2026-04-24 15:35:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
### 4. 会话列表
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 订阅会话变化
|
|
|
|
|
|
const unsub = ImSDK.subscribeConversations((conversations) => {
|
|
|
|
|
|
// conversations: ConversationData[]
|
|
|
|
|
|
console.log(conversations)
|
|
|
|
|
|
})
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 置顶会话
|
|
|
|
|
|
await ImSDK.setConversationPinned('user_002', 'SINGLE', true)
|
2026-04-27 11:58:17 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 免打扰
|
|
|
|
|
|
await ImSDK.setConversationMuted('group_xxx', 'GROUP', true)
|
2026-04-27 11:58:17 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 标记已读
|
|
|
|
|
|
await ImSDK.markRead('user_002')
|
2026-04-24 15:35:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
### 5. 群组管理
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 创建群组
|
|
|
|
|
|
const group = await ImSDK.createGroup('项目讨论', ['user_002', 'user_003'])
|
2026-04-27 11:58:17 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 群组列表(仅返回当前用户所在的群)
|
|
|
|
|
|
const groups = await ImSDK.listGroups()
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 添加成员
|
|
|
|
|
|
await ImSDK.addGroupMember('group_xxx', 'user_004')
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 移除成员(需要管理员权限)
|
|
|
|
|
|
await ImSDK.removeGroupMember('group_xxx', 'user_004')
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 退出群聊
|
|
|
|
|
|
await ImSDK.leaveGroup('group_xxx')
|
2026-04-24 15:35:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
### 6. 好友关系
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 好友列表
|
|
|
|
|
|
const friends = await ImSDK.listFriends()
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 添加好友(双向)
|
|
|
|
|
|
await ImSDK.addFriend('user_002')
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 删除好友(双向)
|
|
|
|
|
|
await ImSDK.removeFriend('user_002')
|
2026-04-24 15:35:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
### 7. 消息搜索(本地)
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-27 17:18:56 +08:00
|
|
|
|
import { ImSDK } from '@xuqm/rn-sdk'
|
|
|
|
|
|
import type { MessageSearchParams } from '@xuqm/rn-sdk'
|
|
|
|
|
|
|
|
|
|
|
|
const params: MessageSearchParams = {
|
|
|
|
|
|
keyword: '会议', // 关键词搜索
|
|
|
|
|
|
toId: 'user_002', // 限定会话(可选)
|
|
|
|
|
|
chatType: 'SINGLE', // 限定类型(可选)
|
|
|
|
|
|
msgTypes: ['TEXT'], // 限定消息类型(可选)
|
|
|
|
|
|
limit: 20,
|
|
|
|
|
|
}
|
|
|
|
|
|
const results = await ImSDK.searchMessages(params)
|
2026-04-24 15:35:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
### 8. 推送 SDK
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-27 17:18:56 +08:00
|
|
|
|
import { PushSDK } from '@xuqm/rn-sdk'
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化并注册设备(登录后调用)
|
|
|
|
|
|
await PushSDK.initialize({ userId: 'user_001' })
|
2026-04-27 11:58:17 +08:00
|
|
|
|
```
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
### 9. 版本更新 SDK
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 11:58:17 +08:00
|
|
|
|
```ts
|
|
|
|
|
|
import { UpdateSDK } from '@xuqm/rn-sdk'
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 检查 App 原生更新
|
|
|
|
|
|
const appUpdate = await UpdateSDK.checkAppUpdate()
|
|
|
|
|
|
if (appUpdate?.needsUpdate) {
|
|
|
|
|
|
console.log('新版本:', appUpdate.versionName)
|
|
|
|
|
|
// Linking.openURL(appUpdate.downloadUrl)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查 RN Bundle 热更新
|
|
|
|
|
|
const rnUpdate = await UpdateSDK.checkRnUpdate('your_module_id')
|
|
|
|
|
|
if (rnUpdate?.needsUpdate) {
|
|
|
|
|
|
await UpdateSDK.downloadAndApplyBundle(rnUpdate)
|
2026-04-27 11:58:17 +08:00
|
|
|
|
}
|
2026-04-24 15:35:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
### 10. 断开连接
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-27 17:18:56 +08:00
|
|
|
|
ImSDK.disconnect()
|
2026-04-24 15:35:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
---
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
## TypeScript 类型参考
|
2026-04-24 15:35:24 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 消息
|
2026-04-24 15:35:24 +08:00
|
|
|
|
interface ImMessage {
|
2026-04-27 17:18:56 +08:00
|
|
|
|
id: string
|
|
|
|
|
|
fromId: string
|
|
|
|
|
|
toId: string
|
|
|
|
|
|
chatType: 'SINGLE' | 'GROUP'
|
|
|
|
|
|
msgType: 'TEXT' | 'IMAGE' | 'AUDIO' | 'VIDEO' | 'FILE' |
|
|
|
|
|
|
'LOCATION' | 'NOTIFY' | 'CUSTOM' | 'RICH_TEXT' |
|
|
|
|
|
|
'CALL_AUDIO' | 'CALL_VIDEO' | 'FORWARD' | 'REVOKED'
|
|
|
|
|
|
content: string // JSON 字符串,结构按 msgType 不同
|
|
|
|
|
|
status: 'SENDING' | 'SENT' | 'DELIVERED' | 'READ' | 'FAILED' | 'REVOKED'
|
|
|
|
|
|
createdAt: number // Unix 毫秒
|
2026-04-24 15:35:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 17:18:56 +08:00
|
|
|
|
// 会话
|
2026-04-27 11:58:17 +08:00
|
|
|
|
interface ConversationData {
|
2026-04-27 17:18:56 +08:00
|
|
|
|
targetId: string
|
|
|
|
|
|
chatType: 'SINGLE' | 'GROUP'
|
2026-04-27 11:58:17 +08:00
|
|
|
|
lastMsgContent: string
|
2026-04-27 17:18:56 +08:00
|
|
|
|
lastMsgType: string
|
|
|
|
|
|
lastMsgTime: number
|
|
|
|
|
|
unreadCount: number
|
|
|
|
|
|
isMuted: boolean
|
|
|
|
|
|
isPinned: boolean
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 群组
|
|
|
|
|
|
interface ImGroup {
|
|
|
|
|
|
id: string
|
|
|
|
|
|
name: string
|
|
|
|
|
|
creatorId: string
|
|
|
|
|
|
memberIds: string // JSON 数组字符串
|
|
|
|
|
|
adminIds: string
|
|
|
|
|
|
createdAt: number
|
2026-04-24 15:35:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
```
|
2026-04-27 17:18:56 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 迁移指南(v0.3.x → v0.4.0)
|
|
|
|
|
|
|
|
|
|
|
|
v0.4.0 预计改动(**Breaking Changes**):
|
|
|
|
|
|
|
|
|
|
|
|
```diff
|
|
|
|
|
|
// 初始化
|
|
|
|
|
|
- await XuqmSDK.initialize({ appId: 'xxx', serverUrl: 'https://...' })
|
|
|
|
|
|
+ await XuqmSDK.initialize({ appId: 'xxx' }) // serverUrl 内置,无需传入
|
|
|
|
|
|
|
|
|
|
|
|
// IM 登录(改为 UserSig 鉴权,密码不再传入 SDK)
|
|
|
|
|
|
- await ImSDK.login(userId, nickname, avatar, dbName)
|
|
|
|
|
|
+ const userSig = await yourServer.getUserSig(userId) // 您的服务端签发
|
|
|
|
|
|
+ await ImSDK.login(userId, userSig, { nickname, avatar })
|
|
|
|
|
|
// dbName 自动由 appId + userId 派生,无需传入
|
|
|
|
|
|
|
|
|
|
|
|
// loginWithToken 废弃
|
|
|
|
|
|
- await ImSDK.loginWithToken(userId, token, dbName)
|
|
|
|
|
|
+ // 统一使用 login(userId, userSig)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
UserSig 生成方式见[安全设计文档](../../design/02-security-design.md)。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 常见问题
|
|
|
|
|
|
|
|
|
|
|
|
**Q: 如何获取 appId?**
|
|
|
|
|
|
在 [租户平台](https://dev.xuqinmin.com) 注册账号后,创建应用即可获得 AppId。
|
|
|
|
|
|
|
|
|
|
|
|
**Q: 为什么不需要传 serverUrl?**
|
|
|
|
|
|
XuqmGroup 是托管平台,服务地址统一管理,与腾讯云 IM 等平台的设计一致,开发者只需关心业务逻辑。
|
|
|
|
|
|
|
|
|
|
|
|
**Q: UserSig 是什么?(v0.4.0)**
|
|
|
|
|
|
UserSig 是您的业务服务端用 AppSecret 为用户签发的安全凭证,有效期可配置。AppSecret 绝不下发到客户端。
|
|
|
|
|
|
|
|
|
|
|
|
**Q: 本地消息存储在哪里?**
|
|
|
|
|
|
使用 WatermelonDB(SQLite),按 `appId + userId` 自动隔离,多账号切换安全。
|