Skip to main content

Google Play

Uploading Android builds to Play: tracks, the first manual upload, the Play Console declarations, and CI with fastlane. Read it before your first Android release or when you set up Android CI.

How it works​

TrackReviewWho gets it
InternalNoneUp to 100 named testers, minutes after upload
ClosedYesTester lists or Google Groups
OpenYesAnyone who opts in
ProductionYesEveryone, optionally a percentage at first

How to build it​

The first upload is by hand​

Play refuses API uploads for an app until a person uploads the first AAB in Play Console. Do that once per app, then let CI take over. On an app that has never been published, CI must upload with release status draft; Play rejects completed releases on draft apps.

The CI service account​

  • A Google Cloud service account with the Release manager role on the app in Play Console.
  • Its JSON key is a CI secret. Never commit it.
  • If Play denies access to every track, fail the job. Otherwise the version-code lookup returns nothing and the build goes out as version code 1.

fastlane​

lane :internal do
upload_to_play_store(
package_name: ENV.fetch("PACKAGE_NAME"), # no fallback: an empty value must fail
track: "internal",
aab: "../build/app/outputs/bundle/prodRelease/app-prod-release.aab",
release_status: "completed",
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true,
)
end

Play Console declarations​

Every one of these is checked at review. Fill them before the first closed-track release, and update them before any build that changes what they describe.

DeclarationWhat to watch
Data safetyEvery data type the app and its SDKs collect, including device and advertising ids. Must match the privacy policy
Account deletionAn in-app path and a web URL where people can ask for deletion without the app
App accessA working demo account and steps. Missing it is a near-automatic rejection
Target audienceMatches the terms and the Apple age rating. Under 18 brings in the Families policy checks
Content rating (IARC questionnaire)Answer honestly; it is compared with what reviewers see
Child safety standardsSocial and community apps must publish their standards and offer in-app reporting
Advertising IDIf any SDK uses it, declare it, and keep the AD_ID permission. If not, remove the permission in the manifest
Store listingNo "#1", "best", rankings or claims in text or in screenshot images

Target SDK and libraries​

Google raises the required targetSdk and Billing Library version about once a year. A build below them cannot be uploaded at all. Put the deadline in the team calendar.

Rules​

Rule

Update the Data safety form before you upload a build that collects something new. A build that collects data its declaration denies is a policy violation from the moment it is live.

Rule

Test release builds by installing them from a Play track. Sideloaded release builds fail Play Integrity and in-app purchases.

Rule

CI build scripts never fall back to a default package name. A fallback to an old or wrong package uploads to the wrong app, or fails in a confusing way.

Mistakes we made​

  • A listing was rejected for screenshot text. Two images said things like "the #1 app in the world". Claims in images count as listing text.
  • A build shipped with the advertising-id permission restored while Data safety still said "no advertising id". The permission came back for an attribution SDK. Update the declaration first, upload second.
  • CI ran out of memory. An 8 GB Gradle heap plus the Kotlin daemon was more than the runner had. Size the heap to the runner.
  • CI decoded secrets that no longer existed after a keystore rename, and later pinned a framework version older than the project's.
  • A Gemfile.lock made with the laptop's system Ruby crashed on CI. Use the same Ruby version locally and in CI.
  • Version codes 1 and 2 were already used by manual uploads, so CI's first codes collided. CI now adds an offset.
  • The production upload is still manual from a laptop. It works, but it depends on one person's machine and keys. Move it to CI with a manual approval step.

Checklist​

  • First AAB uploaded by hand; CI uses draft until the app is published.
  • CI service account has Release manager; job fails if Play denies access.
  • Data safety, deletion URL, app access, target audience, content rating done.
  • Advertising-id permission matches the declaration.
  • Listing text and screenshots have no ranking claims.
  • targetSdk and Billing Library meet this year's deadline.
  • Release builds tested from a Play track.