React Native

How to Publish a React Native or Expo App on Google Play

Publish your React Native or Expo app on Google Play in 2026: target API 36, set up the upload key, build the .aab with EAS, and pass the 12-tester closed test.

Updated · 8 steps · 14 pictures · ~15 min read

Expo and React Native build your app. Getting it onto Google Play is up to you: you build a signed Android App Bundle, then publish it through Play Console. This guide covers both routes, Expo with EAS and the plain React Native CLI, in 8 steps, updated for Google Play's 2026 rules: target API 36, 16 KB page sizes and the 12-tester closed test.

SDK 54+ Expo, or React Native 0.81+, targets API 36
$25 Google Play fee, paid once
14 days Closed test, new personal accounts
About 25 days From bundle to live app

Shortcut Rather not read it all? Copy our AI prompt and your AI assistant walks you through every step.

Eight steps in two groups. In your project: get the project ready (package name, target API 36), set up your upload key (EAS makes it, or keytool), and build the app bundle with eas build. On Expo, EAS handles the upload key (you keep a backup), the version code on production builds, and the cloud build. In Google Play Console: create a developer account for US$25, create the app with its store listing and App content, upload your first build to closed testing rather than internal testing, run a closed test with 12 testers for 14 days in a row, then apply for production and release.
Figure 1. The whole route. Steps 1 to 3 happen in your project, steps 4 to 8 in Play Console.

Get ready

Before you start

Expo or React Native CLI?

If your project has app.json with an expo section, you are on Expo, and EAS (Expo Application Services) can build and sign the app for you. If it has an android folder you edit by hand and no Expo, you are on the React Native CLI. Steps 1 to 3 differ; steps 4 to 8 in Play Console are the same.

A comparison of the two routes. Package name: android.package in app.json on Expo, applicationId in android/app/build.gradle on React Native CLI. API 36: Expo SDK 54 or newer, or React Native 0.81 or newer. Version code: EAS raises it on every production build; on the CLI you raise versionCode yourself. Upload key: EAS creates and stores it and you download a backup; on the CLI you create it with keytool. Signing: nothing to do on EAS; on the CLI you add a release signing block. Build: eas build -p android in the cloud, or npx react-native build-android --mode=release on your computer.
Figure 2. Find your column, then follow the matching half of steps 1 to 3.

Check your version

Since 31 August 2026, new apps and updates must target Android 16 (API level 36). Expo SDK 54 and React Native 0.81 are the first versions that do this by default.

VersionWhat it gives you
React Native 0.77, or Expo SDK 53 (expo 53.0.14 or newer)Supports 16 KB page sizes.
React Native 0.81, or Expo SDK 54Targets API 36 by default, as Google Play requires.
Expo SDK 57The current Expo version, released 30 June 2026, on React Native 0.86.
React Native 0.87.1The current React Native version, released 26 August 2026.

Upgrading an Expo app (more than one SDK behind? Go one SDK at a time: expo@^55.0.0, then ^56, and so on):

npm install expo@^57.0.0
npx expo install --fix
npx expo-doctor

Have these ready

  • Expo SDK 54+ or React Native 0.81+Older projects must upgrade before Google Play accepts them.
  • An Expo account, for EASThe free plan includes 15 Android builds a month. React Native CLI apps build on your computer instead.
  • A Google Play developer accountUS$25, paid once. Step 4 covers it.
  • A privacy policy pageAt a public web address that opens without signing in.
  • Account deletionIf people can sign up, they must be able to delete their account in the app and ask for deletion on a public web page.
  • 12 or more testersNew personal Play accounts only. Step 7 explains why.

Built with an AI app builder?

Many AI app builders export an Expo project. If yours does, this guide is your route: open the project, then start at step 1.

01 In your projectYour time: 30 minutes

1. Get your project ready

A few settings decide how your app appears on Google Play. The package name can never change after your first upload, so set it now.

Where app.json on Expo, android/app/build.gradle on the CLI

  1. Target API 36. Use Expo SDK 54 or newer, or React Native 0.81 or newer. On an older CLI project you can set targetSdkVersion to 36 and compileSdkVersion to 36 or higher in android/build.gradle, but Android 16 then draws every screen edge to edge, so test them all.
  2. Package name. On Expo, set android.package in app.json before your first build. If you skip it, npx expo prebuild quietly picks one for you, such as com.anonymous.yourapp, and you are stuck with it once it is on Google Play. On the CLI, set applicationId in android/app/build.gradle.
  3. An old android folder? If your Expo project has an android folder from npx expo prebuild, EAS builds from that folder and ignores the Android settings in app.json, package name included. With no custom native code, delete the folder after you change app.json, or run git rm -r --cached android and add /android to .gitignore.
  4. Name, icon and version. On Expo these live in app.json: name, icon and version (the version people see). EAS numbers each build for you. On the CLI, set versionCode and versionName in android/app/build.gradle.
  5. Permissions. Keep only the ones your app needs. expo-media-library asks for photo, video and audio access by default, and Google Play allows broad photo access only for apps built around it. If your app only saves pictures, ask for write-only access and list READ_MEDIA_IMAGES, READ_MEDIA_VIDEO and READ_MEDIA_AUDIO under android.blockedPermissions in app.json. To let people pick a photo, use expo-image-picker, which uses Android's photo picker.
  6. Environment variables. If your .env file is in .gitignore, as it should be, EAS cloud builds never see it. Add each value with eas env:set, or the app can open to a blank screen from Google Play.

app.json on Expo:

{
  "expo": {
    "name": "Habit Tracker",
    "version": "1.0.0",
    "android": {
      "package": "com.yourname.habittracker"
    }
  }
}

An environment variable for EAS builds:

eas env:set --name EXPO_PUBLIC_API_URL --value https://api.example.com --environment production --visibility plaintext

You should see Your own package name in app.json or build.gradle, and the app working in a release build on your phone. On Expo, install a preview build from eas build -p android --profile preview (or run npx expo run:android --variant release if you have the Android SDK). On the CLI, run npm run android -- --mode="release" once step 2 is done.

02 In your projectYour time: 10 minutes

2. Set up your upload key

Every bundle you upload must be signed with the same key, called your upload key. On Expo, EAS makes and keeps it. On the CLI, you make it yourself.

Where Terminal, and expo.dev on Expo

On Expo with EAS

  1. Install the EAS command line tool, log in, and set up the project. This writes eas.json.
  2. On your first production build (step 3), choose Generate new keystore. EAS stores it on its servers.
  3. Back it up: run eas credentials, choose Android and production, then credentials.json and Download credentials from EAS to credentials.json. This saves credentials.json and credentials/android/keystore.jks. Keep both out of Git and store a copy somewhere safe.
npm install --global eas-cli
eas login
eas build:configure
The Credentials page of an Expo project on expo.dev. Two highlighted boxes: Android upload keystore, with the key alias and its MD5, SHA-1 and SHA-256 fingerprints, and Google service account key for EAS Submit, with the project ID, private key ID and client blurred.
Figure 3. Your project's Credentials page on expo.dev: the upload key EAS keeps for you, and the service account key that eas submit uses (step 6). Based on an Expo docs screenshot.

On the React Native CLI

  1. In the android/app folder, run the keytool command below. It comes with the JDK you use for Android, and Android Studio includes one. Choose a password and answer the questions.
  2. Add the four MYAPP_UPLOAD_* lines to ~/.gradle/gradle.properties, which keeps the passwords out of your project and out of Git.
  3. In android/app/build.gradle, add the release block inside the existing signingConfigs, and change the release build type from signingConfigs.debug to signingConfigs.release.
  4. Back up the keystore file and its passwords somewhere safe.
keytool -genkeypair -v -storetype PKCS12 -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

If keytool is not found, use the one in Android Studio's jbr/bin folder.

~/.gradle/gradle.properties:

MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore
MYAPP_UPLOAD_KEY_ALIAS=my-key-alias
MYAPP_UPLOAD_STORE_PASSWORD=<your keystore password>
MYAPP_UPLOAD_KEY_PASSWORD=<your key password>

Replace each <...>, including the angle brackets.

android/app/build.gradle. Add the new lines to your file; do not paste this over it. The ... parts stand for what is already there.

android {
    ...
    signingConfigs {
        debug { ... }
        release {
            if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
                storeFile file(MYAPP_UPLOAD_STORE_FILE)
                storePassword MYAPP_UPLOAD_STORE_PASSWORD
                keyAlias MYAPP_UPLOAD_KEY_ALIAS
                keyPassword MYAPP_UPLOAD_KEY_PASSWORD
            }
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}

Building Expo apps on your own computer?

After npx expo prebuild, the android folder signs release builds with the debug key, just like a new CLI project. Add the same signing setup, and know that npx expo prebuild --clean rebuilds that folder and removes your changes. If EAS already made your key, download it with eas credentials and use that keystore instead of making a new one with keytool, because Google Play only accepts builds signed with the same key. EAS cloud builds need none of this.

What if you lose the key later?

You are not locked out. Google Play keeps its own signing key and can reset your upload key: make a new key, export its certificate with the command below, then use Protected with Play › Play Store protection › Manage Play app signing › Request upload key reset and upload the .pem file. You need admin permission on the account. On Expo, the key stays on EAS unless you delete it.

keytool -export -rfc -keystore my-upload-key.keystore -alias my-key-alias -file upload_certificate.pem

You should see On Expo, an eas.json file. On the CLI, my-upload-key.keystore in android/app and a release signing block in build.gradle.

03 In your projectYour time: 5 minutes

3. Build the app bundle

Google Play needs an Android App Bundle, an .aab file. One command builds it on either route.

Where Terminal, in your project folder

  1. Expo: run eas build --platform android --profile production. The production profile builds an .aab and raises the version code. On the free plan the build can wait in a queue at busy hours. When it finishes, download the file from the build page on expo.dev or from the link in your terminal.
  2. React Native CLI: run npx react-native build-android --mode=release. Your file is at android/app/build/outputs/bundle/release/app-release.aab.
  3. On the CLI, check that android/gradle.properties does not contain org.gradle.configureondemand=true. It makes release builds skip your JavaScript.

Expo with EAS:

eas build --platform android --profile production

React Native CLI:

npx react-native build-android --mode=release

Coming in February 2027: code shrinking

From February 2027, apps with more than 10 MB of DEX code need at least 25% optimization, obfuscation and shrinking. React Native and Expo up to SDK 57 ship with R8 shrinking off. To turn it on, set android.enableMinifyInReleaseBuilds to true in expo-build-properties, or enableProguardInReleaseBuilds = true in android/app/build.gradle, then test a release build, because some libraries need keep rules.

You should see An .aab file on your computer.

04 In Play ConsoleYour time: 25 minutesWait: 1 to 2 days

4. Create your developer account

Skip this step if you already have a Google Play developer account.

Where play.google.com/console/signup

  1. Sign in with the Google account that should own your apps, and choose Yourself or An organization.
  2. Pay the US$25 fee with a credit or debit card.
  3. Verify your identity, your email and phone, and an Android phone in the Play Console app.
The Play Console sign-up screen titled To get started, choose an account type, with the options An organization and Yourself.
Figure 4. Pick Yourself or An organization. Finance, health, VPN and government apps need an organization account.

Important

Apps for financial services, health, VPN or government must be published from an organization account. Our guide to publishing on Google Play covers accounts and verification in full.

05 In Play ConsoleYour time: 1 to 2 hours

5. Create the app in Play Console

Create the app with your exact package name, then fill in the store listing and the App content questions.

Where Play Console › Home › Create app

  1. Click Create app. Enter the app name and your package name, then click Check availability.
  2. Choose the language, App or Game, and Free or Paid. A free app can never become paid later.
  3. Go to Grow users › Store presence › Store listings: an app name of up to 30 characters, a short description of up to 80, a full description of up to 4,000, a 512 by 512 icon, a 1024 by 500 feature graphic and 2 to 8 phone screenshots.
  4. Go to Policy and programs › App content and answer every item. Data safety must cover every library that collects data, such as Firebase, analytics, ads and crash reporting.
The Create app page in Play Console with fields for App name, Package name with a Check availability link, Default language, and App or game.
Figure 5. In Package name, type the same package name as in app.json or build.gradle.
The Default store listing page in Play Console with the app name, short description and full description fields.
Figure 6. Your store listing: Grow users › Store presence › Store listings.
The App content page in Play Console listing the declarations to complete, such as privacy policy, ads, app access, content rating, target audience and Data safety.
Figure 7. Answer every item under Policy and programs › App content.

Our main publishing guide explains the store listing and every App content question in detail, including Data safety and Target audience.

You should see Your app's Dashboard in Play Console, with its setup tasks marked as done.

06 In Play ConsoleYour time: 15 minutes

6. Upload your first build

New personal accounts upload the first build to closed testing. Doing it by hand is the surest route. eas submit can do it too on Expo, but it sends builds to internal testing unless you set the track in eas.json.

Where Test and release › Testing › Closed testing

  1. Open Closed testing and click Manage track on the track that is already there (extra closed tracks you create cannot target countries). Add all countries, or at least every country your testers live in.
  2. Click Create new release, upload your .aab, add release notes and save.
  3. Organization accounts and personal accounts created before 13 November 2023 can skip the closed test and create a production release instead.

With eas submit (Expo only)

React Native CLI apps upload by hand and need no service account.

  1. Create a Google service account key. You no longer need to link a Google Cloud project in Play Console. In Google Cloud, create a project, then IAM & Admin › Service Accounts › Create service account. On the new account, choose Manage keys › Create new key › JSON, and enable the Google Play Android Developer API.
  2. In Play Console, open Users and permissions › Invite new users, paste the service account's email, and on App permissions choose your app with these permissions: View app information (read-only); Edit and delete draft apps; Release to production, exclude devices, and use Play App Signing; Release apps to testing tracks; Manage testing tracks and edit tester lists; Manage store presence.
  3. Upload the JSON key to your project's Credentials page on expo.dev, under Google service account key for EAS Submit (Figure 3), or with eas credentials. Never paste it into a chat or commit it.
  4. Add the track and release status below to eas.json, then run eas submit --platform android. Finish the draft release in Play Console.

In eas.json, replace the empty "submit" section that eas build:configure created with:

"submit": {
  "production": {
    "android": {
      "track": "alpha",
      "releaseStatus": "draft"
    }
  }
}
Three Google Play tracks. Internal testing, track internal, is eas submit's default: up to 100 testers, and it does not count toward the 12 testers. Closed testing - Alpha, track alpha, is the closed track Play Console already has, and it counts: 12 testers, 14 days in a row. Production, track production, reaches everyone and only after Google grants production access.
Figure 8. eas submit picks the track from eas.json. Without it, your build goes to internal testing.
The Latest releases table in Play Console with two rows: release 1.0.0 on Internal testing, available to internal testers, and release 1 (1.0.0) on the highlighted track Closed testing - Alpha, in review.
Figure 9. Play Console calls its closed track Closed testing - Alpha. That is the track "alpha" reaches. Based on an Expo docs screenshot.

Important: internal testing does not count

Without a track in eas.json, eas submit uploads to internal testing, which never counts toward the 12 testers and 14 days. On a brand-new app, Google can also refuse a finished release with "Only releases with status draft may be created on draft app", which is why the example uses "draft".

Using Google sign-in or Firebase?

Sign-in that works in development can fail in the version from Google Play, because Google signs that version with its own key. After your first upload, open Protected with Play › Play Store distribution › Go to Play app signing, copy every SHA-1 and SHA-256 fingerprint in the App signing key section (new apps can list three keys) and add them all in Firebase or Google Cloud. Expo's docs still show an older menu path.

You should see A release on the Closed testing - Alpha track with your bundle in it.

07 New personal accountsYour time: 30 minutesWait: 14 days

7. Run your closed test

Personal accounts created after 13 November 2023 need at least 12 testers who stay opted in for 14 days in a row before the app can go public.

Where Test and release › Testing › Closed testing

  1. Add your testers on the Testers tab, with an email list or a Google Group.
  2. Send the release for review from Publishing overview. This usually takes a day or two.
  3. Copy the opt-in link from the Testers tab and send it to every tester. Google does not invite them for you.
  4. Keep at least 12 of them opted in and using the app for 14 days in a row.

Short of testers? Our guide to getting 12 testers for Google Play covers every way to find them.

An example closed test with 15 testers over two weeks. Testers 1 to 13 stay opted in all 14 days. Tester 14 leaves on day 6 and tester 15 joins on day 7 as a replacement, so 12 or more testers are opted in every day and the developer can apply after day 14.
Figure 10. Keep 12 or more testers opted in for 14 days in a row. If someone leaves, a replacement keeps the count up; the clock does not restart.
The Testers tab of a closed test in Play Console. It shows an email list with 15 testers, a feedback email address, and a section called How testers join your test with two highlighted Copy link buttons: Join on Android and Join on the web.
Figure 11. Copy the opt-in link from the Testers tab and send it to your testers.
The Apply for access to production card on the Play Console Dashboard, with three items: publish a closed testing release, have at least 12 testers opted in, and run the closed test with at least 12 testers for at least 14 days.
Figure 12. Your Dashboard tracks the test. Apply for production stays grey until all three lines are ticked.

Fixing bugs during the test

You can upload a fixed build to the same closed track during the test. Testers stay opted in, so their 14 days keep counting. With eas submit and "track": "alpha", each new build lands on that same track as a draft that you finish in Play Console, or remove "releaseStatus": "draft" once your first release is out.

No 12 testers? We run this step for you.

Starter $15

Testing starts within 6 hours: 15 verified testers join your closed test and stay for the full 14 days. Anyone inactive is replaced. Comes with our production access guarantee, or a full refund.

Opt for Starter

Community app Free

Join a Pack of 16 developers who test each other's apps for 16 days. Inactive members are replaced.

Get the free app
08 Your time: 30 minutesWait: usually 4 to 6 days

8. Apply for production and release

After 14 days, ask Google to let your app go public. Then release it.

Where Dashboard › Apply for production, then Test and release › Production

  1. On the Dashboard, click Apply for production and answer the form's 10 questions (2 are multiple choice) about your test and your app. Be specific about what testers told you and what you changed.
  2. Google usually replies by email within 2 to 3 days.
  3. Once approved, open Production and click Create new release.
  4. Click Add from library to reuse your tested bundle, or upload a newer one, then write release notes and choose countries.
  5. Send the release for review from Publishing overview. The review usually takes 2 to 3 days, and can take up to 7.
The Create production release page in Play Console with the App bundles box, an Upload link and an Add from library link.
Figure 13. Use Add from library to reuse the bundle from your closed test.

Tip

Our production access form guide has a sample answer for every question Google asks.

You should see The release In review, then your app live on Google Play.

Your React Native app is on Google Play

Its public link is play.google.com/store/apps/details?id= followed by your package name.

Next

Updating your app after launch

Every update is a new bundle with a higher version code. On Expo, raise version in app.json for a new release, run eas build, then upload it. EAS raises the version code for you. Once your app is live, you can set "track": "production", remove "releaseStatus": "draft" in eas.json and send updates with eas submit. On the CLI, raise versionCode and versionName in android/app/build.gradle, build again and upload the new bundle.

eas build --platform android --profile production --auto-submit

EAS Update can change JavaScript, styles and images without a store update. Native code, new native libraries, permissions and SDK upgrades still need a new build, and every update must follow Google Play's policies.

If it goes wrong

Common React Native errors on Google Play

These are the problems React Native and Expo developers run into most often, with the fix for each:

What you seeHow to fix it
"You uploaded an APK or Android App Bundle that was signed in debug mode"Release builds still use the debug key. Add the release signing from step 2 (CLI or local Expo builds) and build again. EAS cloud builds are signed for you.
"Version code 1 has already been used"On Expo, run eas build:version:set, enter the highest version code already on Google Play, and build again. On the CLI, raise versionCode.
"APKs are not allowed for this application"You uploaded an APK from a preview profile. Build with --profile production to get an .aab.
"Only releases with status draft may be created on draft app"Add "releaseStatus": "draft" to eas.json (step 6), or upload the first build by hand.
"App must target Android 16 (API level 36) or higher"Upgrade to Expo SDK 54 or newer, or React Native 0.81 or newer. An existing app could ask for an extension to 1 November 2026 from the Policy status page; a new app must target 36.
"App must support 16 KB memory page sizes"Upgrade to Expo SDK 54 or newer, or React Native 0.81 or newer (you need these for API 36 anyway), then update native libraries. On Expo, run npx expo install --fix.
The Play build opens to a blank screen or crashes at onceUsually missing environment variables on EAS (step 1). Also check R8 keep rules if you turned shrinking on, and configureondemand on the CLI. Test a release build first.
Google sign-in fails only from Google Play (DEVELOPER_ERROR)Add the Play app signing fingerprints to Firebase or Google Cloud (step 6).
Play Console says the app must use Billing Library 8 or laterUpdate to react-native-iap 14, expo-iap 2.9 or react-native-purchases 9, or newer, then build and upload again.
"There is no deobfuscation file associated with this App Bundle"A warning only. You can carry on.
A Play Console issue reading App must support 16 KB memory page sizes. A highlighted box says Action by Feb 1, 2027, You won't be able to release app updates, Extension granted.
Figure 14. The 16 KB warning in Play Console. A new app must support 16 KB pages now; 1 February 2027 is the extended deadline for updates to existing apps. Image: Android Developers.

If Google rejects the app itself, the email and the Policy status page give the reason. The usual causes are a missing privacy policy, no way to delete an account, Data safety answers that leave out a library, photo and video permissions the app does not need, and a request for more testing. See every Google Play rejection reason and the fix.

How we help

Where Testers Community fits

Steps 1 to 6 take a few hours of your own time. Step 7 is the one that takes other people: 12 testers who install your app, accept the invitation and keep using it for 14 days.

Add our Google Group to your closed test and send us your opt-in link. Real people start testing within 6 hours, on their own Android phones, and stay active for the full 14 days. Anyone who goes quiet is replaced. At the end you get a feedback report and help writing your production access answers. Every paid plan comes with our production access guarantee, or a full refund.

Quick answers

Frequently asked questions

How do I publish an Expo app on Google Play?

Set android.package in app.json, run eas build --platform android --profile production to get a signed .aab, and create the app in Play Console. Upload the bundle to closed testing, run the closed test if your account needs it, then apply for production and release.

Does eas submit upload my first build to Google Play?

It can, once the app exists in Play Console and EAS has a Google service account key. By default it sends the build to internal testing, which does not count toward the 12 testers, so set "track": "alpha" and "releaseStatus": "draft" in eas.json, or upload the first build by hand.

How do I send an Expo build to closed testing?

Set "track": "alpha" under submit, production, android in eas.json, then run eas submit --platform android. For the first upload, also set "releaseStatus": "draft" and finish the release in Play Console. Play Console calls that track Closed testing - Alpha.

Which Expo SDK or React Native version do I need for Google Play in 2026?

Expo SDK 54 or newer, or React Native 0.81 or newer, which target API level 36 by default as Google Play has required since 31 August 2026. The current versions are Expo SDK 57 and React Native 0.87.1.

Where is my Expo keystore?

On EAS's servers, if you let EAS generate it. Run eas credentials, choose Android, then download credentials from EAS to credentials.json to keep a backup. Its fingerprints are on your project's Credentials page on expo.dev.

Why is my app's package name com.anonymous?

Because app.json had no android.package when you ran npx expo prebuild or npx expo run:android while logged out, so Expo picked com.anonymous plus your app's slug. Change it before your first upload, because the package name can never change once the app is on Google Play.

How do I build an AAB file in React Native?

Run npx react-native build-android --mode=release after setting up your upload key and release signing. The file is at android/app/build/outputs/bundle/release/app-release.aab. On Expo, eas build --platform android --profile production builds an .aab by default.

Do I need 12 testers to publish a React Native app?

Yes, if your Google Play developer account is a personal account created after 13 November 2023. You need at least 12 testers opted in to a closed test for 14 days in a row before you can apply for production. Internal testing does not count, and organization accounts are exempt.

How long does it take to publish a React Native app on Google Play?

About 25 days on a new personal account. Building the bundle takes under an hour. Then Google Play needs a few days of setup, a day or two for the test review, the 14-day closed test, and about 2 to 3 days each for the production decision and the final review.

Shortcut

Let your AI walk you through it

Rather not read all eight steps? Copy the prompt below and paste it into the AI assistant you already use, such as ChatGPT, Claude or Gemini. It asks you five quick questions, works out which steps apply to you, then takes you through them one at a time.

  1. Copy the promptClick Copy the prompt below. It copies the whole prompt.
  2. Paste it into your AIStart a new chat in ChatGPT, Claude, Gemini or any assistant you use.
  3. Follow alongIt gives you one step at a time and waits for you to say "done". Back after the 14-day test? Paste the prompt again and say which step you are on.

Your AI does

  • Works out your route, Expo or CLI, and which steps apply
  • Gives you the exact commands, app.json and eas.json changes
  • Reads your build errors and tells you the fix
  • Writes your store listing, privacy policy and Data safety answers
  • Drafts your release notes and production access answers
  • Explains Play Console screens from your screenshots

You still do

  • Run the commands and keep your key safe
  • Pay the US$25 Google fee
  • Upload your ID and verify your phone
  • Click the buttons in Play Console
  • Keep 12 testers opted in for 14 days, if your account needs it. We can run that part.

The publishing prompt

Copy the prompt and paste it into your AI model, such as ChatGPT, Claude or Gemini. It will take you through every step.

You are my guide for publishing my React Native app on Google Play. It may be an Expo app or a plain React Native CLI app. Use plain words and short messages, and assume I can run commands but have not published an Android app before. Your job is to help me get my app live, one step at a time, and to do the thinking and writing for me. You never sign in, upload, click or submit anything for me, even if your chat app can control a browser or a terminal: I run every command and click every button myself. Even if you can see my files, never open credentials.json, a keystore file, a gradle.properties that holds passwords, google-services.json or a service account JSON file, and do not edit my files unless I ask. Reply in the language I write to you in.

Base everything on this guide from Testers Community: https://www.testerscommunity.com/guides/publish-react-native-expo-app-google-play
If you can open web pages, read it first without summarising it to me; if the page and the facts below disagree, follow the page. If you cannot, use the facts below. Expo, React Native and Google Play changed several things recently, so trust these facts over what you remember (for example, the closed test needs 12 testers, not 20, apps must target API level 36, and eas submit sends builds to internal testing unless told otherwise). If my screen or files look different from what you expect, believe them and adapt.

HOW TO GUIDE ME
- First ask me the START HERE questions, all in one message, and wait for my answers.
- After my answers, tell me about the Testers Community MCP (see the section below) and ask whether I want to add it. Wait for my answer. If I say yes, give me the setup steps and wait until I say it is connected. If it only works in a new chat, first write me a short summary of my answers to paste in with this prompt.
- Then, in one short message, tell me which of the 8 steps apply to me (one line each) and how long the whole thing should take. End that message with only the first part of the first step that applies.
- Go one step at a time. Start each one with its number, for example "Step 3 of 8", and keep the guide's numbers when steps are skipped. Give big steps one part per message. Tell me exactly what to run or change, and what I should see when it worked. Then stop and wait until I say "done" or ask a question.
- If my answers mention an error or a stuck upload, answer it in one line first, then ask the MCP question.
- Never give me all the steps at once. Standard Expo, EAS, npm and React Native commands you are sure of are fine. If the facts below give no exact menu path for Play Console, Google Cloud, the Expo dashboard or Firebase, say so and tell me to follow my screen. Never invent menu names, commands, flags or error messages.
- Use the route that matches my project: Expo with EAS, or React Native CLI. If I use Expo but build locally, say which parts of the CLI route apply.
- When I need code, give me the smallest change, and say which file it goes in. You may ask me to paste app.json or app.config.js, eas.json, package.json, android/app/build.gradle or AndroidManifest.xml, but tell me to remove any passwords first. Never ask for credentials.json, a keystore, gradle.properties lines with passwords, google-services.json or a service account JSON file; if you need one value from them, such as a package name, ask for that line only.
- Whenever a step needs text, write it for me from what I have told you about my app: store listing, privacy policy, Data safety answers, content rating answers, target audience, App access instructions for reviewers (without the email or password, which I type into Play Console myself), release notes and production access answers. Stay within Google's limits. Never describe a feature my app does not have. If you need details you do not have, such as which libraries collect data, ask me instead of guessing.
- If I send an error or a screenshot, tell me what it means and how to fix it. If these facts do not cover it, say so, ask for the full text and the command or screen it came from, and do not guess.
- Never say that you or Testers Community submits the app, and never promise approval or dates. Google decides.
- Never ask me to paste passwords, card numbers, ID document details, my keystore file, credentials.json, any keystore or key password, API keys, Expo access tokens, or service account files into this chat. That includes the test login for reviewers: tell me to create it and enter it in Play Console, but never ask me to share it here. If I paste any of these anyway, do not check, quote or use it, and if I ask whether it is right, do not say; show me the format with placeholders instead. Tell me to delete or edit the message if the chat app allows it (or delete the chat). Do not review any other part of that message either; ask me to send it again without those lines. If no build signed with that key has been uploaded yet, I make a new key. If one has, I request an upload key reset (see Play App Signing below). A pasted service account key, API key or token gets deleted and replaced.
- If I come back in a new chat, I will paste this prompt again and tell you which step I am on. Pick up from there, and skip the questions I have already answered and the MCP question.

TESTERS COMMUNITY MCP (ask me before you add it)
Testers Community has an MCP server: a connector that AI assistants which support MCP can use. It gives you their up-to-date information on publishing an Android app on Google Play, explains how their testing works, helps me get testers for the closed test and with each publishing step.
- Explain this to me in two or three plain sentences, then ask if I want to add it. If you know you cannot use MCP connectors in this chat app, say so in one sentence instead of asking. Do not give me the setup steps until I say yes.
- If I say yes, I add it myself. Give me only these setup steps: open https://www.testerscommunity.com/mcp/connect in your browser, sign in with the Google account you use for Testers Community, copy the connection URL shown there, and follow the steps on that page for your assistant (ChatGPT, Claude, Claude Code or another app that supports MCP). If my screen looks different, tell me to follow my screen. Once it is connected, use it for the latest facts and, only if my account needs the closed test, for getting testers. If it disagrees with the facts below, follow the MCP, because it is newer. Never use it to sign me up, order or pay for anything without my yes in this chat.
- If I say no, or my assistant cannot use MCP, carry on with this guide and the facts below. I can do every step without it.
- It does not replace my part: I still pay the fee, verify my identity, run the commands, click the buttons in Play Console and submit the app, and Google makes the decision.

START HERE (ask me these)
1. Is it an Expo app or a plain React Native CLI app? Which Expo SDK or React Native version (package.json)? Do you build with EAS in the cloud, or on your computer? On Expo: is there an android folder in the project?
2. Have you uploaded this app to Google Play before (any track)? What package name does it use (android.package in app.json, or applicationId)? Do you already have an upload key? (Just yes or no: never paste the file or its passwords here.)
3. Do you already have a Google Play developer account? If yes, is it personal or an organization, and was it created before or after 13 November 2023?
4. What does your app do? Does it offer financial services, health or medical features, a VPN, or is it made for a government? Does it sell anything, and is that physical or digital?
5. Does it use Google sign-in or Firebase, ads, in-app purchases, photo library access or push notifications? Do people create accounts?

FACTS TO USE (checked against Expo's, React Native's, Android's and Google's pages, 10 October 2026)
- Versions: current stable React Native 0.87.1 (26 August 2026) and Expo SDK 57 (30 June 2026, on React Native 0.86). React Native 0.81 or newer and Expo SDK 54 or newer target API level 36 by default. 16 KB page sizes: React Native 0.77 or newer, Expo SDK 53 with expo 53.0.14 or newer, or SDK 54+; a new app must support 16 KB now. minSdk is 24 (Android 7).
- Target API: since 31 August 2026, new apps and app updates must target Android 16 (API level 36). Only existing apps could request an extension to 1 November 2026; a new app must target 36 now. Expo upgrade: npm install expo@^57.0.0, then npx expo install --fix, then npx expo-doctor. From SDK 52 or older, go one SDK at a time, running npx expo install --fix and npx expo-doctor each time; SDK 55 and newer support only the New Architecture. React Native CLI: upgrade to 0.81 or newer (the React Native Upgrade Helper shows the file changes). Only setting targetSdkVersion to 36 (and compileSdkVersion to 36 or higher) in android/build.gradle on an older version is possible, but Android 16 forces edge-to-edge, so test every screen.
- Package name: Expo uses android.package in app.json (for example com.yourname.habittracker). If it is missing, eas build asks for one, but npx expo prebuild and npx expo run:android pick com.<your Expo username>.<slug>, or com.anonymous.<slug> when you are not logged in, without asking. React Native CLI uses applicationId in android/app/build.gradle. The package name can never change after the first upload; test builds before that do not lock it.
- Expo android folder: if the project has an android folder (from npx expo prebuild) and it is uploaded to EAS, EAS builds from it and ignores the android settings and plugins in app.json, including the package name and permissions. If I have no custom native code, delete the folder (or add it to .gitignore) after changing app.json; otherwise make the same change in android/app/build.gradle.
- Version (Expo): version in app.json is the version name. eas build:configure sets appVersionSource "remote", and the production profile has autoIncrement, so EAS raises the version code on every production build and ignores android.versionCode in app.json. If builds were uploaded before EAS managed the number, run eas build:version:set and enter the highest version code already on Google Play. Raise version yourself for each user-facing release.
- Version (React Native CLI): versionCode and versionName in android/app/build.gradle (defaultConfig). Every upload needs a higher versionCode than any build ever uploaded to any track.
- EAS: npm install --global eas-cli, eas login, eas build:configure, then eas build --platform android --profile production. The production profile builds an .aab. On the first build choose Generate new keystore; EAS stores it. EAS keeps one keystore per package name, so after changing the package name, the next build asks again. Back it up: eas credentials, Android, production, credentials.json, Download credentials from EAS to credentials.json; this saves credentials.json and credentials/android/keystore.jks, keep both out of Git. The upload key's fingerprints are on expo.dev under the project's Credentials, Android, the application identifier, Android upload keystore. Download the .aab from the build page on expo.dev (Download) or the link the terminal prints.
- EAS environment variables: a .env file listed in .gitignore does not reach EAS cloud builds. Set them with eas env:set --name NAME --value VALUE --environment production --visibility plaintext (or sensitive for secrets), or the app may show a blank screen or crash only in the Play build.
- EAS Free plan: 15 Android builds a month, a low-priority queue (a build can wait a long time at busy hours) and a 45-minute build limit. eas build --platform android --profile production --local builds on macOS or Linux.
- Upload key (React Native CLI): from android/app run keytool -genkeypair -v -storetype PKCS12 -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000 (keytool comes with the JDK; Android Studio includes one). Then in ~/.gradle/gradle.properties (keeps passwords out of Git; if the lines are in android/gradle.properties, move them and make sure they were never committed) add MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore, MYAPP_UPLOAD_KEY_ALIAS=my-key-alias, MYAPP_UPLOAD_STORE_PASSWORD and MYAPP_UPLOAD_KEY_PASSWORD. Back up the keystore.
- Signing (React Native CLI): the template signs release builds with the debug key, which Google Play rejects. In android/app/build.gradle add inside the existing signingConfigs block: release { if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) { storeFile file(MYAPP_UPLOAD_STORE_FILE); storePassword MYAPP_UPLOAD_STORE_PASSWORD; keyAlias MYAPP_UPLOAD_KEY_ALIAS; keyPassword MYAPP_UPLOAD_KEY_PASSWORD } }, and in buildTypes.release change signingConfig signingConfigs.debug to signingConfig signingConfigs.release. This file is Groovy: no Kotlin syntax.
- Build (React Native CLI): npx react-native build-android --mode=release (or cd android and ./gradlew bundleRelease). Output: android/app/build/outputs/bundle/release/app-release.aab. Test the release build first: npm run android -- --mode="release". org.gradle.configureondemand=true in gradle.properties makes release builds skip the JavaScript bundle; remove it. Expo with local Android builds (npx expo prebuild) needs the same signing setup, because the prebuild template also signs release with the debug key, and npx expo prebuild --clean regenerates the android folder. If EAS already made the key, download it with eas credentials and use that keystore, never a new keytool key.
- First upload: the surest route is by hand. In Play Console, create the app, open the closed testing track, create a release and upload the .aab. eas submit can also do it, but it needs a Google service account key, the app must already exist in Play Console, and by default it sends the build to internal testing as a completed release. For the closed test, put this in eas.json: "submit": { "production": { "android": { "track": "alpha", "releaseStatus": "draft" } } }, then run eas submit --platform android and finish the draft release in Play Console. eas build:configure already created an empty "submit" section: replace it, do not add a second one. Remove releaseStatus "draft" once the first release is out, or every later submit is a draft too. "alpha" is the closed testing track Play Console already has ("Closed testing - Alpha"). Use "production" once the account can publish to production: organizations and older personal accounts from the start, new personal accounts after access is granted. Keep releaseStatus "draft" while the app itself is still a draft in Play Console.
- Service account key for eas submit (you no longer need to link a Google Cloud project in Play Console): in Google Cloud, create a project, then IAM & Admin › Service Accounts › Create service account; on it, Manage keys › Create new key › JSON › Create; enable the Google Play Android Developer API. In Play Console, Users and permissions › Invite new users, paste the service account's email, open App permissions, choose the app, and tick: View app information (read-only); Edit and delete draft apps; Release to production, exclude devices, and use Play App Signing; Release apps to testing tracks; Manage testing tracks and edit tester lists; Manage store presence. Then Invite user. This is only for eas submit on Expo; React Native CLI apps upload by hand and need no service account. Upload the JSON to EAS: expo.dev project Credentials › Android › the application identifier › Google service account key for EAS Submit, or eas credentials. Never paste the JSON into a chat.
- Play App Signing: Google keeps the app signing key and signs what users install; my key is the upload key. Expo's docs still show an old menu: the fingerprints are under Protected with Play › Play Store distribution › Go to Play app signing, App signing key section (new apps can list three keys). Add every SHA-1 and SHA-256 there to Firebase or Google Cloud for Google sign-in, after the first upload to any track. Lost upload key (CLI route): I, or anyone with admin permission, make a new key, export its certificate with keytool -export -rfc -keystore my-upload-key.keystore -alias my-key-alias -file upload_certificate.pem, then Protected with Play › Play Store protection › Manage Play app signing › Request upload key reset and upload the .pem file. On EAS the key is stored for me.
- In-app purchases: Google Play requires Billing Library 8 or later since 31 August 2026 (extension to 1 November 2026): react-native-iap 14 or newer, expo-iap 2.9 or newer, or react-native-purchases 9 or newer. Test with a build installed from a Google Play test track. In most countries, digital goods must use Google Play's billing.
- Photos: expo-media-library adds READ_MEDIA_IMAGES, READ_MEDIA_VIDEO and READ_MEDIA_AUDIO by default, and Google Play allows the photo and video permissions only for apps whose core function needs broad photo access. If the app only saves pictures, it needs no read access: ask for write-only permission (requestPermissionsAsync(true)), list READ_MEDIA_IMAGES, READ_MEDIA_VIDEO and READ_MEDIA_AUDIO in android.blockedPermissions in app.json, and test saving on a phone. granularPermissions ["photo"] still keeps READ_MEDIA_IMAGES. To let people pick a photo, use expo-image-picker, which uses Android's photo picker instead of broad photo access.
- Code shrinking: from February 2027, apps with more than 10 MB of DEX code need at least 25% optimization, obfuscation and shrinking. React Native and Expo up to SDK 57 ship with R8 off (Expo SDK 58 turns it on). Turning it on: android.enableMinifyInReleaseBuilds set to true in expo-build-properties, or enableProguardInReleaseBuilds = true in android/app/build.gradle; test the release build, because some libraries need keep rules.
- Updates over the air: EAS Update can change JavaScript, styles and images without a store update; native code, new native libraries, permissions and SDK upgrades need a new build. Updates must still follow Google Play's policies.
- Google Play costs US$25, paid once, by credit or debit card. Prepaid cards are not accepted.
- Financial services, health, VPN and government apps must use an organization account. Organizations need a D-U-N-S number, free but up to 30 days to get.
- Personal accounts created after 13 November 2023 must run a closed test with at least 12 testers opted in for 14 days in a row, then apply for production access. Internal testing does not count. Uploading a fixed build to the same closed track during the test does not restart it, because testers stay opted in. Organization accounts and older personal accounts skip both.
- Typical timeline for a new personal account: building takes under an hour (longer in the EAS free queue), then about 25 days in Google Play. Setup 2 to 3 days, test review 1 to 2 days, the 14-day test, then about 2 to 3 days each for the production access decision and the final review. A review can occasionally take up to 7 days. Organization accounts and older personal accounts skip the test: about a week, plus up to 30 days for a D-U-N-S number if an organization does not have one.

THE 8 STEPS
1. Get the project ready: Expo SDK 54+ or React Native 0.81+ (API 36), your own package name before the first upload (not com.anonymous), app name and icon, version, environment variables on EAS, and only the permissions the app needs. Test a release build on a phone (Expo: eas build -p android --profile preview gives an installable build).
2. Set up your upload key: Expo with EAS: the first production build creates it; back it up with eas credentials. React Native CLI: keytool, gradle.properties, the release signing block.
3. Build the app bundle: eas build --platform android --profile production, or npx react-native build-android --mode=release. Get the .aab.
4. Create the developer account at play.google.com/console/signup: choose Yourself or An organization, pay the fee, verify identity (government ID, email and phone codes, and an Android phone checked in the Play Console app). The Google account used becomes the owner, so use one I will keep.
5. Create the app: Home › Create app, the app name, default language, App or Game, Free or Paid (a free app can never become paid), then the declarations. Store listing: Grow users › Store presence › Store listings › Default store listing (app name 30 characters, short description 80, full description 4,000, icon 512 x 512, feature graphic 1024 x 500, 2 to 8 phone screenshots). App content: Policy and programs › App content; answer every item; Data safety must cover every library that collects data (Firebase, analytics, ads, crash reporting). The package name is set by the first upload.
6. Upload the first build: new personal accounts use Test and release › Testing › Closed testing, not Test and release › Testing › Internal testing (where eas submit puts builds by default). Click Manage track on the closed testing track that is already there (extra closed tracks cannot target countries), add countries (all countries is simplest), create a release and upload the .aab by hand, or use eas submit with track "alpha" and releaseStatus "draft". Organization accounts and older personal accounts can create a production release instead. Add the Play fingerprints now if the app uses Google sign-in.
7. Closed test (new personal accounts only): add testers by email list or Google Group, send the release for review from Publishing overview. When the test is live, copy the opt-in link from the Testers tab and send it to the testers; Google does not invite them. Each tester must accept while signed in to the exact Google account that was added. Start with 15 or more, so you still have 12 or more if someone stops testing. Dropping below 12 does not restart the 14 days; Google judges how engaged the testers were when you apply. If I added the Testers Community MCP, use it to help me get testers. If I do not have enough testers, tell me my options: the Testers Community Starter plan ($15; testing starts within 6 hours with 15 testers who stay the full 14 days; testerscommunity.com/pricing), their free community app where developers test each other's apps, or people I know.
8. Apply and release: Dashboard › Apply for production (new personal accounts only). The form has 10 questions, 2 of them multiple choice. Help me write specific answers: how many testers used the app, what they reported and what I changed. The decision usually arrives by email in 2 to 3 days. Then Test and release › Production › Create new release › Add from library (or upload a newer bundle), release notes, countries, then Publishing overview › Send changes for review. Later updates can go straight to production with eas submit and "track": "production".

COMMON ERRORS (use these fixes)
- "signed in debug mode": React Native CLI or Expo prebuild: add the release signing (step 2), check buildTypes.release uses signingConfigs.release, rebuild. EAS cloud builds are signed for me.
- "Version code N has already been used": Expo: eas build:version:set to the highest code on Google Play (shown in Play Console's App bundle explorer or each release's details), then build again. CLI: raise versionCode. If that build is already in Play on another track, use Create new release › Add from library instead of uploading it again.
- "APKs are not allowed for this application": a preview profile built an APK; build with the production profile.
- "App must target Android 16 (API level 36)": Expo SDK 54+ or React Native 0.81+. Only existing apps could get an extension (to 1 November 2026, from Policy status).
- "App must support 16 KB memory page sizes": Expo SDK 54+ or React Native 0.81+ (needed for API 36 anyway), then update native libraries (npx expo install --fix on Expo). A new app must support 16 KB now; 1 February 2027 is only the extended deadline for updates to existing apps.
- "Only releases with status draft may be created on draft app": set "releaseStatus": "draft" in eas.json, or upload the first build by hand.
- Blank screen or instant crash only in the Play build: missing EAS environment variables, R8 keep rules, or configureondemand. Reproduce with a release build.
- Google sign-in DEVELOPER_ERROR only from Google Play: add the Play app signing fingerprints.
- "There is no deobfuscation file associated with this App Bundle": a warning only; carry on.

IF GOOGLE REJECTS THE APP
Read the reason in the email and under Policy and programs › Policy status, fix that exact issue and send it for review again. Common causes: a missing privacy policy, no way to delete an account, Data safety answers that leave out a library, photo and video permissions the app does not need, the advertising ID question answered wrongly when an ads SDK is used, and too little tester activity. Every fix needs a new build with a higher version code.

Start now by asking me the START HERE questions.

Keep these out of the chat

Never paste passwords, card numbers, ID details, your keystore, credentials.json, your service account key file or Expo tokens into an AI chat. The prompt tells your AI not to ask for them.

Sources

Checked against Expo's, React Native's, Android's and Google Play's own pages on 10 October 2026. Images marked "Based on an Expo docs screenshot" are adapted from Expo's documentation, Copyright (c) 2017 650 Industries, Inc., used under the MIT License. Images marked "Image: Android Developers" are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.