Tutorials Search / Shipping & infrastructure / Upload an Android app to Google Play for the first time
📝 Written ● Advanced Updated 2026-05-13

Upload an Android app to Google Play for the first time

From signed AAB to live Play Store listing. The upload itself is one click; everything around it — the signing key choice, the tracks, the metadata, the review wait — is where first-time publishers get stuck. This is the path through, written for someone who has shipped zero Android apps.

The Google Play upload pipeline is conceptually simpler than Apple's but practically heavier. Simpler because the binary itself ships immediately to your testers — there's no provisioning-profile dance, no entitlements file, no separate "development" vs "distribution" build. Heavier because Google asks you to fill out more paperwork than Apple does: a content rating questionnaire, a data safety form, target audience declarations, ad declarations, and government-ID verification for the developer account. Most of the first-time time isn't in the build; it's in the metadata.

The mental model that makes the rest comprehensible: you have a signing key that proves "this update came from the same publisher as the previous one." If you lose it, you can't update your app — ever. Play App Signing (Google's recommendation since 2017) splits this into two keys: an upload key on your machine that you can rotate if compromised, and an app signing key Google holds and uses to sign the actual binary that ships to devices. You almost always want Play App Signing unless you have a strong reason not to. The other half of the model is tracks: internal → closed → open → production, each with progressively more reach. You ship to internal first (up to 100 named testers, instantaneous), then closed (a private invite list, an hour to roll out), then open (anyone with the link), then production (everyone). Most first uploads go internal → fix things → production over a week.

This tutorial covers the one-time account setup, the signing-key decision, the first AAB build, the metadata required to even submit, the internal-track upload, and what to do when the review comes back asking questions. End state: your app live on the Play Store, downloadable to any Android device.

What you'll learn

Prerequisites: An Android app that builds and runs on an emulator (AVD tutorial), a Google account, $25 USD for the one-time developer registration fee, a government-issued ID (passport / driver's license — Google requires personal verification for new accounts since 2023), a 1024×500 feature graphic, an app icon (512×512 PNG), and at least 2 phone screenshots (16:9 portrait or landscape). The screenshots are the part most people forget until they're already at the upload screen.

Step 1: Create a Play Console developer account

1

One-time $25, government-ID verification

Go to play.google.com/console/signup. Sign in with the Google account you want to own the app. Pick Personal or Organization:

  • Personal — you're an individual publisher. Government ID verification required.
  • Organization — a company entity owns the apps. Requires a D-U-N-S number for the business plus a verifiable phone number tied to the organization. Slower verification (1–2 weeks) but lets you publish as a brand instead of a person.

Pay the $25 (lifetime fee — you can publish as many apps as you want on this account forever). Submit the ID. Wait for verification — usually 48 hours for personal accounts, longer for organizations.

The "20 testers for 14 days" rule (new in 2024). Personal-account first-time publishers must enroll 20 closed-track testers and run the app on the closed track for at least 14 days before being allowed to push to production. Plan for this: start the closed test the same day your account is verified, even if the app is unfinished. The 14 days run in parallel with you finishing the metadata. Organization accounts are exempt from this rule.

Step 2: Decide on signing strategy

2

Almost everyone should pick Play App Signing

You're choosing one of two patterns:

  • Play App Signing (recommended for ~99% of cases). You generate an upload key locally; Google generates and holds an app signing key. Every AAB you upload is signed by your upload key, Play strips that, signs with the app key, and ships the result. If your upload key is compromised, you contact Google and rotate it; the app on users' devices keeps working because the app signing key never left Google.
  • Self-managed signing (legacy). You generate one key, sign everything yourself, never upload the key to Google. If you lose the key, you can't update the app — period. The new app would be a separate listing under a different package ID. This pattern exists for organizations with legal reasons to never let Google touch the signing key. It's not what you want.

Pick Play App Signing. The "upload key" you'll generate next is what your local builds sign with.

Step 3: Generate an upload key

3

One keystore file, kept somewhere safe forever

keytool -genkey -v \
  -keystore ~/keys/mybrand-upload.keystore \
  -keyalg RSA -keysize 2048 -validity 25000 \
  -alias mybrand-upload
# Enter a password. Save it in your password manager.
# Fill in the X.500 fields (name, organization, country).
# 25000 days = ~68 years. Yes, really. Keystores aren't supposed to expire.

Back this keystore up: cloud storage, encrypted USB, password manager attachment — anywhere it'll survive your laptop dying. Losing it means you can't push updates that bypass Google's escalation flow (which exists but is slow). Treat it like the deed to a property.

The keystore password and the key password (you'll be asked for both) can be the same; many people use the same for simplicity. Store both in your password manager.

Step 4: Build a signed AAB

4

AAB, not APK — Play Console rejects APKs for new apps

In app/build.gradle.kts (or app/build.gradle for Groovy DSL), add a release signing config:

android {
    signingConfigs {
        create("release") {
            storeFile = file(System.getenv("UPLOAD_KEYSTORE_PATH") ?: "$rootDir/keystore-not-set")
            storePassword = System.getenv("UPLOAD_KEYSTORE_PASSWORD")
            keyAlias = "mybrand-upload"
            keyPassword = System.getenv("UPLOAD_KEY_PASSWORD")
        }
    }
    buildTypes {
        release {
            signingConfig = signingConfigs.getByName("release")
            isMinifyEnabled = true
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
}

Build the bundle:

export UPLOAD_KEYSTORE_PATH=~/keys/mybrand-upload.keystore
export UPLOAD_KEYSTORE_PASSWORD='your-password'
export UPLOAD_KEY_PASSWORD='your-password'
./gradlew :app:bundleRelease

# Output:
# app/build/outputs/bundle/release/app-release.aab

That's the file you upload. Verify it's signed:

jarsigner -verify -verbose -certs app/build/outputs/bundle/release/app-release.aab
# Last line should say: "jar verified."
Never commit the keystore to git. Even a private repo is a future-leak risk. echo "*.keystore" >> .gitignore and load credentials from env vars or a secret manager. CI builds should pull the keystore from an encrypted secret (GitHub Actions encrypted secrets, AWS Secrets Manager, etc.), never the repo.

Step 5: Create the app in Play Console

5

The shell of the listing

Play Console → Create app. Fill in:

  • App name — what users see in the store. Max 30 chars. Can change later but the URL slug is set from it.
  • Default language — the locale your store listing's primary copy is in. You can add other languages later.
  • App or game — affects which category trees you can pick. Mostly cosmetic.
  • Free or paid — paid is one-time purchase or subscription. Free apps can still have in-app purchases. You cannot change free → paid later, only paid → free. Pick conservatively.

Submit. The app is now in Play Console as a draft. You can't publish anything yet; you need a signed AAB on a track and a bunch of metadata first.

Step 6: Fill out the required metadata (this is most of the work)

6

Six forms; none are optional

In Play Console, sidebar App content, work through each item. Submitting without filling these in is the #1 first-upload error.

  • Privacy policy. A URL to a publicly accessible privacy policy document. If your app collects any data, this is mandatory. If it collects no data, you still need a one-line policy stating that. Generators exist (app-privacy-policy-generator.firebaseapp.com); host the result somewhere durable.
  • App access. If parts of your app require a login, you must provide test credentials so reviewers can access them. "Username: [email protected], Password: ..." — Google reviewers actually use these.
  • Ads. Yes or no. If yes, additional ad-content rating questions follow.
  • Content rating. A questionnaire ("Does the app contain violence?", "References to gambling?") that generates an IARC rating. Takes 5–10 minutes. The rating affects which countries can see the app.
  • Target audience and content. Age bands, with extra rules if you target under-13. "Mixed audience" is the safe pick for most consumer apps.
  • Data safety. The heaviest form. Disclose every kind of data your app collects (location, contacts, photos, files, device IDs, etc.) and whether it's required, shared with third parties, encrypted in transit. The disclosures must match reality — Google does cross-check the app's runtime behavior against the form, and mismatches are a removal reason. Block out 20–40 minutes for this form on the first app.
  • Government apps / News apps / Health apps / etc. Conditional declarations if your app falls in a regulated category.

Step 7: Build the store listing

7

What users see when they tap your app

Sidebar Main store listing. Required assets:

  • App icon — 512×512 PNG, 32-bit, with alpha. The icon Google shows everywhere.
  • Feature graphic — 1024×500 JPG/PNG. The wide banner shown at the top of your listing.
  • Phone screenshots — at least 2, max 8. PNG or JPG, 16:9 or 9:16, between 320 and 3840 px on the shorter side. Take these from the AVD: adb exec-out screencap -p > screen.png.
  • Short description — 80 chars. Appears in search-result snippets.
  • Full description — 4000 chars. The actual product page copy.
  • Tablet screenshots — optional but recommended if you support tablets. Skipping these means tablet users see your phone screenshots in a less-flattering aspect ratio.

The descriptions are the part most worth iterating on — they're also editable post-launch, so good-enough at first is fine. Icon and feature graphic are harder to redo without re-uploading.

Step 8: Upload to the internal testing track

8

The fastest path to the app installed on a real device

Sidebar TestingInternal testingCreate new release:

  • App signing — Play Console offers Play App Signing on first upload. Accept it.
  • Upload AAB — drop in app-release.aab from Step 4. Upload takes 1–3 minutes.
  • Release name — auto-fills from the version code. Leave it.
  • Release notes — what changed. For the first release: "Initial release."

Save → Review release → Start rollout to internal testing. The release is processing within 5 minutes.

Add testers: Internal testingTesters tab → create an email list (paste up to 100 Gmail addresses, one per line). Save. Each tester gets a Play Store opt-in link they need to click before they can install the app.

Send the opt-in link to your testers. They click it, accept, then visit the app's Play Store page (or the direct internal-test link) and install. Within 5–10 minutes of release rollout, the app is installable on their device.

Step 9: Promote to closed → open → production

9

The progression that actually ships to the public

Once internal testing confirms the build works:

  • Closed testing — a private group, usually email-list-based or Google Group. Same upload flow; Promote release from internal → closed. Use this for early-access users, beta programs. If you're on a personal account, this is the 14-day requirement.
  • Open testing (optional) — anyone with the link can join. Lower commitment than production. Useful for "soft launch" without the Play Store search visibility.
  • Production — the public launch. Anyone in the supported countries can find and install your app. The first production release goes through full review (3–7 days); subsequent updates often clear in under 24 hours.

For the first push to production: ProductionCreate new releasePromote from closed testing. Add release notes. Submit. Wait. Email lands when status changes.

Common first-submit rejections. Google's reviewers reject for specific, fixable reasons — almost never vague ones:
  • Data safety mismatch — your form says you don't collect location, but the manifest declares ACCESS_FINE_LOCATION. Fix the form or remove the permission.
  • Target API level too low — Play requires apps target a recent Android API (currently API 34 / Android 14 for new apps). Bump targetSdkVersion and rebuild.
  • Missing privacy policy URL — the URL must resolve. A 404 is treated as missing.
  • "Login required but no test credentials" — fill in App Access with working test credentials.
  • Sensitive permissions without justification — for permissions like SMS, Call Log, or All Files Access, you must explain why the app needs them and use the official disclosure flows.

The deploy loop after the first release

Once the app is live and you have Play App Signing set up, updates are dramatically faster than the first time:

# Bump versionCode and versionName in app/build.gradle.kts
# Build a new signed AAB
./gradlew :app:bundleRelease

# Upload it via the Play Console UI, OR via the official gradle plugin:
# https://github.com/Triple-T/gradle-play-publisher
./gradlew publishReleaseBundle

The gradle-play-publisher plugin authenticates with a service-account JSON key (download from Play Console → Settings → Developer account → API access) and lets you push releases from CI. After the first manual upload, every subsequent release can be one CI step.

What's next