Merge pull request #4044 from h11128/update-version-1

添加共存版的检查更新
This commit is contained in:
Horis
2024-07-25 14:19:57 +08:00
committed by GitHub
18 changed files with 249 additions and 119 deletions
@@ -1,51 +1,54 @@
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.fromJsonObject
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/latest"
private val lastBetaReleaseUrl =
"https://api.github.com/repos/gedoor/legado/releases/tags/beta"
@Test
fun updateApp_beta() {
val body = okHttpClient.newCall(Request.Builder().url(lastBetaReleaseUrl).build()).execute()
.body!!.string()
val releaseList = Gson().fromJsonObject<GithubRelease>(body)
.getOrElse {
throw NoStackTraceException("获取新版本出错 " + it.localizedMessage)
}
.gitReleaseToAppReleaseInfo()
.sortedByDescending { it.createdAt }
assertTrue(releaseList.size == 2)
assertTrue(releaseList.all { it.downloadUrl.isNotBlank() })
assertTrue(releaseList.all { it.versionName.isNotBlank() })
}
@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().fromJsonObject<GithubRelease>(body)
.getOrElse {
throw NoStackTraceException("获取新版本出错 " + it.localizedMessage)
}
.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.size == 1)
assertTrue(releaseList.all { it.downloadUrl.isNotBlank() })
assertTrue(releaseList.all { it.versionName.isNotBlank() })
}
}
@@ -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.BETA_RELEASEA
}
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
)
/**
@@ -145,7 +145,7 @@ object PreferKey {
const val mouseWheelPage = "mouseWheelPage"
const val recordHeapDump = "recordHeapDump"
const val optimizeRender = "optimizeRender"
const val updateToBeta = "updateToBeta"
const val updateToVariant = "updateToVariant"
const val cPrimary = "colorPrimary"
const val cAccent = "colorAccent"
@@ -23,8 +23,6 @@ object AppUpdate {
fun check(scope: CoroutineScope): Coroutine<UpdateInfo>
fun checkBeta(scope: CoroutineScope): Coroutine<UpdateInfo>
}
}
@@ -1,83 +1,67 @@
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.config.AppConfig
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.AppVariant
import io.legado.app.model.GithubRelease
import io.legado.app.utils.fromJsonObject
import kotlinx.coroutines.CoroutineScope
import splitties.init.appCtx
@Keep
@Suppress("unused")
object AppUpdateGitHub : AppUpdate.AppUpdateInterface {
private val checkVariant: AppVariant
get() = when (AppConfig.updateToVariant) {
"official_version" -> AppVariant.OFFICIAL
"beta_release_version" -> AppVariant.BETA_RELEASE
"beta_releaseA_version" -> AppVariant.BETA_RELEASEA
else -> AppConst.appInfo.appVariant
}
private suspend fun getLatestRelease(): List<AppReleaseInfo> {
val lastReleaseUrl = if (checkVariant.name.lowercase().contains("beta")) {
"https://api.github.com/repos/gedoor/legado/releases/tags/beta"
} else {
"https://api.github.com/repos/gedoor/legado/releases/latest"
}
val body = okHttpClient.newCallStrResponse {
url(lastReleaseUrl)
}.body
if (body.isNullOrBlank()) {
throw NoStackTraceException("获取新版本出错")
}
return Gson().fromJsonObject<GithubRelease>(body)
.getOrElse {
throw NoStackTraceException("获取新版本出错 " + it.localizedMessage)
}
.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("已是最新版本")
}
getLatestRelease()
.filter { it.appVariant == checkVariant }
.firstOrNull { it.versionName > AppConst.appInfo.versionName }
?.let {
return@async AppUpdate.UpdateInfo(
it.versionName,
it.note,
it.downloadUrl,
it.name
)
}
?: throw NoStackTraceException("已是最新版本")
}.timeout(10000)
}
override fun checkBeta(scope: CoroutineScope): Coroutine<AppUpdate.UpdateInfo> {
return Coroutine.async(scope) {
val preReleaseUrl = "https://api.github.com/repos/gedoor/legado/releases/tags/beta"
val body = okHttpClient.newCallStrResponse {
url(preReleaseUrl)
}.body
if (body.isNullOrBlank()) {
throw NoStackTraceException("获取新版本出错")
}
val rootDoc = jsonPath.parse(body)
val path = "\$.assets[?(@.name =~ /legado_${appCtx.channel}_.*?apk\$/)]"
val name = rootDoc.readString("$.name")
?: throw NoStackTraceException("获取新版本出错")
val tagName = name.replace("legado_app_", "")
if (tagName > AppConst.appInfo.versionName) {
val assetsMap = rootDoc.read<List<Any>>(path)
.firstOrNull()
?: throw NoStackTraceException("获取新版本出错")
val assets = jsonPath.parse(assetsMap)
val updateBody = rootDoc.readString("$.body")
?: throw NoStackTraceException("获取新版本出错")
val downloadUrl = assets.readString("$.browser_download_url")
?: throw NoStackTraceException("获取新版本出错")
val fileName = assets.readString("$.name")
?: throw NoStackTraceException("获取新版本出错")
return@async AppUpdate.UpdateInfo(tagName, updateBody, downloadUrl, fileName)
} else {
throw NoStackTraceException("已是最新版本")
}
}.timeout(10000)
}
}
@@ -471,7 +471,7 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
val defaultHomePage get() = appCtx.getPrefString(PreferKey.defaultHomePage, "bookshelf")
val updateToBeta get() = appCtx.getPrefBoolean(PreferKey.updateToBeta, false)
val updateToVariant get() = appCtx.getPrefString(PreferKey.updateToVariant, "default_version")
val doublePageHorizontal: String?
get() = appCtx.getPrefString(PreferKey.doublePageHorizontal)
@@ -0,0 +1,91 @@
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,
BETA_RELEASEA,
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.BETA_RELEASEA,
timestamp,
note,
name,
apkUrl,
url
)
preRelease && name.contains("release") ->
AppReleaseInfo(
AppVariant.BETA_RELEASE,
timestamp,
note,
name,
apkUrl,
url
)
else ->
AppReleaseInfo(
AppVariant.OFFICIAL,
timestamp,
note,
name,
apkUrl,
url
)
}
}
}
@@ -88,20 +88,16 @@ class AboutFragment : PreferenceFragmentCompat() {
private fun checkUpdate() {
waitDialog.show()
AppUpdate.gitHubUpdate?.run {
val job = if (AppConfig.updateToBeta) {
checkBeta(lifecycleScope)
} else {
check(lifecycleScope)
}
job.onSuccess {
showDialogFragment(
UpdateDialog(it)
)
}.onError {
appCtx.toastOnUi("${getString(R.string.check_update)}\n${it.localizedMessage}")
}.onFinally {
waitDialog.dismiss()
}
check(lifecycleScope)
.onSuccess {
showDialogFragment(
UpdateDialog(it)
)
}.onError {
appCtx.toastOnUi("${getString(R.string.check_update)}\n${it.localizedMessage}")
}.onFinally {
waitDialog.dismiss()
}
}
}
@@ -1155,4 +1155,8 @@
<string name="start_chapter">Cap. inicio</string>
<string name="update_to_bata_title">更新至测试版</string>
<string name="update_to_bata_summary">检查更新时查找最新的测试版本</string>
<string name="default_version">当前</string>
<string name="official_version">正式版</string>
<string name="beta_release_version">测试版</string>
<string name="beta_releaseA_version">共存版</string>
</resources>
@@ -1158,4 +1158,8 @@
<string name="start_chapter">開始の章</string>
<string name="update_to_bata_title">更新至测试版</string>
<string name="update_to_bata_summary">检查更新时查找最新的测试版本</string>
<string name="default_version">当前</string>
<string name="official_version">正式版</string>
<string name="beta_release_version">测试版</string>
<string name="beta_releaseA_version">共存版</string>
</resources>
@@ -1158,4 +1158,8 @@
<string name="start_chapter">Início</string>
<string name="update_to_bata_title">更新至测试版</string>
<string name="update_to_bata_summary">检查更新时查找最新的测试版本</string>
<string name="default_version">当前</string>
<string name="official_version">正式版</string>
<string name="beta_release_version">测试版</string>
<string name="beta_releaseA_version">共存版</string>
</resources>
+4
View File
@@ -1154,4 +1154,8 @@ Còn </string>
<string name="start_chapter">Chương đầu</string>
<string name="update_to_bata_title">更新至测试版</string>
<string name="update_to_bata_summary">检查更新时查找最新的测试版本</string>
<string name="default_version">当前</string>
<string name="official_version">正式版</string>
<string name="beta_release_version">测试版</string>
<string name="beta_releaseA_version">共存版</string>
</resources>
@@ -1155,4 +1155,8 @@
<string name="start_chapter">開始篇章</string>
<string name="update_to_bata_title">更新至测试版</string>
<string name="update_to_bata_summary">检查更新时查找最新的测试版本</string>
<string name="default_version">当前</string>
<string name="official_version">正式版</string>
<string name="beta_release_version">测试版</string>
<string name="beta_releaseA_version">共存版</string>
</resources>
@@ -1157,4 +1157,8 @@
<string name="start_chapter">開始篇章</string>
<string name="update_to_bata_title">更新至测试版</string>
<string name="update_to_bata_summary">检查更新时查找最新的测试版本</string>
<string name="default_version">当前</string>
<string name="official_version">正式版</string>
<string name="beta_release_version">测试版</string>
<string name="beta_releaseA_version">共存版</string>
</resources>
+6 -2
View File
@@ -1155,6 +1155,10 @@
<string name="start_from">开始日期</string>
<string name="daily_chapters">日更章数</string>
<string name="start_chapter">起始章节</string>
<string name="update_to_bata_title">更新至测试版</string>
<string name="update_to_bata_summary">检查更新查找最新的测试版本</string>
<string name="update_to_bata_title">检查更新查找版本</string>
<string name="update_to_bata_summary">检查更新查找其他签名版本</string>
<string name="default_version">当前</string>
<string name="official_version">正式版</string>
<string name="beta_release_version">测试版</string>
<string name="beta_releaseA_version">共存版</string>
</resources>
+15
View File
@@ -151,6 +151,14 @@
<item>@string/my</item>
</string-array>
<string-array name="default_app_variant">
<item>@string/default_version</item>
<item>@string/official_version</item>
<item>@string/beta_release_version</item>
<item>@string/beta_releaseA_version</item>
</string-array>
<string-array name="default_home_page_value">
<item>bookshelf</item>
<item>explore</item>
@@ -158,6 +166,13 @@
<item>my</item>
</string-array>
<string-array name="default_app_variant_value">
<item>default_version</item>
<item>official_version</item>
<item>beta_release_version</item>
<item>beta_releaseA_version</item>
</string-array>
<string-array name="tip_color">
<item>Same color as content</item>
<item>Customize</item>
+4
View File
@@ -1158,4 +1158,8 @@
<string name="start_chapter">Start Chapter</string>
<string name="update_to_bata_title">更新至测试版</string>
<string name="update_to_bata_summary">检查更新时查找最新的测试版本</string>
<string name="default_version">当前</string>
<string name="official_version">正式版</string>
<string name="beta_release_version">测试版</string>
<string name="beta_releaseA_version">共存版</string>
</resources>
+8 -4
View File
@@ -146,11 +146,15 @@
android:summary="@string/show_add_to_shelf_alert_summary"
android:title="@string/show_add_to_shelf_alert_title" />
<io.legado.app.lib.prefs.SwitchPreference
android:defaultValue="false"
android:key="updateToBeta"
<io.legado.app.lib.prefs.NameListPreference
android:defaultValue="default_version"
android:key="updateToVariant"
android:summary="@string/update_to_bata_summary"
android:title="@string/update_to_bata_title" />
android:title="@string/update_to_bata_title"
app:allowDividerAbove="false"
app:allowDividerBelow="false"
app:entries="@array/default_app_variant"
app:entryValues="@array/default_app_variant_value" />
<io.legado.app.lib.prefs.Preference
android:key="webPort"