Create a local Production Build (AAB/APK)
While cloud builds (EAS) are convenient, there are valid reasons to build locally: saving on build quotas, keeping signing keys strictly on your own hardware, or debugging complex native compilation issues.
Unlike a Development Build, a Production Build is optimized, minified, and signed. It does not contain the Metro bundler or the developer menu.
There are two distinct output formats you can generate locally:
- AAB (.aab): The Android App Bundle. This is required for uploading to the Google Play Store.
- APK (.apk): The Android Package Kit. This is used for direct installation on a device (sideloading) without the Store.
A “Release” build requires a Keystore (signing certificate).
If you try to upload an unsigned build or a build signed with the default debug key to the Play Store, it will be rejected.
For this guide, we assume you have a keystore file ready (e.g., my-upload-key.keystore).
Otherwise if you only want to create an APK for development or testing, generate the native project and then execute the build command with option C
Prerequisites
- A workspace configured with Expo (
npx expo prebuildcapability) - Java JDK v17 installed and configured
- Android Studio & Android SDK Command-line tools
- Platform Tools (ADB) added to your system PATH
Windows User Tip:
Just like with development builds, keep your project path short (e.g., C:\GitHub\app)
to avoid the 260-character path limit error during the Gradle build process.
Configure and Build
1. Generate Native Projects
First, we ensure the native android folder exists and is up to date with your Expo config.
npx expo prebuild
2. Configure Signing (Crucial for Release)
By default, React Native uses a debug key. For a production release, you must tell Gradle to use your upload key.
Place Keystore file
Move your generated .keystore file into the android/app directory.
Edit native build properties
Add your keystore credentials here. This keeps them out of the build script itself.
MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore
MYAPP_UPLOAD_KEY_ALIAS=my-key-alias
MYAPP_UPLOAD_STORE_PASSWORD=*****
MYAPP_UPLOAD_KEY_PASSWORD=*****Ensure JDK and SDK paths are set (as in development builds)
org.gradle.java.home=C:\\path\\to\\jdk-17sdk.dir=C:\\Users\\<your-user>\\AppData\\Local\\Android\\SdkYou might need to create the file local.properties under /android
Edit android/app/build.gradle
Open android/app/build.gradle and add the signing configuration inside the android block:
android {
...
signingConfigs {
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 {
// Apply the config here
signingConfig signingConfigs.release
...
}
}
}3. execute the Build Command
Now navigate to the android folder and run the Gradle task. Choose one of the following based on your needs.
Option A: Build for Play Store (AAB)
cd android
./gradlew bundleRelease
Output location: android/app/build/outputs/bundle/release/app-release.aab
Option B: Build for Direct Install (APK)
cd android
./gradlew assembleRelease
Option C: For testing and debugging (APK)
cd android
./gradlew assembleDebug
Output location: android/app/build/outputs/apk/release/app-release.apk
Install APK via ADB
If you chose Option B and generated an APK, you can install it directly onto your connected USB device using ADB (Android Debug Bridge).
If you previously installed a Development Build or a Debug version of the app,
you must uninstall it from the phone first.
Android will not allow you to install a Release version over a Debug version because the signatures do not match.
Error message: INSTALL_FAILED_UPDATE_INCOMPATIBLE
Installation Steps
Verify Connection
Ensure your phone is connected via USB and recognized by ADB.
sh filename="Terminal" adb devices
You should see a device ID followed by device.
Install the APK
Run the install command pointing to your generated APK file.
adb install android/app/build/outputs/apk/release/app-release.apkVerify Installation
If successful, the terminal will return Success, and the app icon will appear on your device’s app drawer.
Since this is a Production Build, opening it will launch the app immediately without loading from a metro server.
Created: 21.01.2026
Last Updated: 21.01.2026