Quick answer: a package name (
applicationId) is a lowercase, dot-separated identifier such ascom.yourbrand.shopwith at least two segments, each starting with a letter, no hyphens, no Java keywords, and never thecom.exampleprefix. It identifies your app to Android and Google Play and cannot be changed after the first publish.
What depends on it
- The Play listing — its URL is
play.google.com/store/apps/details?id=<package name>. - Updates — Android matches an incoming APK to an installed app by package name, then checks the signature.
- Sandboxing — private storage, preferences and databases live in a directory named after it.
- Everything downstream — deep links, crash reports, analytics, support tickets.
The syntax
| Rule | Rejected | Accepted |
|---|---|---|
| Two or more segments | shop | com.shop |
| Lowercase | com.MyShop | com.myshop |
| Each segment starts with a letter | com.3dprint.app | com.print3d.app |
| Letters, digits, underscores only | com.my-shop.app | com.myshop.app |
| No Java keywords | com.new.app | com.newapp.app |
| Not the sample prefix | com.example.shop | com.yourbrand.shop |
Gradle enforces the first five. Google Play enforces the last, and it is one of the commonest reasons a first upload bounces.
Why the domain is backwards
yourbrand.com becomes com.yourbrand. The habit comes from Java packages and exists to prevent collisions: you control the domain, so nobody else can honestly claim the prefix, so two developers cannot both publish com.yourbrand.shop.
Nothing checks it. No DNS lookup, no hosting requirement — it is a convention that works because it is followed. That is also why inventing a domain you do not own is risky: if someone registers it later and publishes, the conflict is theirs to win.
No domain at all? io.github.yourhandle.appname borrows the uniqueness of a GitHub account and is widely used.
When it is wrong
Syntax errors are cheap — a validator catches them before a build starts.
The expensive error is publishing under a name you later regret, because changing it means:
- a brand-new Play listing;
- zero installs, ratings and reviews carried over;
- existing users are not migrated — they keep the old app until they find the new one;
- the old listing must be unpublished, and its name is retired for everyone, forever.
Choosing well
- Leave room —
com.acme.appages badly;com.acme.shopandcom.acme.trackerdo not. - No years, versions or platforms —
com.acme.shop2026andcom.acme.androidappare permanent in a way you will regret. - Follow the brand, not today's domain — domains change hands; the package name cannot follow.
- Short — it appears in crash logs, file paths, deep links and support emails.
applicationId vs namespace
Modern Gradle splits two ideas that used to be one. namespace is the Kotlin/Java package your source and the generated R class live in; applicationId is the identity Android and Play use. Usually they match:
android {
namespace = "com.acme.shop"
defaultConfig {
applicationId = "com.acme.shop"
}
}
The split is useful for one trick: a .debug suffix on the applicationId lets a development build sit beside the release build instead of replacing it. When anyone asks for your "package name", they mean the applicationId.