Submitting to Google Play
Shipping Android: the Play Console record, testing tracks, the data safety form, and a staged rollout you can halt.
eas submit --platform android --profile productionAndroid releases go through the Play Console. Create the app there, then upload an .aab. Play expects the first upload of a brand new app to be done by hand in the Console, because that is where you create the initial release; automated submission works from then on.
Automated submission
eas submit --platform android needs a Google service account key, uploaded once with eas credentials --platform android or referenced as serviceAccountKeyPath in the submit profile. The profile's track is one of internal, alpha, beta or production.
Tracks
Internal testing reaches a listed set of testers within minutes and is where you should live day to day. Closed and open testing are review-gated and slower. Production is reviewed and can take days.
Data safety
Play requires a declaration of what the app collects, what it shares, and whether data is encrypted in transit. It is checked against the app's behaviour, and a library you added counts as your collection.
Staged rollout
Set releaseStatus: "inProgress" with rollout as a fraction, for example 0.1, so a tenth of devices get the release. If crash reports rise you halt it in the Console. Play also enforces a minimum target API level each year; the value Expo SDK 57 ships meets the current one, so do not lower it.
Example
// app.config.ts - the Android fields Play checks
import type { ConfigContext, ExpoConfig } from "expo/config";
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: "Trailhead",
slug: "trailhead",
version: "1.2.0", // becomes versionName; the listing shows this
android: {
// The package name is permanent once a listing exists.
package: "com.example.trailhead",
// No versionCode here: appVersionSource is "remote", so EAS owns it.
adaptiveIcon: {
foregroundImage: "./assets/adaptive-icon.png",
backgroundColor: "#0B3D2E",
},
permissions: ["android.permission.CAMERA"],
// A dependency can merge in a permission you never asked for, and then you
// have to declare it on the data safety form. Block what you do not use.
blockedPermissions: [
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.RECORD_AUDIO",
],
},
});When to use it
- Get a build to internal testers in minutes rather than waiting on review.
- Roll a release out to ten percent of devices and halt it if crash-free sessions drop.
- Answer the data safety form consistently with what the app sends.
- Stop a dependency from adding a permission that would widen your privacy declaration.
More examples
Submit profiles for a test track and a staged production release
The preview profile pushes straight to internal testing and marks it live, because internal testers are not worth a manual step. The production profile starts at ten percent and stays inProgress until you raise it in the Console, which is the cheapest insurance against a crash that only happens on real devices.
{
"submit": {
"preview": {
"android": {
"serviceAccountKeyPath": "./credentials/play-service-account.json",
"track": "internal",
"releaseStatus": "completed"
}
},
"production": {
"android": {
"serviceAccountKeyPath": "./credentials/play-service-account.json",
"track": "production",
"releaseStatus": "inProgress",
"rollout": 0.1,
"changesNotSentForReview": false
}
}
}
}First release, then automated ones
Teams get stuck here more often than anywhere else in the release path: eas submit cannot create the first release of a listing. Do that one upload manually, confirm the app shows in internal testing, and every release afterwards is the single submit command.
# Build the bundle Play accepts (app-bundle is the default)
eas build --platform android --profile production
# First time only: download the .aab and create the release by hand in the
# Play Console, so the listing exists
eas build:list --platform android --limit 1
# After that, submission is one command
eas submit --platform android --profile production --latest
# Upload the service account key once; it is then stored with your credentials
eas credentials --platform android
Discussion