Why the Android app is a file on the website, and how to know it is ours
Most Android apps arrive through a store that vouches for them. EasyDooo arrives as a file from easydooo.com/download, with a hash next to it, and a page that tells you how to let your phone install something from outside the store. This is why it is built that way, what vouches for the file instead, and the costs we accept for it.
Why not the store, yet
A store listing is deferred, not refused. Shipping from the website means a release goes out the moment it is built, with no review queue, and the purchase stays on the website with no store fee. The price is paid by the person installing: Android asks them to allow installs from an unknown source once, and the app cannot update itself, only announce that an update exists.
One manifest owns the link
A hand-maintained list in the backend names every release: version, size, hash, where the file is, and the notes. Three things read it. The download page renders the version, the size and the SHA-256. The download link itself is a route that redirects to the file, so the file can move hosts without the page or any installed app changing. And the app's own update check reads the same list to decide whether to show the update banner.
A half-published release never looks live
An entry is committed before the file is uploaded, with a placeholder where the address goes. While the placeholder is there, the download page shows a disabled button that says the file has not been uploaded yet, the download route answers 404, and the update check tells phones nothing. A validation at import fails the build on an entry that is half filled in, so a release cannot be published by accident or in part.
What vouches for the file
Nothing between the site and your phone does, so the page prints the SHA-256 of the exact bytes and shows the one-line command to check it. Every APK is signed with one key, and that key is the app's identity on your phone: Android refuses an update signed with a different key. A test in the backend reads the three files the deployment serves and checks each one's size and hash against the manifest on every run, so the page cannot promise a hash the file does not have.
Newest three, nowhere else
The files are static files of the website's own deployment, three at a time: the newest release and the two before it. Each is about sixty-seven megabytes, every one ever committed stays in the repository's history, and the file host's quotas are the website's quotas. Each name is served as immutable for a year, so a rebuilt file must take a new name; the same name may never carry different bytes.
What this costs
- The person installing has to allow installs from an unknown source once, and has to trust a hash rather than a store badge.
- No automatic updates. The app shows a banner; the person taps it and installs the new file over the old one.
- Only the three newest versions can be downloaded. A direct link to an older file stops working when it drops off.
- The signing key is the whole identity. Lose it or replace it and every user has to uninstall, losing what the phone held locally.