A label and a counter
Android apps carry two version fields that do unrelated jobs, and confusing them is a classic cause of a rejected Play upload.
versionName— a string for people:1.4.2,2.0-beta,Winter update. It shows on the store listing and in Settings. Android never compares it.versionCode— an integer for the system. It is the only thing Android and Play look at to decide which build is newer. Users never see it.
The rule that follows: every upload needs a higher versionCode than any you have used before — higher, not different. Play remembers every code, including those from deleted releases and internal test tracks.
Choosing a scheme
| Scheme | Example | Strength | Limit |
|---|---|---|---|
| Counter | 14 | Cannot overflow or confuse | Says nothing on its own |
| Semantic | 1.4.2 → 10402 | Readable from a crash report | Minor and patch cap at 99 |
| Date | 260911 | Self-dating, sortable | One release per day |
| Date + build | 26091101 | Up to 100 builds a day | Passes the ceiling in 2042 |
Undecided? Use the counter. The code is not documentation; its one job is to go up. Semantic codes earn their keep when you want to read the release off a crash log without a lookup.
The 2,100,000,000 ceiling
Play refuses any version code above 2,100,000,000. A scheme such as yyyyMMddHH produces 2026091114 today — already too large. Any four-digit year followed by more than four digits breaks; the calculator flags it as soon as your inputs cross the line.
The mistake that costs a release cycle
"Version code N has already been used" has one exit: a bigger number. Two habits avoid it — bump the code in the same commit as the change rather than from memory at upload time, and if you use per-ABI splits, multiply your logical code by ten so the variants fit in the units digit.
What users experience
A higher code with a matching signature installs as an update and keeps data, databases and preferences. A lower or equal code is refused, which is why sideloading an older APK over a newer one fails with a downgrade or parse error. Uninstalling first works but wipes the app's data — and an APK signed with a different key can never update, whatever the numbers say.
In the HTML to App builder the version name and code are two fields on the package step, doing exactly these two jobs.