添加共存版的检查更新

This commit is contained in:
Jason Yao
2024-07-24 20:18:01 -07:00
parent ed4311eae9
commit 039151ecc1
4 changed files with 158 additions and 61 deletions

View File

@@ -1,51 +1,34 @@
package io.legado.app
import com.google.gson.Gson
import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.http.okHttpClient
import io.legado.app.utils.channel
import io.legado.app.utils.jsonPath
import io.legado.app.model.GithubRelease
import io.legado.app.utils.fromJsonArray
import okhttp3.Request
import org.junit.Assert.assertTrue
import org.junit.Test
import splitties.init.appCtx
class UpdateTest {
private val lastReleaseUrl = "https://api.github.com/repos/gedoor/legado/releases/latest"
private val lastReleaseUrl =
"https://api.github.com/repos/gedoor/legado/releases?page=1?per_page=1"
@Test
fun updateApp() {
val body = okHttpClient.newCall(Request.Builder().url(lastReleaseUrl).build()).execute()
.body!!.string()
val rootDoc = jsonPath.parse(body)
val downloadUrl =
rootDoc.read<List<String>>("\$.assets[?(@.name =~ /legado_app_.*?apk\$/)].browser_download_url")
print(downloadUrl)
}
@Test
fun updateLollipop() {
val body = okHttpClient.newCall(Request.Builder().url(lastReleaseUrl).build()).execute()
.body!!.string()
val rootDoc = jsonPath.parse(body)
val downloadUrl =
rootDoc.read<List<String>>("\$.assets[?(@.name =~ /legado_lollipop_.*?apk\$/)].browser_download_url")
print(downloadUrl)
}
val releaseList = Gson().fromJsonArray<GithubRelease>(body)
.getOrElse {
throw NoStackTraceException("获取新版本出错 " + it.localizedMessage)
}
.flatMap { it.gitReleaseToAppReleaseInfo() }
.sortedByDescending { it.createdAt }
@Test
fun updateChannel() {
val body = okHttpClient.newCall(Request.Builder().url(lastReleaseUrl).build()).execute()
.body!!.string()
val rootDoc = jsonPath.parse(body)
val path = "\$.assets[?(@.name =~ /legado_${appCtx.channel}_.*?apk\$/)]"
val downloadUrl = rootDoc.read<List<String>>("${path}.browser_download_url")
.firstOrNull()
?: throw NoStackTraceException("获取新版本出错")
val fileName = rootDoc.read<List<String>>("${path}.name")
.firstOrNull()
?: throw NoStackTraceException("获取新版本出错")
print(downloadUrl)
print(fileName)
assertTrue(releaseList.isNotEmpty())
assertTrue(releaseList.all { it.downloadUrl.isNotBlank() })
assertTrue(releaseList.all { it.versionName.isNotBlank() })
}
}

View File

@@ -5,6 +5,7 @@ import android.content.pm.PackageManager
import android.provider.Settings
import androidx.annotation.Keep
import io.legado.app.BuildConfig
import io.legado.app.model.AppVariant
import splitties.init.appCtx
import java.text.SimpleDateFormat
@@ -58,6 +59,11 @@ object AppConst {
appCtx.packageManager.getPackageInfo(appCtx.packageName, PackageManager.GET_ACTIVITIES)
?.let {
appInfo.versionName = it.versionName
// TODO: 增加测试版还是正式版的检查
if (it.packageName.contains("releaseA")) {
appInfo.appVariant = AppVariant.COMPATIBLE
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
appInfo.versionCode = it.longVersionCode
} else {
@@ -74,7 +80,8 @@ object AppConst {
@Keep
data class AppInfo(
var versionCode: Long = 0L,
var versionName: String = ""
var versionName: String = "",
var appVariant: AppVariant = AppVariant.UNKNOWN
)
/**

View File

@@ -1,49 +1,55 @@
package io.legado.app.help
import androidx.annotation.Keep
import com.google.gson.Gson
import io.legado.app.constant.AppConst
import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.http.newCallStrResponse
import io.legado.app.help.http.okHttpClient
import io.legado.app.utils.channel
import io.legado.app.utils.jsonPath
import io.legado.app.utils.readString
import io.legado.app.model.AppReleaseInfo
import io.legado.app.model.GithubRelease
import io.legado.app.utils.fromJsonArray
import kotlinx.coroutines.CoroutineScope
import splitties.init.appCtx
@Keep
@Suppress("unused")
object AppUpdateGitHub : AppUpdate.AppUpdateInterface {
// TODO:在关于->其他,添加其他版本选项,使用该函数
private suspend fun getRecentReleases(): List<AppReleaseInfo> {
val lastReleaseUrl =
"https://api.github.com/repos/gedoor/legado/releases?page=1?per_page=1"
val body = okHttpClient.newCallStrResponse {
url(lastReleaseUrl)
}.body
if (body.isNullOrBlank()) {
throw NoStackTraceException("获取新版本出错")
}
return Gson().fromJsonArray<GithubRelease>(body)
.getOrElse {
throw NoStackTraceException("获取新版本出错 " + it.localizedMessage)
}
.flatMap { it.gitReleaseToAppReleaseInfo() }
.sortedByDescending { it.createdAt }
}
override fun check(
scope: CoroutineScope,
): Coroutine<AppUpdate.UpdateInfo> {
return Coroutine.async(scope) {
val lastReleaseUrl = "https://api.github.com/repos/gedoor/legado/releases/latest"
val body = okHttpClient.newCallStrResponse {
url(lastReleaseUrl)
}.body
if (body.isNullOrBlank()) {
throw NoStackTraceException("获取新版本出错")
}
val rootDoc = jsonPath.parse(body)
val tagName = rootDoc.readString("$.tag_name")
?: throw NoStackTraceException("获取新版本出错")
if (tagName > AppConst.appInfo.versionName) {
val updateBody = rootDoc.readString("$.body")
?: throw NoStackTraceException("获取新版本出错")
val path = "\$.assets[?(@.name =~ /legado_${appCtx.channel}_.*?apk\$/)]"
val downloadUrl = rootDoc.read<List<String>>("${path}.browser_download_url")
.firstOrNull()
?: throw NoStackTraceException("获取新版本出错")
val fileName = rootDoc.read<List<String>>("${path}.name")
.firstOrNull()
?: throw NoStackTraceException("获取新版本出错")
return@async AppUpdate.UpdateInfo(tagName, updateBody, downloadUrl, fileName)
} else {
throw NoStackTraceException("已是最新版本")
}
val recentReleases = getRecentReleases()
recentReleases
.filter { it.appVariant == AppConst.appInfo.appVariant }
.firstOrNull { it.versionName > AppConst.appInfo.versionName }
?.let {
return@async AppUpdate.UpdateInfo(
it.versionName,
it.note,
it.downloadUrl,
it.name
)
} ?: throw NoStackTraceException("已是最新版本")
}.timeout(10000)
}

View File

@@ -0,0 +1,101 @@
package io.legado.app.model
import com.google.gson.annotations.SerializedName
import java.time.Instant
data class AppReleaseInfo(
val appVariant: AppVariant,
val createdAt: Long,
val note: String,
val name: String,
val downloadUrl: String,
val assetUrl: String
) {
val versionName: String = name.split("_").getOrNull(2)?.removeSuffix(".apk") ?: ""
}
enum class AppVariant {
OFFICIAL,
COMPATIBLE,
BETA_RELEASE,
UNKNOWN
}
data class GithubRelease(
val assets: List<Asset>,
val body: String,
@SerializedName("prerelease")
val isPreLease: Boolean,
) {
fun gitReleaseToAppReleaseInfo(): List<AppReleaseInfo> {
return assets
.filter { it.isValid }
.map { it.assetToAppReleaseInfo(isPreLease, body) }
}
}
data class Asset(
@SerializedName("browser_download_url")
val apkUrl: String,
@SerializedName("content_type")
val contentType: String,
@SerializedName("created_at")
val createdAt: String,
@SerializedName("download_count")
val downloadCount: Int,
val id: Int,
val name: String,
val state: String,
val url: String
) {
val isValid: Boolean
get() = (contentType == "application/vnd.android.package-archive") && (state == "uploaded")
fun assetToAppReleaseInfo(preRelease: Boolean, note: String): AppReleaseInfo {
val instant = Instant.parse(createdAt)
val timestamp: Long = instant.toEpochMilli()
return when {
preRelease && name.contains("releaseA") ->
AppReleaseInfo(
AppVariant.COMPATIBLE,
timestamp,
note,
name,
apkUrl,
url
)
preRelease && name.contains("release") ->
AppReleaseInfo(
AppVariant.BETA_RELEASE,
timestamp,
note,
name,
apkUrl,
url
)
!preRelease && name.contains("release") ->
AppReleaseInfo(
AppVariant.OFFICIAL,
timestamp,
note,
name,
apkUrl,
url
)
else ->
AppReleaseInfo(
AppVariant.UNKNOWN,
timestamp,
note,
name,
apkUrl,
url
)
}
}
}