Skip to content

fix(android-llmservice): monotonic versionCode for clean in-place upgrades#317

Merged
bernardladenthin merged 1 commit into
mainfrom
claude/android-llmservice-upgrade-versioncode
Jul 10, 2026
Merged

fix(android-llmservice): monotonic versionCode for clean in-place upgrades#317
bernardladenthin merged 1 commit into
mainfrom
claude/android-llmservice-upgrade-versioncode

Conversation

@bernardladenthin

Copy link
Copy Markdown
Owner

Summary

Fixes the "there was a problem parsing the package" / must-uninstall-before-update symptom on the sideloaded app. There are two reasons Android rejects an in-place upgrade; this PR fixes the one that's a code issue and documents the other (which is a CI-secret setup, not code):

  • versionCode was hardcoded to 1 → every APK advertised the same version. Now derived from GITHUB_RUN_NUMBER in CI (strictly increasing per run; -PappVersionCode=<n> overrides; local hand builds fall back to 1), so successive release APKs advertise a higher code and Android accepts the update.
  • Stable signing key (documentation only). Without the upload-key CI secrets the release build falls back to debug signing, and a GitHub-hosted runner generates a fresh random debug key per build → consecutive sideloaded APKs have different signers → Android rejects the update (surfaced as the generic parse error). The fix is to set the existing ANDROID_UPLOAD_KEYSTORE_BASE64 / …_STORE_PASSWORD / …_KEY_ALIAS / …_KEY_PASSWORD CI secrets (the CI wiring already decodes+signs with them) so every build shares one key. The key stays a private secret — never committed (the repo is public; a leaked signing key would let anyone ship a fake update). Documented in README.md ("In-place upgrades") and requirements.md R10.2/R10.4.

No behavior change for local/AndroidStudio builds (still versionCode 1, debug-signed). Docs kept in sync per the requirements.md rule.

Test plan

  • versionCode expression uses the already-present providers.gradleProperty(...) pattern (same as jllamaVersion) + System.getenv("GITHUB_RUN_NUMBER"), fallback 1
  • CI build-android-llmservice compiles the app (Gradle config-time read)
  • Docs updated — README.md + requirements.md

Related issues / PRs

Follow-up to the android-llmservice app work (PRs #310#316). Reported symptom: parse error when updating an already-installed build.

Checklist

  • My commits follow Conventional Commits
  • No security-sensitive changes (the signing key remains a private CI secret; nothing sensitive is committed)

🤖 Generated with Claude Code

https://claude.ai/code/session_01HTS5FpMtBLJENTGoRUrp5m


Generated by Claude Code

…rades

The release build hardcoded versionCode=1, so every APK advertised the
same version — one of the two reasons an in-place upgrade of a sideloaded
build failed (the installer shows the generic 'problem parsing the
package'). versionCode now derives from GITHUB_RUN_NUMBER in CI (strictly
increasing per run; -PappVersionCode overrides; local hand builds use 1).

The other half of clean upgrades is a STABLE signing key across builds:
without the upload-key CI secrets the release falls back to debug signing,
and a GitHub runner generates a fresh random debug key per build, so
consecutive APKs have different signers and Android rejects the update.
Documented in README ('In-place upgrades') and requirements.md R10.2/R10.4;
the actual key stays a private CI secret (never committed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HTS5FpMtBLJENTGoRUrp5m
@sonarqubecloud

Copy link
Copy Markdown

@bernardladenthin bernardladenthin merged commit 96a99b3 into main Jul 10, 2026
13 of 17 checks passed
@bernardladenthin bernardladenthin deleted the claude/android-llmservice-upgrade-versioncode branch July 10, 2026 07:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants