Skip to content

Commit fe8936f

Browse files
kasnderclaude
andauthored
Fix release asset ordering so the in-app updater fetches the APK (#686)
* Fix release asset ordering so the in-app updater fetches the APK GitHub's API returns release assets sorted by name, not upload order. The app's checkUpdate() always downloads assets[0], so once build_and_sign.sh started attaching SHA256SUMS.txt and BUILD-INFO.txt alongside the APK, those alphabetically-earlier names could be picked up instead of the APK (#681). Rename the metadata files using the APK filename as a literal prefix so it always sorts first. * Show release version name in update notification, not asset filename checkUpdate() already opened the release's html_url (the GitHub release page) rather than a direct asset link, so tapping the notification was never downloading a raw file. But its title used the first release asset's filename, which is confusing and, per #681, could be a metadata file rather than the APK depending on asset ordering. Use the release's display name (e.g. "Version 2026072702") instead, falling back to a formatted tag if the release has no name. --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent f9b17c1 commit fe8936f

4 files changed

Lines changed: 31 additions & 17 deletions

File tree

app/src/main/java/eu/faircode/netguard/ServiceSinkhole.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -803,22 +803,24 @@ private void checkUpdate() {
803803
JSONObject jroot = jarray.getJSONObject(0);
804804
// JSONObject jroot = new JSONObject(json.toString());
805805
if (jroot.has("tag_name") && jroot.has("html_url") && jroot.has("assets")) {
806+
// Always link to the release page rather than a specific
807+
// asset: the user picks the right download there, and
808+
// the notification doesn't depend on asset ordering.
806809
String url = jroot.getString("html_url");
807810
JSONArray jassets = jroot.getJSONArray("assets");
808811
if (jassets.length() > 0) {
809-
JSONObject jasset = jassets.getJSONObject(0);
810-
if (jasset.has("name")) {
811-
long available = jroot.getLong("tag_name");
812-
String name = jasset.getString("name");
813-
Log.i(TAG, "Tag " + available + " name " + name + " url " + url);
814-
815-
long current = Util.getSelfVersionCode(ServiceSinkhole.this);
816-
if (current < available) {
817-
Log.i(TAG, "Update available from " + current + " to " + available);
818-
showUpdateNotification(name, url);
819-
} else
820-
Log.i(TAG, "Up-to-date current version " + current);
821-
}
812+
long available = jroot.getLong("tag_name");
813+
String name = (jroot.has("name") && !jroot.isNull("name") && jroot.getString("name").length() > 0)
814+
? jroot.getString("name")
815+
: getString(R.string.title_version, available);
816+
Log.i(TAG, "Tag " + available + " name " + name + " url " + url);
817+
818+
long current = Util.getSelfVersionCode(ServiceSinkhole.this);
819+
if (current < available) {
820+
Log.i(TAG, "Update available from " + current + " to " + available);
821+
showUpdateNotification(name, url);
822+
} else
823+
Log.i(TAG, "Up-to-date current version " + current);
822824
}
823825
}
824826
} catch (JSONException ex) {

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ Your internet traffic is not being sent to a remote VPN server.</string>
346346
<string name="msg_inactive">No active internet connection</string>
347347
<string name="msg_queue">TrackerControl is busy</string>
348348
<string name="msg_update">Update available, tap to download</string>
349+
<string name="title_version">Version %1$d</string>
349350
<string name="msg_usage">You can allow (greenish) or deny (reddish) Wi-Fi or mobile internet access by tapping on the icons next to an app</string>
350351
<string name="msg_push">Incoming (push) messages are mostly handled by the system component Play services, which is allowed internet access by default</string>
351352
<string name="msg_system">Managing all (system) apps can be enabled in the settings</string>

docs/RELEASING.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,14 @@ The script writes the signed APK and verification metadata to
6565
`output/release-2026071301/` and creates a draft GitHub release containing:
6666

6767
- `TrackerControl-githubRelease-latest.apk`
68-
- `SHA256SUMS.txt`
69-
- `BUILD-INFO.txt`
68+
- `TrackerControl-githubRelease-latest.apk.sha256sums`
69+
- `TrackerControl-githubRelease-latest.apk.build-info.txt`
70+
71+
The two metadata files are named with the APK filename as a prefix so they
72+
always sort alphabetically after it. The GitHub API returns release assets
73+
ordered by name, and the app's in-app update checker always downloads
74+
`assets[0]`; without this ordering it can fetch `BUILD-INFO.txt` instead of
75+
the APK (#681).
7076

7177
Install and test the APK from the draft, then publish the release in GitHub.
7278

scripts/build_and_sign.sh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,14 @@ readonly OUTPUT_DIR=${RELEASE_OUTPUT_DIR:-"$ROOT/output/release-$TAG"}
130130
mkdir -p "$OUTPUT_DIR"
131131
readonly ALIGNED_APK="$TEMP_DIR/TrackerControl-githubRelease-aligned.apk"
132132
readonly TEMP_SIGNED_APK="$TEMP_DIR/TrackerControl-githubRelease-signed.apk"
133+
# Asset names must sort alphabetically after the APK: the GitHub API
134+
# returns release assets ordered by name, and the app's update checker
135+
# (ServiceSinkhole#checkUpdate) always takes assets[0] as the download.
136+
# Using the APK filename as a literal prefix guarantees it sorts first
137+
# under any lexicographic comparison, regardless of case-folding rules.
133138
readonly SIGNED_APK="$OUTPUT_DIR/TrackerControl-githubRelease-latest.apk"
134-
readonly SIGNED_SUMS="$OUTPUT_DIR/SHA256SUMS.txt"
135-
readonly OUTPUT_BUILD_INFO="$OUTPUT_DIR/BUILD-INFO.txt"
139+
readonly SIGNED_SUMS="$OUTPUT_DIR/TrackerControl-githubRelease-latest.apk.sha256sums"
140+
readonly OUTPUT_BUILD_INFO="$OUTPUT_DIR/TrackerControl-githubRelease-latest.apk.build-info.txt"
136141
[[ ! -e $SIGNED_APK ]] || fail "signed output already exists: $SIGNED_APK"
137142

138143
printf 'Aligning and signing the APK...\n'

0 commit comments

Comments
 (0)