244 行
5.6 KiB
Markdown
244 行
5.6 KiB
Markdown
# XuqmGroup Android SDK 文档
|
||
|
||
> Kotlin 2.3.10 · AGP 9.1.0 · minSdk 24 · compileSdk 36
|
||
|
||
## 模块结构
|
||
|
||
```
|
||
XuqmGroup-AndroidSDK/
|
||
├── sdk-core/ # 核心:初始化、HTTP、Token 存储
|
||
├── sdk-im/ # IM:WebSocket 实时通信
|
||
├── sdk-push/ # 推送:设备 Token 注册
|
||
├── sdk-update/ # 版本管理:检查更新、下载安装、RN 热更新
|
||
└── sample-app/ # 示例 App(Jetpack Compose)
|
||
```
|
||
|
||
## 集成
|
||
|
||
### Gradle(Maven 私有仓库)
|
||
|
||
在项目根 `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.init(
|
||
context = this,
|
||
appKey = "ak_your_app_key",
|
||
appSecret = "as_your_app_secret",
|
||
apiBaseUrl = "https://api.xuqm.com",
|
||
imBaseUrl = "wss://im.xuqm.com",
|
||
debug = BuildConfig.DEBUG
|
||
)
|
||
```
|
||
|
||
### 2. 用户登录后设置 Token
|
||
|
||
```kotlin
|
||
// 调用你的业务登录接口获得 token 后
|
||
XuqmSDK.tokenStore.save(token)
|
||
```
|
||
|
||
---
|
||
|
||
## sdk-core
|
||
|
||
### SDKConfig
|
||
|
||
| 参数 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `appKey` | String | 应用 Key(租户平台获取) |
|
||
| `appSecret` | String | 应用 Secret |
|
||
| `apiBaseUrl` | String | 后端 API 地址 |
|
||
| `imBaseUrl` | String | IM WebSocket 地址(wss://) |
|
||
| `debug` | Boolean | 开启日志 |
|
||
|
||
### TokenStore
|
||
|
||
基于 `DataStore<Preferences>` 持久化存储。
|
||
|
||
```kotlin
|
||
// 存储
|
||
XuqmSDK.tokenStore.save("eyJ...")
|
||
|
||
// 读取(协程)
|
||
val token = XuqmSDK.tokenStore.get()
|
||
|
||
// 清除(登出)
|
||
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
|
||
|
||
### 注册推送 Token
|
||
|
||
在获取到厂商推送 token 后调用:
|
||
|
||
```kotlin
|
||
PushSDK.registerToken(
|
||
appId = "ak_xxx",
|
||
userId = "user_001",
|
||
vendor = Vendor.HUAWEI, // HUAWEI / XIAOMI / OPPO / VIVO / HONOR / APNS
|
||
token = "device_push_token"
|
||
)
|
||
```
|
||
|
||
### 与 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` 中维护。
|