Skip to main content

Android

Not built on the authors' machine. npm run android (prebuild, Gradle, an emulator or a phone) was never run for this page. What was run: npx expo config (valid, the react-native-webgpu plugin resolves) and npx expo prebuild --no-install --clean in a throwaway copy of the template, which succeeded and gave the values below. It is not known from our own runs whether the app launches, whether WebGPU draws on an emulator, or how fast it runs. The steps are Expo's standard ones, checked against Expo SDK 58's docs and the template's config.

On Android your game is an ordinary Expo app: expo run:android generates the native project, builds it with Gradle, installs it and loads the game's JavaScript from Metro. The engine needs nothing from the Moonspell app to run there (What is and is not open).

Prerequisites​

  • Android Studio with the Android SDK, and an emulator or a phone with USB debugging on.
  • Java (a JDK). expo run:android needs Android Studio and Java installed and configured.
  • Node and npm, and a real npm install in the game's folder.

Run it​

npm install
npm run android

npm run android is expo run:android. The first run generates android/ (Expo's prebuild), compiles a debug build, installs it on an emulator or a connected phone and starts Metro. Later runs skip prebuild while android/ exists. Arguments after -- go to expo run:android:

npm run android -- --device

--device lets you pick a connected phone or an emulator.

The template does not include expo-dev-client, so this is a plain debug build that loads from Metro, without the development launcher screen.

What app.json needs​

The Android part of the template's app.json:

{
"expo": {
"orientation": "portrait",
"android": { "package": "com.rofi.crescentmoon.game" },
"plugins": ["react-native-webgpu"]
}
}
KeyWhy
plugins: ["react-native-webgpu"]Required on Android. react-native-webgpu's native code needs API level 26 (androidMinSdkVersion in its package.json), and its build.gradle does not go lower for an app with a lower minSdkVersion, so such an app fails with a manifest-merger error. Expo's default is 24. The config plugin raises the app's minSdkVersion to 26
android.packageChange com.rofi.crescentmoon.game to an id of your own. It becomes the namespace and applicationId
orientation: "portrait"Becomes screenOrientation="portrait" on the activity

What the prebuild check generated:

SettingValue
android.minSdkVersion26 (Android 8.0)
newArchEnabledtrue
hermesEnabledtrue
namespace, applicationIdcom.rofi.crescentmoon.game
screenOrientationportrait

The template sets no scheme, so your build opens no deep links. If you add one, useLaunchRoomId() reads ?room=CODE from the link through React Native's Linking (Net). Not tested.

Emulators and phones​

On Android, react-native-webgpu runs Dawn on Vulkan. Its docs warn that Android emulators may fall back to a software adapter: slow, and some features may be missing. Test performance on a real phone.

Release builds​

At a pointer level only; none of this was run for the engine:

  • Locally: npx expo run:android --variant release makes a release build, unsigned. Signing it for the Play Store is covered by Expo: local app production.
  • In the cloud: EAS Build (eas build --platform android), which handles the keystore (Expo: EAS Build). Expo's development-build profiles expect expo-dev-client, which the template does not include.

Different from the Moonspell app​

Inside the Moonspell appYour Expo build
How the game loadsThe app loads the game's Android export into its own runtimeYour app is the game; Metro serves it in development
Exit buttonBack to the app's gamesexitToShell() does nothing; the template's App.tsx unmounts the game and shows its "Play" button
Paused off screenYes, while the app's feed keeps the game loaded but not shownNever: the game is always active
getLaunchUrl(), getShareUrl(), roomInviteUrl()The app passes the links innull
The app's feed and share linksYesNo
Game backendThe game's own WorkerGAME_BACKEND_URL is null in the template: leaderboards, presence and rooms stay on this device until you deploy the backend and set it

Icons on Android draw the Material Symbol twin of each SF Symbol, and Skia text uses the sans-serif family where the engine names a system font. These and the other differences are on Platform differences.

See also​