diff --git a/app/src/androidTest/java/io/legado/app/UpdateTest.kt b/app/src/androidTest/java/io/legado/app/UpdateTest.kt index 60d3163c3..f9f1ac0a0 100644 --- a/app/src/androidTest/java/io/legado/app/UpdateTest.kt +++ b/app/src/androidTest/java/io/legado/app/UpdateTest.kt @@ -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(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>("\$.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>("\$.assets[?(@.name =~ /legado_lollipop_.*?apk\$/)].browser_download_url") - print(downloadUrl) - } + val releaseList = Gson().fromJsonObject(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>("${path}.browser_download_url") - .firstOrNull() - ?: throw NoStackTraceException("获取新版本出错") - val fileName = rootDoc.read>("${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() }) } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/constant/AppConst.kt b/app/src/main/java/io/legado/app/constant/AppConst.kt index fb020a164..8d627b8af 100644 --- a/app/src/main/java/io/legado/app/constant/AppConst.kt +++ b/app/src/main/java/io/legado/app/constant/AppConst.kt @@ -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 ) /** diff --git a/app/src/main/java/io/legado/app/constant/PreferKey.kt b/app/src/main/java/io/legado/app/constant/PreferKey.kt index c389e90a3..5c5ec94d6 100644 --- a/app/src/main/java/io/legado/app/constant/PreferKey.kt +++ b/app/src/main/java/io/legado/app/constant/PreferKey.kt @@ -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" diff --git a/app/src/main/java/io/legado/app/help/AppUpdate.kt b/app/src/main/java/io/legado/app/help/AppUpdate.kt index 967795f32..af9b572f8 100644 --- a/app/src/main/java/io/legado/app/help/AppUpdate.kt +++ b/app/src/main/java/io/legado/app/help/AppUpdate.kt @@ -23,8 +23,6 @@ object AppUpdate { fun check(scope: CoroutineScope): Coroutine - fun checkBeta(scope: CoroutineScope): Coroutine - } } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/AppUpdateGitHub.kt b/app/src/main/java/io/legado/app/help/AppUpdateGitHub.kt index 0fa0ee2a1..7bc860713 100644 --- a/app/src/main/java/io/legado/app/help/AppUpdateGitHub.kt +++ b/app/src/main/java/io/legado/app/help/AppUpdateGitHub.kt @@ -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 { + 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(body) + .getOrElse { + throw NoStackTraceException("获取新版本出错 " + it.localizedMessage) + } + .gitReleaseToAppReleaseInfo() + .sortedByDescending { it.createdAt } + } + override fun check( scope: CoroutineScope, ): Coroutine { 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>("${path}.browser_download_url") - .firstOrNull() - ?: throw NoStackTraceException("获取新版本出错") - val fileName = rootDoc.read>("${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 { - 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>(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) - } - - } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/config/AppConfig.kt b/app/src/main/java/io/legado/app/help/config/AppConfig.kt index ad945b350..ed3a3f43f 100644 --- a/app/src/main/java/io/legado/app/help/config/AppConfig.kt +++ b/app/src/main/java/io/legado/app/help/config/AppConfig.kt @@ -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) diff --git a/app/src/main/java/io/legado/app/model/AppReleaseInfo.kt b/app/src/main/java/io/legado/app/model/AppReleaseInfo.kt new file mode 100644 index 000000000..eefa68a07 --- /dev/null +++ b/app/src/main/java/io/legado/app/model/AppReleaseInfo.kt @@ -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, + val body: String, + @SerializedName("prerelease") + val isPreLease: Boolean, +) { + fun gitReleaseToAppReleaseInfo(): List { + 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 + ) + + } + } +} diff --git a/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt b/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt index 1760138de..0fa7cb546 100644 --- a/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt +++ b/app/src/main/java/io/legado/app/ui/about/AboutFragment.kt @@ -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() + } } } diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index fc7ef944e..44aaf4d31 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -1155,4 +1155,8 @@ Cap. inicio 更新至测试版 检查更新时查找最新的测试版本 + 当前 + 正式版 + 测试版 + 共存版 diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 341968180..068b8bb4c 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -1158,4 +1158,8 @@ 開始の章 更新至测试版 检查更新时查找最新的测试版本 + 当前 + 正式版 + 测试版 + 共存版 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index d285259b8..77b7fe71c 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1158,4 +1158,8 @@ Início 更新至测试版 检查更新时查找最新的测试版本 + 当前 + 正式版 + 测试版 + 共存版 diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 6e7446aec..9510deecb 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -1154,4 +1154,8 @@ Còn Chương đầu 更新至测试版 检查更新时查找最新的测试版本 + 当前 + 正式版 + 测试版 + 共存版 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 3f3d3847e..075c75f24 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -1155,4 +1155,8 @@ 開始篇章 更新至测试版 检查更新时查找最新的测试版本 + 当前 + 正式版 + 测试版 + 共存版 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 630fafed1..cddf82c8b 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1157,4 +1157,8 @@ 開始篇章 更新至测试版 检查更新时查找最新的测试版本 + 当前 + 正式版 + 测试版 + 共存版 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 640a4128d..764d8dce9 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1155,6 +1155,10 @@ 开始日期 日更章数 起始章节 - 更新至测试版 - 检查更新时查找最新的测试版本 + 检查更新查找版本 + 检查更新查找其他签名版本 + 当前 + 正式版 + 测试版 + 共存版 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 2d3e5a0f1..5dc6bc30b 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -151,6 +151,14 @@ @string/my + + + @string/default_version + @string/official_version + @string/beta_release_version + @string/beta_releaseA_version + + bookshelf explore @@ -158,6 +166,13 @@ my + + default_version + official_version + beta_release_version + beta_releaseA_version + + Same color as content Customize diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 23643bbfb..fe8fea950 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1158,4 +1158,8 @@ Start Chapter 更新至测试版 检查更新时查找最新的测试版本 + 当前 + 正式版 + 测试版 + 共存版 diff --git a/app/src/main/res/xml/pref_config_other.xml b/app/src/main/res/xml/pref_config_other.xml index 650f070ad..cf3a05dbe 100644 --- a/app/src/main/res/xml/pref_config_other.xml +++ b/app/src/main/res/xml/pref_config_other.xml @@ -146,11 +146,15 @@ android:summary="@string/show_add_to_shelf_alert_summary" android:title="@string/show_add_to_shelf_alert_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" />