XuqmGroup-AndroidSDK/sdk-update/src/main/java/com/xuqm/sdk/update/UpdateSDK.kt
XuqmGroup 00f2ad04b7 feat(sample): 添加示例应用的核心功能模块
- 集成依赖管理配置文件 libs.versions.toml,统一管理项目依赖版本
- 实现演示 API 接口定义,包含登录、注册、用户管理等 RESTful 端点
- 创建认证仓库 AuthRepository,处理用户会话管理和加密存储
- 开发登录和注册界面,实现用户身份验证流程
- 构建聊天界面 ChatScreen,支持消息收发和历史记录显示
- 实现联系人管理功能,包含好友搜索和添加删除操作
- 添加会话列表界面,展示最近聊天记录和未读消息提示
2026-04-27 19:00:54 +08:00

94 行
3.4 KiB
Kotlin

package com.xuqm.sdk.update
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.core.content.FileProvider
import com.xuqm.sdk.XuqmSDK
import com.xuqm.sdk.network.ApiClient
import com.xuqm.sdk.update.api.UpdateApi
import com.xuqm.sdk.update.model.RnUpdateInfo
import com.xuqm.sdk.update.model.UpdateInfo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.net.URL
object UpdateSDK {
private val api: UpdateApi by lazy { ApiClient.create() }
private fun normalizeDownloadUrl(rawUrl: String?): String? {
if (rawUrl.isNullOrBlank()) return rawUrl
if (rawUrl.contains("/api/v1/updates/api/v1/rn/files/")) {
return rawUrl.replace("/api/v1/updates/api/v1/rn/files/", "/api/v1/rn/files/")
}
return runCatching {
val uri = Uri.parse(rawUrl)
if (uri.path?.startsWith("/files/apk/") == true) {
"${uri.scheme}://${uri.authority}/api/v1/updates${uri.path}"
} else {
rawUrl
}
}.getOrDefault(rawUrl)
}
suspend fun checkAppUpdate(context: Context): UpdateInfo? = withContext(Dispatchers.IO) {
XuqmSDK.requireInit()
val versionCode = context.packageManager
.getPackageInfo(context.packageName, 0).longVersionCode.toInt()
runCatching {
api.checkUpdate(XuqmSDK.appId, "ANDROID", versionCode).data?.let {
it.copy(downloadUrl = normalizeDownloadUrl(it.downloadUrl) ?: it.downloadUrl)
}
}.getOrNull()
}
suspend fun downloadAndInstall(
context: Context,
downloadUrl: String,
onProgress: (Int) -> Unit = {},
) = withContext(Dispatchers.IO) {
val apkFile = File(context.getExternalFilesDir(null), "update.apk")
val url = URL(downloadUrl)
val connection = url.openConnection()
connection.connect()
val totalSize = connection.contentLengthLong
connection.getInputStream().use { input ->
apkFile.outputStream().use { output ->
val buffer = ByteArray(8192)
var downloaded = 0L
var read: Int
while (input.read(buffer).also { read = it } != -1) {
output.write(buffer, 0, read)
downloaded += read
if (totalSize > 0) onProgress((downloaded * 100 / totalSize).toInt())
}
}
}
withContext(Dispatchers.Main) { installApk(context, apkFile) }
}
private fun installApk(context: Context, apkFile: File) {
val intent = Intent(Intent.ACTION_VIEW).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
val uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", apkFile)
setDataAndType(uri, "application/vnd.android.package-archive")
}
context.startActivity(intent)
}
suspend fun checkRnUpdate(moduleId: String, currentVersion: String): RnUpdateInfo? =
withContext(Dispatchers.IO) {
XuqmSDK.requireInit()
runCatching {
api.checkRnUpdate(XuqmSDK.appId, moduleId, "ANDROID", currentVersion).data?.let {
it.copy(downloadUrl = normalizeDownloadUrl(it.downloadUrl) ?: it.downloadUrl)
}
}.getOrNull()
}
}