XuqmGroup-AndroidSDK/README.md

256 行
6.1 KiB
Markdown

2026-04-21 22:25:33 +08:00
# XuqmGroup Android SDK 文档
> Kotlin 2.3.10 · AGP 9.1.0 · minSdk 24 · compileSdk 36
## 模块结构
```
XuqmGroup-AndroidSDK/
├── sdk-core/ # 核心初始化、HTTP、Token 存储、通用工具/组件
2026-04-21 22:25:33 +08:00
├── sdk-im/ # IMWebSocket 实时通信
├── sdk-push/ # 推送:设备 Token 注册
├── sdk-update/ # 版本管理检查更新、下载安装、RN 热更新
└── sample-app/ # 示例 AppJetpack Compose
```
## 集成
### GradleMaven 私有仓库)
在项目根 `settings.gradle.kts` 添加仓库:
```kotlin
dependencyResolutionManagement {
repositories {
maven {
url = uri("https://nexus.xuqinmin.com/repository/android-hosted/")
credentials {
username = providers.gradleProperty("NEXUS_USER").orNull ?: ""
password = providers.gradleProperty("NEXUS_PASSWORD").orNull ?: ""
}
}
}
}
```
`gradle.properties` 或环境变量中配置:
```properties
NEXUS_USER=your_username
NEXUS_PASSWORD=your_password
```
引入依赖:
```kotlin
dependencies {
implementation("com.xuqm:sdk-core:0.1.0")
implementation("com.xuqm:sdk-im:0.1.0") // 可选
implementation("com.xuqm:sdk-push:0.1.0") // 可选
implementation("com.xuqm:sdk-update:0.1.0") // 可选
}
```
## 快速开始
### 1. 初始化Application.onCreate
```kotlin
XuqmSDK.initialize(
2026-04-21 22:25:33 +08:00
context = this,
appId = "ak_your_app_id",
logLevel = if (BuildConfig.DEBUG) LogLevel.DEBUG else LogLevel.WARN
2026-04-21 22:25:33 +08:00
)
```
### 2. 用户登录后初始化 IM
2026-04-21 22:25:33 +08:00
```kotlin
// 调用业务登录接口,拿到 userSig 后只需要登录一次 SDK
val userSig = api.getUserSig(userId)
XuqmSDK.login(
userId = userId,
userSig = userSig,
nickname = profile.nickname,
avatar = profile.avatar,
)
// 如果工程里集成了 sdk-im,SDK 会自动完成 IM 登录
2026-04-21 22:25:33 +08:00
```
### 3. 切换联调环境
默认使用外网域名。若要本地联调,可在 `Application.onCreate()` 里切换:
```kotlin
XuqmSDK.useLocalServiceEndpoints("10.0.2.2") // Android Emulator
// 物理设备可改成你的电脑局域网 IP
```
如果是 sample-app,也可以直接调用
```kotlin
SampleEnvironmentConfig.useLocalhost("10.0.2.2")
```
切换后,HTTP API 会立即走新端点;如果 IM 已登录,SDK 会自动重新连接。
sample-app 里也提供了一个“环境设置”页面,可以直接在外网和本地联调之间切换。
2026-04-21 22:25:33 +08:00
---
## sdk-core
### SDKConfig
| 参数 | 类型 | 说明 |
|------|------|------|
| `appId` | String | 应用标识(租户平台获取) |
| `logLevel` | LogLevel | 日志等级 |
2026-04-21 22:25:33 +08:00
### TokenStore
基于 `EncryptedSharedPreferences` 持久化存储。
2026-04-21 22:25:33 +08:00
```kotlin
// 存储
XuqmSDK.tokenStore.saveToken("eyJ...")
2026-04-21 22:25:33 +08:00
// 读取(协程)
val token = XuqmSDK.tokenStore.getToken()
2026-04-21 22:25:33 +08:00
// 清除(登出)
XuqmSDK.tokenStore.clear()
```
### ApiClient
基于 OkHttp 5 + Retrofit 3,自动附加 Bearer Token,统一解析 `ApiResponse<T>`
```kotlin
// 通过 RetrofitFactory 获取接口实例
val service = RetrofitFactory.create(MyApiService::class.java)
```
---
## sdk-im
### ImClient
```kotlin
val imClient = ImClient()
// 注册事件监听
imClient.listener = object : ImEventListener {
override fun onConnected() { /* WebSocket 连接成功 */ }
override fun onDisconnected(code: Int, reason: String) { /* 断开 */ }
override fun onMessage(msg: ImMessage) { /* 收到新消息 */ }
override fun onRevoke(msgId: String, operatorId: String) { /* 消息被撤回 */ }
override fun onError(t: Throwable) { /* 连接错误 */ }
}
// 连接
imClient.connect()
// 发送消息
imClient.send(SendMessageParams(
toId = "user_002",
chatType = ChatType.SINGLE,
msgType = MsgType.TEXT,
content = "Hello!"
))
// 撤回消息
imClient.revoke(msgId = "uuid")
// 断开连接Activity/Fragment 销毁时调用)
imClient.disconnect()
```
### 消息类型MsgType
`TEXT` / `IMAGE` / `VIDEO` / `AUDIO` / `FILE` / `CUSTOM` / `LOCATION` / `NOTIFY` / `RICH_TEXT` / `CALL_AUDIO` / `CALL_VIDEO` / `FORWARD`
### ImMessage 结构
```kotlin
data class ImMessage(
val id: String,
val fromId: String,
val toId: String,
val chatType: ChatType, // SINGLE / GROUP
val msgType: MsgType,
val content: String,
val extra: String?,
val revoked: Boolean,
val createdAt: String
)
```
### 自动重连
断线后指数退避重连,初始间隔 3 秒,最大间隔 30 秒。调用 `disconnect()` 后停止重连。
---
## sdk-push
### 推送接入
2026-04-21 22:25:33 +08:00
`PushSDK.initialize()` 后由 SDK 自动完成厂商初始化、设备注册与 token 上传,不再要求业务侧单独调用注册接口。
2026-04-21 22:25:33 +08:00
### 与 IM 联动
当 IM 和推送服务均已开启时,IM 服务在目标用户离线时会自动调用推送服务发送离线推送通知。
业务方只需分别注册推送 Token 和 IM 登录,无需额外配置。
---
## sdk-update
### 检查原生 App 更新
```kotlin
val result: UpdateResult = UpdateSDK.checkUpdate(
appId = "ak_xxx",
platform = Platform.ANDROID
)
if (result.needsUpdate) {
// result.versionName, result.downloadUrl, result.forceUpdate
UpdateSDK.downloadAndInstall(context, result.downloadUrl)
}
```
`downloadAndInstall` 会将 APK 下载到 `getExternalFilesDir(null)`,通过 `FileProvider` 触发系统安装。
AndroidManifest 中已配置 `@xml/file_paths``external-files-path`)。
### 检查 RN Bundle 更新
```kotlin
val rnResult = UpdateSDK.checkRnUpdate(
appId = "ak_xxx",
moduleId = "main",
platform = "android",
currentVersion = "1.0.0"
)
if (rnResult.needsUpdate) {
val filePath = UpdateSDK.downloadBundle(context, rnResult.downloadUrl, "main.android.bundle")
// 校验 MD5
// 通知 RN 引擎加载新 bundle
}
```
---
## 发版
```bash
# 在 gradle.properties 中配置 NEXUS_USER / NEXUS_PASSWORD
./gradlew :sdk-core:publish
./gradlew :sdk-im:publish
./gradlew :sdk-push:publish
./gradlew :sdk-update:publish
```
发布至 `https://nexus.xuqinmin.com/repository/android-hosted/`,groupId `com.xuqm`,版本号在各模块 `build.gradle.kts` 中维护。