Android: build, install and pair a phone
Every app project builds an Android APK alongside the web app. You install it on your phone and pair the phone once; after that it syncs with the app’s database on its own and works offline.
1. Build
Push to main. Every push builds both targets, and the push output names the builds. You can follow them on
the app’s Builds page (/manage/<app>/builds), where each build has a Log.
- Rebuild Android on the Builds page rebuilds the latest
mainwithout a push. - A newer push replaces a build of the same target that hasn’t started yet.
- A build fails if
gen/is stale (runpdb codegenand commit it),schema.sqlisn’t an approved schema version, or the APK asks for a permission thatapp.jsondoesn’t declare. The error is on the build row.
APKs are signed with the platform’s key, so each new build installs over the previous one and keeps the app’s local data and pairing.
2. Install
On the phone, sign in to the platform in the browser and open the app’s Builds page.
- Tap APK on the latest successful Android build.
- Allow your browser to install apps when Android asks (Install unknown apps), then install.
3. Pair
The first time it opens, the app shows a pairing code (XXXX-XXXX) and a URL (<platform>/pair).
- Tap Open in browser on the phone, or open
/pairon any device where you’re signed in and type the code. - Check that the code, device name (e.g.
Google Pixel 8), app and build match the phone in front of you, then Approve.
The app picks the approval up within a few seconds and starts syncing. A code expires after 10 minutes; the app then shows a new one. If you deny it, the app shows a new code as well.
Using it
The bar at the top of the app shows the sync state:
| Status | Meaning |
|---|---|
| Synced | Up to date. Sync now forces a sync. |
| Offline | Changes are saved on the phone and upload when the network is back. |
| N unsynced | Local changes waiting to upload. |
| Changes refused | The platform or the database refused a change. Nothing uploads until you Try again (after a fix) or Reset this device’s copy, which discards the phone’s unsynced changes and downloads a fresh copy. |
| A newer version is available | The schema has moved on. The installed build keeps working; install a newer APK to get the new fields. |
Deleted rows go to the app’s Bin on the platform, where you can restore them.
Managing devices
The app’s Devices page (/manage/<app>/devices) lists every paired phone and browser with its build,
schema version and last use.
- Revoke cuts a device off immediately. It keeps its local data and unsynced changes, and shows a new pairing code; approve it to reconnect.
- Block build stops every client on that build from syncing. They show Update required until a newer APK is installed (their local data is kept). Unblock it under Blocked builds.
Troubleshooting
- “Can’t reach …” on the pairing screen: the phone can’t reach the platform URL baked into the APK (for a private platform, check that the phone is on the VPN/tailnet).
- Update required: the build is blocked, or the APK expects a newer schema than the platform has approved. Install the latest build, or approve the pending schema change.
- The phone won’t install over the old app: the APK was signed with a different key (for example a local
gradle assembleDebugbuild). Uninstall the old app first; unsynced changes on the phone are lost.