转到文件
XuqmGroup b5d00c5f78 build: switch apply(from) to Groovy publish.gradle for AGP compat
KTS scripts loaded via apply(from) are compiled without AGP on the
classpath, so LibraryExtension and ext are unresolvable. Groovy
applied scripts are evaluated dynamically and don't have this issue.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:23:51 +08:00
docs docs: add detailed documentation 2026-04-21 22:25:33 +08:00
gradle build: switch apply(from) to Groovy publish.gradle for AGP compat 2026-04-29 15:23:51 +08:00
sample-app feat(im): add remote chat search and locate 2026-04-29 09:54:40 +08:00
sdk-core build: switch apply(from) to Groovy publish.gradle for AGP compat 2026-04-29 15:23:51 +08:00
sdk-im build: switch apply(from) to Groovy publish.gradle for AGP compat 2026-04-29 15:23:51 +08:00
sdk-push build: switch apply(from) to Groovy publish.gradle for AGP compat 2026-04-29 15:23:51 +08:00
sdk-update build: switch apply(from) to Groovy publish.gradle for AGP compat 2026-04-29 15:23:51 +08:00
.gitignore feat(sample): 添加示例应用的核心功能模块 2026-04-27 19:00:54 +08:00
build.gradle.kts feat(sample): 添加示例应用的核心功能模块 2026-04-27 19:00:54 +08:00
gradle.properties chore: initial commit 2026-04-21 22:07:29 +08:00
gradlew feat(sample): 集成 Sentry 异常监控功能 2026-04-24 16:46:38 +08:00
gradlew.bat feat(sample): 集成 Sentry 异常监控功能 2026-04-24 16:46:38 +08:00
local.properties feat(sample): 集成 Sentry 异常监控功能 2026-04-24 16:46:38 +08:00
README.md feat(push): use Firebase token auto registration 2026-04-29 09:50:09 +08:00
settings.gradle.kts chore: initial commit 2026-04-21 22:07:29 +08:00

XuqmGroup Android SDK 文档

Kotlin 2.3.10 · AGP 9.1.0 · minSdk 24 · compileSdk 36

模块结构

XuqmGroup-AndroidSDK/
├── sdk-core/        # 核心初始化、HTTP、Token 存储、文件上传、通用工具/组件
├── sdk-im/          # IMWebSocket 实时通信
├── sdk-push/        # 推送:设备 Token 注册
├── sdk-update/      # 版本管理:检查更新、下载安装
└── sample-app/      # 示例 AppJetpack Compose

集成

GradleMaven 私有仓库)

在项目根 settings.gradle.kts 添加仓库:

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 或环境变量中配置:

NEXUS_USER=your_username
NEXUS_PASSWORD=your_password

引入依赖:

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

XuqmSDK.initialize(
    context = this,
    appId = "ak_your_app_id",
    logLevel = if (BuildConfig.DEBUG) LogLevel.DEBUG else LogLevel.WARN
)

2. 用户登录后初始化 IM

// 调用业务登录接口,拿到 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() 里切换:

XuqmSDK.useLocalServiceEndpoints("192.168.116.9")
// 物理设备可改成你的电脑局域网 IP

如果是 sample-app,也可以直接调用

SampleEnvironmentConfig.useLocalhost("10.0.2.2")

切换后,HTTP API 会立即走新端点;如果 IM 已登录,SDK 会自动重新连接。

sample-app 里也提供了一个“环境设置”页面,可以直接在外网和本地联调之间切换。


sdk-core

SDKConfig

参数 类型 说明
appId String 应用标识(租户平台获取)
logLevel LogLevel 日志等级

TokenStore

基于 EncryptedSharedPreferences 持久化存储。

// 存储
XuqmSDK.tokenStore.saveToken("eyJ...")

// 读取(协程)
val token = XuqmSDK.tokenStore.getToken()

// 清除(登出)
XuqmSDK.tokenStore.clear()

ApiClient

基于 OkHttp 5 + Retrofit 3,自动附加 Bearer Token,统一解析 ApiResponse<T>

// 通过 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

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 结构

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() 时会自动注销当前设备绑定。

还可以按用户设置接收开关:

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 更新

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_pathsexternal-files-path)。


发版

# 在 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 中维护。