Why You Can't Switch Between Your APK and the F-Droid Build

F-Droid builds Photo Sweep from source on its own infrastructure and signs it with its own key. That one fact means two APKs of the same commit will never be interchangeable.

Why You Can't Switch Between Your APK and the F-Droid Build

The single most useful sentence in F-Droid's own documentation, for anyone submitting an app they also distribute themselves, is this one: they build from source on their own infrastructure, and they sign with their own key, not yours.

One codebase, two APKs that will never be the same file
One codebase, two APKs that will never be the same file

Same source commit, different signing key — that's the whole story.

What this means in practice

Photo Sweep ships a signed APK from GitHub Releases, built and signed by me, tagged android-v1.0.1. F-Droid, once the inclusion request is accepted, takes that same source, rebuilds it on their build servers, and signs the result with a key that belongs to F-Droid, not to me.

The two resulting APKs share a git commit and, ideally, byte-identical application behavior. They do not share a signature. Android treats signature mismatch as a hard boundary: it will not let you install an update over an existing app if the signing key doesn't match. A user running my GitHub-Releases build who later installs the F-Droid version — or the other way around — has to uninstall first. There's no update path between them.

Why this isn't a bug to fix

It would be tempting to think of this as a packaging problem to solve, the way you'd solve a build reproducibility issue. It isn't one, and there's no configuration that unifies it. F-Droid's entire trust model rests on not trusting upstream-provided binaries — they rebuild from source specifically so that what users install has passed through F-Droid's own pipeline, verifiable against the source tree, rather than through a binary I could have altered before uploading. Signing with their key is the mechanism that makes that model function. Signing with mine would defeat the purpose of using F-Droid at all.

So the two-signature situation isn't a rough edge in the onboarding process. It's the feature working as intended, seen from the wrong angle.

What it costs, concretely

For Photo Sweep specifically, the cost is small but real:

  • Anyone who installed the app before F-Droid inclusion, then later wants to move to the F-Droid-maintained build for its auto-update convenience, has to do a manual uninstall/reinstall once. Their local data — cached verdicts, the encrypted app password — doesn't survive that in general, though because sign-in uses Login Flow v2 and hands back a revocable per-device password, re-authenticating afterward is a few taps against their own Nextcloud login page, not a support ticket.
  • I can't quietly push a hotfix build that reaches both audiences at once. GitHub-Releases users get whatever I tag and publish there; F-Droid users get whatever F-Droid's build pipeline picks up and signs, on F-Droid's own timeline, independent of mine.
  • Version numbering has to stay meaningful across both, which is straightforward here because versionCode and versionName are both derived from the git tag — there's no separate "F-Droid build number" to keep in sync by hand.

The plainly-stated version

If anyone asks why they can't just flip between the two builds: F-Droid builds from source and signs with its own key, so the two APKs are cryptographically different artifacts even when they come from the same commit. That's normal for every app on F-Droid, not specific to this one, and it's worth saying in exactly those words rather than letting it read as a bug report.

Series: Launching Photo Sweep.