This project uses Rock to manage native builds. Rather than compiling native code locally when running commands like npm run android, Rock first attempts to download remote builds (artifacts prebuilt on CI) from S3. If a matching remote build isn’t available, it automatically falls back to building locally.
By storing complete native build artifacts remotely, Rock reduces the need for local compilation and simplifies setup through automated downloads.
Note: Any changes to files involved in generating a fingerprint (e.g., package.json) will trigger a local build.
The following steps describe how to configure the project to fully utilize Rock.
- To install project dependencies run:
npm install - To start metro server run:
npm run startNote: For now this is a required step — metro needs to be called manually in a separate terminal. - To run application on a Development Simulator:
- For standalone
npm run android-standalone - For hybrid app
npm run android
- For standalone
After completing these steps, you should be able to start both mobile platform apps using the remote build.
If you haven't done any intentional edits outside of src/ (like adding new dependencies) but your app is still running into a full build, remember that it's way easier to debug and address a remote cache miss rather than any compilation error.
-
Try re-installing dependencies:
npm run i-standalonefor the standalone appnpm installfor the hybrid app
-
Try running:
- For standalone
npm run android-standalone - For hybrid app
npm run android
- For standalone
-
If you’re still encountering errors, you can try running:
git clean -fdx android/when running standalone appgit clean -fdx ./Mobile-Expensifywhen running hybrid app
-
Then try running again:
- For standalone
npm run android-standalone - For hybrid app
npm run android
- For standalone
-
If the issue persists, verify that workflow in the GitHub repository have completed successfully:
- Android builds If the workflow is still running, open it and verify it matches your fingerprint. Once complete, Rock should download the remote build. If not, check whether the last main commit hash merged into your branch has the same fingerprint as yours.
If the fingerprints do not match, run:
npx rock fingerprint -p android --verboseCompare the results with the GitHub Actions output to see which files have different fingerprints.
-
In the event of workflow failures, it is recommended to have the option to manually build the application. The following steps will cover the manual build process.
-
Configure MapBox
- Before installing Android dependencies, you need to obtain a token from Mapbox to download their SDKs. Please run
npm run configure-mapboxand follow the instructions. If you already did this step for iOS, there is no need to repeat this step.
- Before installing Android dependencies, you need to obtain a token from Mapbox to download their SDKs. Please run
-
React Native Environment Setup
- Go through the official React-Native instructions on this page to start running the app on android.
-
ccache Setup (Optional)
- The Android project can utilize ccache to significantly reduce compilation times. Since C/C++ code doesn't change as frequently, ccache can cache compilation results and reuse them across builds.
- Install ccache via Homebrew:
brew install ccache - Once installed, the build system will automatically detect and use ccache when available.
- To view cumulative statistics on cache usage, run:
ccache --show-stats - Note: If you encounter any issues with the ccache cache, our clean command (via Rock CLI) will automatically clean the ccache directory as well.
- To run on a Development Emulator:
npm run android - Changes applied to Javascript will be applied automatically, any changes to native code will require a recompile
If you are an Expensify employee and want to point the emulator to your local VM, follow this
By default, react-native is built from source when building the Android app. However, you can enable prebuilt artifacts to speed up the build process:
- Open
android/gradle.properties(for Standalone NewDot) orMobile-Expensify/Android/gradle.properties(for HybridApp) - Set
patchedArtifacts.forceBuildFromSource=false
To use prebuilt artifacts, you need to have GitHub CLI installed and configured:
-
Install GitHub CLI
- Install GitHub CLI by following the instructions from cli.github.com
-
Create a GitHub Personal Access Token
- Go to GitHub Settings > Developer Settings > Personal Access Tokens
- Click "Generate new token (classic)"
- Select the following scopes:
reporead:orggistread:packages
- Copy the generated token
-
Login to GitHub CLI
echo "YOUR_TOKEN" | gh auth login --with-token
-
Verify Login
gh auth status
You should see a message confirming you are authenticated with your GitHub account.
After completing these steps, you should be able to build Android apps with prebuilt react-native artifacts.
To receive mobile push notifications in the development build while hitting the Staging or Production API, you need to use the production airship config.
Add inProduction = true to Mobile-Expensify/Android/assets/airshipconfig.properties
Copy the production config to the development config.
To test the web app in Android emulator browsers, you need to install the development certificate. The development server uses HTTPS protocol, so the Android emulator needs the same certificate installed.
You must first configure HTTPS certificates by following the instructions in the Web Setup Guide.
- Open any emulator using Android Studio
- Use
adb push "$(mkcert -CAROOT)/rootCA.pem" /storage/emulated/0/Download/to push certificate to install in Download folder. - Install the certificate as CA certificate from the settings. On the Android emulator, this option can be found in Settings > Security > Encryption & Credentials > Install a certificate > CA certificate.
- Close the emulator.
Note: If you want to run app on https://127.0.0.1:8082, then just install the certificate and use adb reverse tcp:8082 tcp:8082 on every startup.
- Run
npm run setupNewDotWebForEmulators android - Select the emulator you want to run if prompted. (If single emulator is available, then it will open automatically)
- Let the script execute till the message
🎉 Done!.
Note: If you want to run app on https://dev.new.expensify.com:8082, then just do the Android flow and use npm run startAndroidEmulator to start the Android Emulator every time (It will configure the emulator).
If you want to set up both iOS and Android simulators at once:
- Run
npm run setupNewDotWebForEmulators allornpm run setupNewDotWebForEmulators - Check if the iOS flow runs first and then Android flow runs.
- Let the script execute till the message
🎉 Done!.
The flow may fail to root with error adbd cannot run as root in production builds. In this case, please refer to https://stackoverflow.com/a/45668555. Or use https://127.0.0.1:8082 for less hassle.
Our React Native Android app now uses the Hermes JS engine which requires your browser for remote debugging. These instructions are specific to Chrome since that's what the Hermes documentation provided.
- Navigate to
chrome://inspect - Use the
Configure...button to add the Metro server address (typicallylocalhost:8081, check yourMetrooutput) - You should now see a "Hermes React Native" target with an "inspect" link which can be used to bring up a debugger. If you don't see the "inspect" link, make sure the Metro server is running
- You can now use the Chrome debug tools. See React Native Debugging Hermes
Ensure the following is set in your app's android/app/build.gradle file.
project.ext.react = [
enableHermes: true,
hermesFlagsRelease: ["-O", "-output-source-map"], // <-- here, plus whichever flag was required to set this away from default
]- Install the necessary packages:
npm i - Run your Android app in production mode
- Navigate to the feature you wish to profile.
- Initiate the profiling session by tapping with four fingers to open the menu and selecting
Use Profiling. - Close the menu and interact with the app.
- After completing your interactions, tap with four fingers again and select to stop profiling.
- You will be presented with a
Shareoption to export the trace, which includes a trace file (Profile<app version>.cpuprofile) and build info (AppInfo<app version>.json).
- You have two files:
AppInfo<app version>.jsonandProfile<app version>.cpuprofile - Place the
Profile<app version>.cpuprofilefile at the root of your project. - If you have already generated a source map from the steps above for this branch, you can skip to the next step. Otherwise, obtain the app version from
AppInfo<app version>.jsonswitch to that branch and generate the source map as described.
IMPORTANT: You should generate the source map from the same branch as the trace was recorded.
- Upon completion, the generated source map can be found at:
android/app/build/generated/sourcemaps/react/productionRelease/index.android.bundle.map - Use the following command to symbolicate the trace:
npm run symbolicate-release:android - A new file named
Profile_trace_for_<app version>-converted.jsonwill appear in your project's root folder. - Open this file in your tool of choice:
- SpeedScope (https://www.speedscope.app)
- Perfetto UI (https://ui.perfetto.dev/)
- Google Chrome's Tracing UI (chrome://tracing)
- If you are having issues with Getting Started, please reference React Native's Documentation
- For additional Android-specific troubleshooting, see the HybridApp documentation
Note: Expensify engineers that will be testing with the API in your local dev environment please refer to these additional instructions.