Publish a fixed-name APK so the latest build has a permanent link

GitHub's /releases/latest/download/<name> redirect needs a file name
that stays put, and the release asset is named after its version. Each
production release now carries the same build twice: the versioned copy,
and a plain ProLibertateGames.apk, which makes this link permanent:

  .../releases/latest/download/ProLibertateGames.apk

Only the production channel gets one. /releases/latest skips
prereleases, which is exactly what stops a production install being
handed a dev build, so there is no equivalent dev link to offer.

The updater now picks its asset by name rather than taking the first
.apk it sees. Both copies are byte-identical, so nothing would have
broken either way, but relying on upload order for which file gets
installed is not something to leave lying around.
This commit is contained in:
Claude
2026-08-06 15:33:44 +00:00
parent d6e237ce4a
commit 331a620f83
3 changed files with 46 additions and 15 deletions
@@ -120,20 +120,25 @@ class Updater(private val activity: Activity) {
}
val assets = json.optJSONArray("assets") ?: return null
for (i in 0 until assets.length()) {
val asset = assets.getJSONObject(i)
val name = asset.optString("name")
if (name.endsWith(".apk")) {
return Release(
tag = tag,
versionCode = versionCode,
apkUrl = asset.getString("browser_download_url"),
apkName = name,
channel = channel,
)
}
}
return null
val apks = (0 until assets.length())
.map { assets.getJSONObject(it) }
.filter { it.optString("name").endsWith(".apk") }
// A production release carries the same build twice: once named for its
// version, and once under a fixed name so a permanent download link
// exists. Pick the versioned one explicitly rather than whichever was
// uploaded first, so what gets installed is traceable to its tag.
val chosen = apks.firstOrNull { it.optString("name").contains(tag) }
?: apks.firstOrNull()
?: return null
return Release(
tag = tag,
versionCode = versionCode,
apkUrl = chosen.getString("browser_download_url"),
apkName = chosen.optString("name"),
channel = channel,
)
}
private fun openConnection(url: String): HttpURLConnection =