Boot an emulator (SDK Manager installs the system images; Appendix A lists the emulator and adb commands) and there are three ways to run the app. npm 2,036 run android opens the project in Expo Go 6,418 , installing Expo Go if needed, and compiles nothing (Expo Go). npx expo run:android generates android/, builds a debug APK, installs it, starts Metro and launches the app: the everyday command. Or do those steps by hand, as a CI script would, which shows what happens:
npx expo prebuild --platform android
cd android && ./gradlew assembleDebug✔ Created native directory ... ✔ Finished prebuild ... BUILD SUCCESSFUL in 11m 44s 213 actionable tasks: 213 executed
The first build compiles React Native 36,878 's C++ with CMake for four CPU architectures; later builds reuse Gradle 19,597 's cache. A debug APK contains no JavaScript: it fetches the bundle from Metro, and without Metro it shows a red "Unable to load script" screen, which is not a build failure. So install it, start Metro and launch:
adb -s emulator-5566 install -r android/app/build/outputs/apk/debug/app-debug.apk
npx expo start --port 8086 &
adb -s emulator-5566 shell am start -n com.example.booknest/.MainActivityPerforming Streamed Install
Success
Starting: Intent { cmp=com.example.booknest/.MainActivity }
Starting project at /home/dev/ch03-02/BookNest
Starting Metro Bundler
...
Android Bundled 2205ms index.js (696 modules)The app shows the template's line of text (the left screen of the figure in Fast Refresh and Metro). -s picks one device when several are attached, and port 8086 is used only because this machine runs several Metro servers; yours can use the default 8081. An emulator reaches your computer at 10.0.2.2, and the app looks for Metro at 10.0.2.2:8081 unless you build it with -PreactNativeDevServerPort=8086, as was done here. A USB phone needs adb reverse tcp:8081 tcp:8081 instead. If am start only brings back an old error screen, run adb shell am force-stop com.example.booknest first so that the bundle reloads.