XuqmGroup-AndroidSDK/sdk-update/src/main/java/com/xuqm/sdk/update/UpdateSDK.kt

94 行
3.4 KiB
Kotlin

2026-04-21 22:07:29 +08:00
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) {
2026-04-21 22:07:29 +08:00
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()
2026-04-21 22:07:29 +08:00
}
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) }
2026-04-21 22:07:29 +08:00
}
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? =
2026-04-21 22:07:29 +08:00
withContext(Dispatchers.IO) {
XuqmSDK.requireInit()
runCatching {
api.checkRnUpdate(XuqmSDK.appId, moduleId, "ANDROID", currentVersion).data?.let {
it.copy(downloadUrl = normalizeDownloadUrl(it.downloadUrl) ?: it.downloadUrl)
}
}.getOrNull()
2026-04-21 22:07:29 +08:00
}
}