Appearance
Android
For: getting the game onto an Android phone, and from there onto Google Play.
What the Android app is
The Android app is the same Expo application as the iOS one. It wraps the web game in a native shell that loads the deployed site in a web view. On top of that it adds deep links, haptics, push notifications, a wake lock, offline and update-required screens, and hardware back-button handling.
Shipping a change to the game itself is therefore a web deploy rather than a Play submission. A new binary is needed only when the native shell changes.
The project lives under platforms/mobile, and its configuration is platforms/mobile/app.config.ts.
Identity
These values are committed. The application id is the same string as the iOS bundle identifier, and changing it after a Play release starts a new listing rather than updating the existing one.
| Item | Value |
|---|---|
| Display name | Grafted Wars |
| Application id | com.graftedwars.game |
| Expo slug | grafted-wars |
| Expo account | evgeniiarts |
| URL scheme | graftedwars |
| Version | 1.0.0, with version codes held remotely by Expo |
| Orientation | portrait |
| Adaptive icon | a foreground image over the palette's background colour |
Three permissions are blocked outright in the configuration, so no dependency can quietly add them: the overlay permission, and both external-storage permissions. That keeps the Play listing's permission set small and the review short to answer for.
Once per machine
Install the mobile project's own dependencies, which are separate from the repository root's:
bash
npm ci --prefix platforms/mobileBuilding locally also needs a Java toolchain and the Android SDK, with adb on your path for device work. Building through Expo's hosted builders needs none of that.
Which server the app talks to
The shell points at the production site by default. Override it to aim elsewhere:
bash
GRAFTED_WARS_GAME_URL=https://<staging address> npx eas build --platform android --profile previewThe value is validated rather than trusted. A URL carrying embedded credentials is discarded, and a plain-HTTP URL is discarded unless it is localhost and GRAFTED_WARS_ALLOW_HTTP_LOCALHOST is set to true.
Run it on a device
Start the development server:
bash
npm run start --prefix platforms/mobileTo build and install a native debug build on a connected device:
bash
npm run android --prefix platforms/mobileRegenerating the native project from the configuration, when a plugin or an identity value changes:
bash
npm run prebuild:android --prefix platforms/mobileProve it on real hardware
The project carries a script that drives a connected device and reports what it found. Three forms exist:
bash
npm run prove:android --prefix platforms/mobile
npm run prove:android:debug --prefix platforms/mobile
npm run prove:android:release --prefix platforms/mobileUse the release form before a store build, because a release build differs from a debug one in ways that only show on a device.
Build for distribution
Three profiles exist in platforms/mobile/eas.json, and the artifact differs by profile.
| Profile | Artifact | For |
|---|---|---|
development | development client build | day-to-day work against a dev server |
preview | an APK | sideloading onto a device, or handing to a tester |
production | an app bundle | a Play submission, with the version code incremented automatically |
An APK you can install directly:
bash
npx eas build --platform android --profile previewA Play-ready app bundle:
bash
npx eas build --platform android --profile productionPlay accepts app bundles rather than APKs for new releases, which is why the production profile differs from preview here and does not on iOS.
Credentials
Expo generates and holds the upload keystore, and prompts for what it needs on the first build.
| Item | Where it comes from |
|---|---|
| Upload keystore | generated and stored by Expo on the first build, or supplied by you |
| Google Play developer account | play.google.com/console |
| Play service account key | a Google Cloud service account, granted access in the Play Console |
| Expo access token | expo.dev → Account Settings → Access Tokens, for non-interactive builds |
Losing the upload keystore without Play App Signing enrolled means no further update can be published to that listing. Enrol in Play App Signing and let Google hold the app signing key, so a lost upload key can be reset rather than being fatal.
None of these belong in this repository. Credentials and access is the index.
Google Play submission
Once a production build finishes, submit it:
bash
npx eas submit --platform android --profile productionThe submission profile carries no options of its own, so the interactive prompts decide the target track. The listing, screenshots, content rating and data-safety declarations are filled in through the Play Console rather than from here.
Prove it before you ship
Type-check the mobile project from the repository root:
bash
npm run mobile:typecheckThe project also carries its own suite, run from its own directory:
bash
npm test --prefix platforms/mobileSharp edges
A web deploy changes what every installed app shows, because the shell loads the live site. A bad production deploy reaches phones with no store involvement.
The app images are generated rather than hand-drawn. Run npm run images:check --prefix platforms/mobile when an icon or splash asset changes.
Version codes are held remotely by Expo rather than in the repository, so two machines cannot disagree about the next one.