# 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/ # 版本管理:检查更新、下载安装 └── 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.initialize( context = this, appId = "ak_your_app_id", logLevel = if (BuildConfig.DEBUG) LogLevel.DEBUG else LogLevel.WARN ) ``` ### 2. 用户登录后初始化 IM ```kotlin // 调用业务登录接口,拿到 userSig 后只需要登录一次 SDK val userSig = api.getUserSig(userId) XuqmSDK.login( userId = userId, userSig = userSig, nickname = profile.nickname, avatar = profile.avatar, ) // 如果工程里集成了 sdk-im,SDK 会自动完成 IM 登录 ``` ### 3. 切换联调环境 默认使用外网域名。若要本地联调,可在 `Application.onCreate()` 里切换: ```kotlin XuqmSDK.useLocalServiceEndpoints("192.168.116.9") // 物理设备可改成你的电脑局域网 IP ``` 如果是 sample-app,也可以直接调用: ```kotlin SampleEnvironmentConfig.useLocalhost("10.0.2.2") ``` 切换后,HTTP API 会立即走新端点;如果 IM 已登录,SDK 会自动重新连接。 sample-app 里也提供了一个“环境设置”页面,可以直接在外网和本地联调之间切换。 --- ## sdk-core ### SDKConfig | 参数 | 类型 | 说明 | |------|------|------| | `appId` | String | 应用标识(租户平台获取) | | `logLevel` | LogLevel | 日志等级 | ### TokenStore 基于 `EncryptedSharedPreferences` 持久化存储。 ```kotlin // 存储 XuqmSDK.tokenStore.saveToken("eyJ...") // 读取(协程) val token = XuqmSDK.tokenStore.getToken() // 清除(登出) XuqmSDK.tokenStore.clear() ``` ### ApiClient 基于 OkHttp 5 + Retrofit 3,自动附加 Bearer Token,统一解析 `ApiResponse`。 ```kotlin // 通过 RetrofitFactory 获取接口实例 val service = RetrofitFactory.create(MyApiService::class.java) ``` --- ## sdk-im ### Android sample 已具备 - 会话列表先读本地缓存,再刷新网络 - 联系人列表先读本地缓存,再刷新网络 - 聊天历史分页加载 - 当前会话本地搜索 - 输入草稿自动保存 - 群设置支持编辑群名和群公告 - 群组扩展 API 已补齐:管理员设置、禁言、解散群 - 公开群支持搜索、创建和加群审批 - 会话支持本地删除 - 显示总未读数 - 消息状态直接展示 - 会话置顶/免打扰/已读/草稿/删除同步服务端 - IM 连接状态提示 - SDK 登录态恢复后自动重连 - IM token 自动续签,过期前会静默刷新并重连 - 群聊支持 `@userId` 提及,并写入 `mentionedUserIds` - 关系链支持好友申请、接受/拒绝、黑名单 - 支持图片 / 视频 / 音频 / 文件消息,文件通过独立文件服务上传后再发 IM - 图片支持拍照、摄像、图库选择,文件支持文件管理器选择 - 语音支持长按录音、抬手发送 - 支持引用回复、群聊已读人数展示 - 支持 `LOCATION` / `CUSTOM` / `RICH_TEXT` / `FORWARD` / `QUOTE` / `MERGE` / `CALL_AUDIO` / `CALL_VIDEO` 等通用消息类型发送 - 单聊支持已读回执,服务端会把 `READ` 状态推回发送者 ### 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.send(SendMessageParams( toId = "group_001", chatType = ChatType.GROUP, msgType = MsgType.TEXT, content = "@user_002 你好", mentionedUserIds = "user_002", )) // 撤回消息 imClient.revoke(msgId = "uuid") // 断开连接(Activity/Fragment 销毁时调用) imClient.disconnect() ``` ### 消息类型(MsgType) `TEXT` / `IMAGE` / `VIDEO` / `AUDIO` / `FILE` / `CUSTOM` / `LOCATION` / `NOTIFY` / `RICH_TEXT` / `CALL_AUDIO` / `CALL_VIDEO` / `FORWARD` / `QUOTE` / `MERGE` ### 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 ### 推送接入 在 `XuqmSDK.login()` 成功后,SDK 会自动完成当前系统推送 token 的注册与上传,不再要求业务侧手工传入 token。`logout()` 时会自动注销当前设备绑定。 还可以按用户设置接收开关: ```kotlin PushSDK.setReceivePush(context, enabled = false) PushSDK.setReceivePush(context, enabled = true) ``` 如果项目接入了 Firebase Messaging,`sdk-push` 会通过 `FirebaseMessagingService.onNewToken()` 自动接收并上报 FCM token。对应服务已经随库注册,只要应用工程提供 Firebase 配置即可生效。 ### 与 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`)。 --- ## 发版 ```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` 中维护。