Skip to content

App update: one download at a time, each in its own file - #7

Merged
ProjectZero02 merged 1 commit into
mainfrom
app-update-once
Oct 27, 2026
Merged

ProjectZero02 merged 1 commit into
mainfrom
app-update-once

Conversation

@ProjectZero02

Copy link
Copy Markdown
Owner

Right after 2.2.1 was published, the phone's in-app update failed with "The download is corrupt (checksum mismatch)".

The release is fine. Downloading v2.2.1/PowerDeck.apk here gives the same SHA-256 that GitHub's asset digest and SHA256SUMS.txt list (ebb9c1c5…871a6c), including with OkHttp's request headers through the redirect.

Cause (app side).

  • Every tap on Update launched a new coroutine downloading into the same cacheDir/update.apk. That includes the home banner, the Settings row and the Settings button.
  • Nothing showed that a download was running, so a second tap was easy.
  • Two downloads at once truncated and overwrote each other's file, and the checksum check then failed. A finished one could also delete the file while the other was still reading it.

Fix.

  • MainViewModel.installUpdate runs one download at a time with the new state AppCheck.Downloading. The home banner reads "Downloading PowerDeck X…" with no button; Settings shows the same with a spinner.
  • Updater.download puts each download in a temp file of its own and hashes it as it streams, with no second read of the whole file.
  • A download that doesn't match is retried once, and a damaged copy is always deleted.
  • The message after two damaged downloads says to tap Update again.

Tests (UpdaterTest, MockWebServer with a throttled 512 KB body):

  • a clean download comes back intact, with no stray files;
  • a damaged download is retried, and the damaged copy is removed;
  • a download damaged twice fails with the checksum message and leaves nothing behind;
  • two downloads at once both come back intact in separate files. With the old shared update.apk this test fails, which I checked by putting the old line back.

Android unit tests: 67, all passing, and the screenshots are unchanged.

🤖 Generated with Claude Code

Every tap on Update (home banner, Settings row, Settings button)
launched a download into the same cache file. Two at once overwrote
each other and the checksum check failed with "The download is
corrupt".

Now the view model runs one download at a time and the banner and
Settings show it's downloading. Each download goes to a temp file of
its own and is hashed as it streams, and a damaged download is retried
once. Tests cover a clean download, a damaged one that's retried, one
damaged twice, and two downloads at once (which fails on the old
shared file).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ProjectZero02
ProjectZero02 merged commit 20b964b into main Oct 27, 2026
6 checks passed
@ProjectZero02
ProjectZero02 deleted the app-update-once branch October 27, 2026 20:24
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.

1 participant