Building an Android release normally means a working Android Studio install, the right JDK, a Gradle cache that eats your disk, and a keystore file that lives on one laptop. VibeView cloud builds move all of that off your machine. The CLI uploads your project source, the build runs in a clean environment, and you get back either a debug build you can run on a cloud Android emulator straight away, or a signed release you can send to Google Play from the same terminal.
This guide follows one app from source to the Play Console’s internal testing track: a debug .apk first, then a signed .aab, then the upload. It works the same from Windows, Linux or macOS.
What you need
- A VibeView account and the CLI:
npm install -g vibeview && vibeview login - A React Native project, bare or Expo (for a managed Expo project with no
android/folder, see Build an Expo app without EAS) - For the store step: a Google Play Console account with the app created in it, and a Google Cloud service account (covered below)
You don’t need Java, Gradle or the Android SDK locally. Every plan includes cloud builds each month; builds beyond your plan’s allowance draw from usage credit. The pricing page has each plan’s numbers.
Part 1: a debug build on a cloud emulator
-
Start the build from your project root.
vibeview build --cloud --platform androidThe first run asks for two things and saves them to
vibeview.json: the build command, and where the finished file lands. For a bare React Native project the suggestion is a GradleassembleDebug. Make sure the command installs your dependencies, becausenode_modulesis never uploaded:{ "defaultPlatform": "android", "platforms": { "android": { "build": { "command": "yarn install --immutable && cd android && ./gradlew assembleDebug", "artifact": "android/app/build/outputs/apk/debug/*.apk" } } } }Use whatever your lockfile calls for:
npm ci,yarn install --immutableorpnpm install --frozen-lockfile. -
Watch the log. The CLI packs every file git tracks plus untracked files that
.gitignoredoesn’t exclude, uploads them, and streams the Gradle output. Add--no-waitto start the build and leave;vibeview builds logs <id> --followpicks it back up. -
Run it. A succeeded debug build lands in the app’s Build history with a
cloudbadge. If the project had no app yet, the build creates one from the binary and the CLI writes itsappIdintovibeview.json. Open the build’s page and choose Run this build to start it on a cloud Android emulator in the browser, or runvibeview dev --platform androidto work on it with Metro and hot reload.
You’ll know it worked when the build page shows added to app builds on its timeline and the app launches on the emulator. If your build filters native ABIs, keep x86_64 in the list. VibeView’s Android emulators run x86_64 natively, and some of them can also run ARM code through ARM translation, but a translated app can crash at launch and an ARM-only build is limited to the devices that support it (Preparing your build has the details). React Native’s default architectures already include x86_64.
Part 2: a signed .aab for Google Play
A production build is a different artifact with a different job. It is signed with your release key, it is meant for the store, and it doesn’t install on a VibeView device. It shows up on the Builds page with a Download action instead of in Build history.
-
Get a keystore. If you already have one, upload it; every password is prompted with hidden input, never passed as a flag:
vibeview credentials add --platform android --file release.jksIf you’ve never made one, let VibeView generate it. No
keytoolneeded:vibeview credentials generate --platform android --name releaseThis stores the keystore as a signing credential, saves a copy of the file locally and prints its passwords. Keep your own backup, though an organization admin can re-download a generated keystore later with
vibeview credentials download release. -
Point Gradle at it. Add this block to
android/app/build.gradle. VibeView sets the four properties only during a production build, and thehasPropertyguard keeps your local debug builds unaffected:if (project.hasProperty('VIBEVIEW_STORE_FILE')) { signingConfigs { release { storeFile file(VIBEVIEW_STORE_FILE) storePassword VIBEVIEW_STORE_PASSWORD keyAlias VIBEVIEW_KEY_ALIAS keyPassword VIBEVIEW_KEY_PASSWORD } } buildTypes.release.signingConfig signingConfigs.release }Keep the
signingConfigassignment inside the guard. A managed Expo project has no checked-in Gradle file, so it adds the same block with a small config plugin; the App Signing docs explain how. -
Turn on automatic version codes. Google Play refuses an upload that reuses a
versionCode. SetautoIncrementand every production build gets the next number from a counter VibeView keeps per app and platform, passed to the build asVIBEVIEW_BUILD_NUMBER:// android/app/build.gradle, inside defaultConfig versionCode (System.getenv("VIBEVIEW_BUILD_NUMBER") ?: "1").toInteger()If the app is already on Play, seed the counter once with your current highest
versionCode:vibeview versions set --app <app-id> --platform android <number>makes the next production build<number>+ 1. -
Build the release.
vibeview build --cloud --production --platform androidThe first run asks for the release command and offers a Gradle
bundleRelease, which writes an.aab. Yourvibeview.jsonthen carries both builds side by side:{ "platforms": { "android": { "appId": "my-app-abc123", "build": { "command": "yarn install --immutable && cd android && ./gradlew assembleDebug", "artifact": "android/app/build/outputs/apk/debug/*.apk", "productionCommand": "yarn install --immutable && cd android && ./gradlew bundleRelease", "productionArtifact": "android/app/build/outputs/bundle/release/*.aab", "autoIncrement": true } } } }Want a signed
.apkinstead, to hand to a tester outside the store? Point the release command atassembleReleaseand the artifact atandroid/app/build/outputs/apk/release/*.apk.vibeview builds download <id>saves either file locally.
Part 3: upload the .aab to Google Play from the command line
Google’s publishing API can update an app but can’t create one, so do two one-time things first: create the app in Play Console (All apps → Create app), and set up a service account. In Google Cloud, create the account under IAM & Admin → Service Accounts and download its JSON key, enable the Google Play Android Developer API for that project, then invite the account’s email in Play Console under Users and permissions with release access. Store the key once:
vibeview credentials play-key add --file service-account.json
Check that Play knows your app before you spend a build on it. No build is needed:
vibeview submit --check --platform android --package com.example.myapp
Then upload:
vibeview submit --platform android --latest --track internal
--latest picks your newest succeeded production build. The package name is read from the .aab itself. Releases on internal, alpha and beta default to completed, so testers get them right away. On production the default is a draft that waits for you in Play Console. --release-status inProgress --rollout 0.1 starts a staged rollout to 10% of users instead. To skip the flags next time, put "submit": { "track": "internal" } next to the build block in vibeview.json.
The upload is the binary only. Store listing, screenshots and release notes stay in Play Console, exactly as if you had uploaded the file by hand. Eligible builds also get a Submit to store button on the dashboard’s Builds page.
Android TV uses the same keystore
An Android TV app needs no credential of its own. Android TV production builds sign with your Android keystore, so one key, uploaded or generated, covers your phone and TV builds. Build with --platform androidtv and submit with vibeview submit --platform androidtv --track internal. For a TV debug build, include both x86 and x86_64 native code so it runs on every Android TV emulator. The Apple TV and Android TV build guide walks through a TV project end to end.
Troubleshooting
Cannot find moduleorCouldn't find the node_modules state file. The build command never installed dependencies. Addnpm ci(or your package manager’s equivalent) to the front of it.- Play refuses the upload as a duplicate version code. Turn on
autoIncrement, or seed the counter above your highest existingversionCodewithvibeview versions set. - “create the app in Play Console first”. The app doesn’t exist in Play Console yet, or its package name differs from the one in your build.
- The service account “lacks release permission”. Invite its email in Play Console under Users and permissions and grant release access.
- The production build fails as unsigned. The
signingConfigassignment sits outside thehasPropertyguard, or the block is missing. VibeView refuses an unsigned artifact when it supplied credentials.
Frequently asked questions
Frequently asked questions
Can I build an .aab without Android Studio?
Yes. The cloud build runs Gradle for you, and vibeview credentials generate --platform android creates the keystore without keytool. Your machine only needs Node.js for the CLI.
What if I lose the keystore?
New Play apps use Play App Signing by default, which makes your keystore an upload key: Google Play support can help reset a lost one. Apps on legacy direct signing can’t be updated without the original key. A keystore VibeView generated can be re-downloaded by an organization admin; an uploaded one can never be read back.
Can I run the signed .aab on a VibeView emulator?
No. Production builds are for the store and can’t be installed on a VibeView device. Test with the debug build from Part 1, which runs on a cloud Android emulator.
Do I still need a Mac for the iOS version?
No. The same commands build iOS on VibeView’s macOS builders and upload to TestFlight. See Upload to TestFlight without a Mac.
Next steps
- Not using React Native? Flutter, Capacitor and Ionic and Kotlin Multiplatform projects cloud-build the same way, and so do native Xcode and Gradle projects
- Cloud Builds, App Signing and Store Submission: the full reference
- Run an APK online, if you already have an
.apkand only need a device - Cloud builds overview: what builds on VibeView, for iOS, Android, Apple TV and Android TV