JavaScript
min read
Last update on

Building APKs locally with expo: a step-by-step guide

Building APKs locally with expo: a step-by-step guide
Table of contents

Building an APK locally with Expo gives you greater control over your development workflow, allowing you to generate a standalone Android package without depending on Expo’s cloud build services. 

This approach is particularly valuable for developers who need faster iteration, offline capabilities, or want to customize their build process.

In this blog, we’ll walk you through the steps to build an APK locally using Expo, highlight the tools you'll need, and cover potential challenges you might face along the way.

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js (Latest LTS version recommended)
  • Expo CLI (npm install -g expo-cli)
  • Android Studio (with Android SDK and emulator support)
  • EAS CLI (npm install -g eas-cli)

Step 1: Initialise an Expo project

If you don’t already have an Expo project, create one with the following command:

npx create-expo-app myApp
cd myApp

Step 2: Configure Expo for bare workflow

By default, Expo manages builds in the cloud, but to generate an APK locally, we need to prebuild our project:

npx expo prebuild

This command converts your managed Expo project into a bare React Native project with the necessary Android and iOS folders.

Step 3: Open the project in Android studio

  1. Open Android Studio.
  2. Click Open and navigate to your project’s android directory.
  3. Let Android Studio sync the Gradle files.
  4. Ensure you have installed the required Android SDKs.

Step 4: Build the APK using Gradle

To build an APK, use the following command inside the android directory:

cd android
./gradlew assembleRelease

This process might take a few minutes. Once completed, your APK will be located in:

android/app/build/outputs/apk/release/app-release.apk

Step 5: Signing the APK (optional)

For distribution, you should sign your APK. Generate a keystore using:

keytool -genkeypair -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-key-alias

Move the generated keystore to android/app/ and update the android/app/build.gradle file to reference your signing details.

 Signing the APK
 Signing the APK

Step 6: Install and test the APK

Once the APK is built, install it on an Android device or emulator:

adb install android/app/build/outputs/apk/release/app-release.apk

You can now run and test your Expo-built Android application locally!

Alternative method: building APK locally with EAS build

EAS Build is available to anyone with an Expo account, regardless of whether you pay for EAS or use their Free plan. You can sign up at https://expo.dev/signup.

Expo also provides EAS Build (Expo Application Services), which allows you to build APKs locally without manually handling Gradle commands. Here’s how:

1. Install EAS CLI (if not installed already):

npm install -g eas-cli


2. Configure EAS for local builds:

eas build: configure

3. Run a local build:

Android: eas build --local --platform android
iOS: eas build --local --platform ios

Alternatively, you can use --platform all option to build for Android and iOS at the same time:

eas build --local --platform all

4. This command will build the APK on your local machine.

5. Find the generated APK:

  • The built APK will be located inside the dist/ directory in your project.

Why use EAS build locally?

  • Automates the build process without requiring manual Gradle commands.
  • Works with both managed and bare workflows.
  • Simplifies configuration and signing.


If you are already signed in to an Expo account using Expo CLI, you can skip the steps described in this section. If you are not, run the following command to log in:

eas login

You can check whether you are logged in by running

eas whoami

Configure the project

To configure an Android or an iOS project for EAS Build, run the following command:

eas build:configure

Expo APK local build: The challenges I faced & how I solved them

While building an APK locally with Expo, you might encounter various challenges. Here are some common issues and how to resolve them:

1. Gradle version issues

Problem: The Build fails due to incompatible Gradle versions.
Solution: Update your Gradle version in android/gradle/wrapper/gradle-wrapper.properties.

Find this line:
distributionUrl=https\://services.gradle.org/distributions/gradle-x.x.x-all.zip


Update it to the latest stable version. You can find the latest version here.
Example:
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip

Gradle version

Update Gradle Plugin (If Needed) android/build.gradle

find classpath 'com.android.tools.build:gradle:x.x.x'


Update it to the latest version found in Android Gradle Plugin release notes.

Ensure your Android SDK is current.

2. Java version mismatch

Problem: Gradle build fails due to incompatible Java versions.
Solution: Ensure you are using the correct Java version (usually Java 11 or Java 17) by setting it in your environment variables.
Open a terminal or command prompt and run: java -version
If the version is not Java 11 or Java 17, you need to update it.

Install the Correct Java Version

Windows: Download & install Java from Adoptium or Oracle.

Mac/Linux: Use Homebrew (Mac) or SDKMAN (Linux) to install:

brew install openjdk@17

macOS/Linux

Open the Terminal and edit your shell config:

nano ~/.zshrc  # (For macOS with zsh)

nano ~/.bashrc  # (For Linux or bash)


Add this

export JAVA_HOME=$(/usr/libexec/java_home -v 17) 
export PATH=$JAVA_HOME/bin:$PATH


Apply changes:

source ~/.zshrc  # or source ~/.bashrc

Verify the version:

 java --version


Set Java Version in gradle.properties

Open:android/gradle.properties
Add: org.gradle.java.home=/path/to/java17
(Replace /path/to/java17 with your actual Java installation path.)

3. Dependency conflicts

Problem: Errors related to conflicting dependencies in package.json.
Solution: Run expo doctor to identify issues and resolve conflicts by upgrading/downgrading dependencies as needed.

4. Missing Android SDK or emulator issues

Problem: The build process cannot locate the required Android SDK.
Solution: Install and configure the Android SDK in Android Studio and set ANDROID_HOME and ANDROID_SDK_ROOT environment variables.

5. Build fails with Hermes

Problem: The app crashes or doesn't build due to the Hermes engine. 

Solution: Try disabling Hermes by modifying android/app/build.gradle or ensure you are using a compatible Hermes version.

Check if Hermes is enabled

Open:

android/app/build.gradle

Find this block:

project.ext.react = [enableHermes: true  // Change to false to disable Hermes]


If enableHermes: true, try switching it to false and rebuilding.

6. Slow build times

Problem: Gradle takes too long to compile the project. 

Solution: Enable Gradle caching and daemon mode, and use a more powerful machine for faster builds.


Enable gradle daemon & caching

1. Open:

~/.gradle/gradle.properties

(If it doesn’t exist, create it.)

2. Add or modify these lines:

org.gradle.daemon=true          # Keeps Gradle running in the background for faster builds

3. Enable build caching

org.gradle.caching=true         # Enables build caching

4. Enable parallel execution

org.gradle.parallel=true        # Enables parallel execution

5. Configures projects on demand

org.gradle.configureondemand=true  # Configures projects on demand

6. Limits worker processes (adjust based on CPU)

org.gradle.workers.max=4        # Limits worker processes (adjust based on CPU)

Use a faster gradle distribution

1. Open

android/gradle/wrapper/gradle-wrapper.properties

2. Update to the latest Gradle version (check Gradle Releases):

distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip

Allocate more RAM to gradle

1. Open

android/gradle.properties

2. Add

org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m -Dkotlin.daemon.jvm.options="-Xmx2g"(Increase -Xmx4g based on available RAM.)

Use incremental compilation

1. Open

android/build.gradle

2. Add this inside the android block:

 android {...    
compileOptions {
        	incremental true  // Enables incremental Java compilation
   	     }
   }

Conclusion

Building APKs locally with Expo gives you complete control over your app’s build process, making it an excellent choice for offline development, thorough debugging, and distributing apps without depending on cloud-based services. This approach can be especially helpful when working in secure environments or when faster iteration cycles are needed. 

However, it’s important to be prepared for some common hurdles along the way, such as Gradle version mismatches, dependency conflicts, or issues related to Android SDK configuration. 

By identifying and addressing these challenges early, you can create a more reliable and streamlined build workflow. 

With the right tools, attention to detail, and a clear understanding of the process, you can confidently build, test, and distribute your Expo-based Android applications entirely on your local machine.

Happy coding!

Written by
Editor
Ananya Rakhecha
Tech Advocate