Building and Installing the App
This page covers what is needed to build the Android app, how to produce an APK, and how to install it on a phone or emulator. It reflects the project configuration in android-app/ at the time of writing.
Requirements
Section titled “Requirements”| Tool | Version | Notes |
|---|---|---|
| Android Studio | A release that supports Android Gradle Plugin 8.12 | Android Studio will warn on sync if it is too old. |
| JDK | 17 or newer | Required to run Gradle / AGP 8.x. The JDK bundled with Android Studio works. The app code itself compiles to Java 11. |
| Android SDK Platform | API 36 | Install through Settings → Languages & Frameworks → Android SDK. |
| Gradle | 8.14.4 | Downloaded automatically by the Gradle wrapper (gradlew). Do not install separately. |
No other tools, accounts or API keys are needed for a debug build.
Project configuration
Section titled “Project configuration”These values are set in android-app/app/build.gradle.kts and android-app/gradle/libs.versions.toml:
| Setting | Value |
|---|---|
applicationId / namespace | com.example.myapplication |
minSdk | 21 (Android 5.0) |
targetSdk / compileSdk | 36 |
| Android Gradle Plugin | 8.12.3 |
| Kotlin | 2.0.21 |
| Java source / target | 11 |
versionCode / versionName | 1 / 1.0 |
Backend URL
Section titled “Backend URL”The app does not have a settings screen for the server address. It is compiled into the app as BuildConfig fields in app/build.gradle.kts:
buildConfigField("String", "BASE_URL", "\"https://p27payload.benb.au/api/\"")buildConfigField("String", "MEDIA_BASE", "\"https://p27payload.benb.au\"")BASE_URLis the Payload REST API root used by Retrofit. It must end with a/, or Retrofit will throw on startup.MEDIA_BASEis prepended to relative image paths returned by Payload (e.g./api/media/file/...).
Both the defaultConfig (debug) and release blocks currently point at the development server on Ben’s machine (see Payload overview). To point the app at a different server, both pairs of lines need to be changed, followed by a Gradle sync and rebuild.
Using a local Payload server
Section titled “Using a local Payload server”When running Payload locally on port 3000, an emulator reaches the host computer at 10.0.2.2, not localhost:
buildConfigField("String", "BASE_URL", "\"http://10.0.2.2:3000/api/\"")buildConfigField("String", "MEDIA_BASE", "\"http://10.0.2.2:3000\"")Android 9 (API 28) and newer block plain http:// traffic by default, so a local HTTP server also needs a network security config that allows cleartext traffic to 10.0.2.2. This must not be shipped in a release build.
Building in Android Studio
Section titled “Building in Android Studio”- Clone the repository and open the
android-app/folder (not the repository root) in Android Studio. - Wait for the Gradle sync to finish. On first open, Android Studio creates
local.propertiescontaining the path to the Android SDK. This file is machine-specific and must not be committed. - If the sync fails with a Java version error, set Settings → Build, Execution, Deployment → Build Tools → Gradle → Gradle JDK to a JDK 17+ (e.g. the bundled JetBrains Runtime).
- Select a device or emulator in the toolbar and press Run. This builds and installs the debug version.
To produce an APK file without running it: Build → Build App Bundle(s) / APK(s) → Build APK(s).
Building from the command line
Section titled “Building from the command line”From the android-app/ folder:
# macOS / Linux./gradlew assembleDebug
# Windowsgradlew.bat assembleDebugThe APK is written to:
android-app/app/build/outputs/apk/debug/app-debug.apkThe debug APK is signed automatically with the Android debug key, so it can be installed on any device straight away. It is the build to share with the team and client for testing.
If ./gradlew fails with Permission denied, the script has lost its executable flag. Run chmod +x gradlew locally, or fix it in the repository with git update-index --chmod=+x gradlew.
Release builds
Section titled “Release builds”./gradlew assembleReleaseThe project has no signing configuration yet, so this produces app/build/outputs/apk/release/app-release-unsigned.apk, which Android will refuse to install.
To produce an installable release APK, sign it through Build → Generate Signed App Bundle / APK in Android Studio, creating a new keystore when prompted. The keystore file and its passwords:
- must never be committed to the repository;
- must be backed up safely. An app signed with a lost keystore can never be updated, since Android and Google Play only accept updates signed with the same key.
Code shrinking (isMinifyEnabled) is currently off for release builds.
Installing on a device
Section titled “Installing on a device”With USB (adb)
Section titled “With USB (adb)”- On the phone, enable Developer options (tap Build number in About phone seven times), then turn on USB debugging.
- Connect the phone and accept the debugging prompt.
- Install:
adb install -r app/build/outputs/apk/debug/app-debug.apk-r replaces an existing install and keeps its data.
Without a computer
Section titled “Without a computer”- Send the APK to the phone (e.g. Google Drive, email, or downloaded from a GitHub build).
- Open it on the phone. Android asks for permission to install apps from that source (Chrome, Files, etc.). Allow it for that app only.
- On Android 5–7 this is a single Unknown sources switch under Settings → Security.
- Tap Install.
Switching between debug and release builds
Section titled “Switching between debug and release builds”Debug and release APKs are signed with different keys. Installing one over the other fails with INSTALL_FAILED_UPDATE_INCOMPATIBLE. Uninstall the existing app first; this also clears its saved login.
Known issues
Section titled “Known issues”These do not stop a debug build but should be resolved before the app is handed over or published:
applicationIdiscom.example.myapplication. Google Play rejectscom.example.*IDs. It has to be changed to a real ID before the first store release and cannot be changed afterwards.- The server address is hardcoded for both debug and release builds (see Backend URL). A release build currently talks to the development server.
- No release signing is configured, so release builds are unsigned.
- Duplicate dependencies: Material and ConstraintLayout are declared both in the version catalog and as hardcoded strings in
app/build.gradle.kts, with different ConstraintLayout versions (2.2.1 and 2.1.4). Gradle resolves to the higher version, so this does not break the build, but the hardcoded lines should be removed. - No automated build is set up yet. Every APK is currently built on a team member’s machine.
Troubleshooting
Section titled “Troubleshooting”| Error | Cause / fix |
|---|---|
Android Gradle plugin requires Java 17 to run | Set the Gradle JDK to 17+ (see Building in Android Studio). From the command line, point JAVA_HOME at a JDK 17+. |
SDK location not found | local.properties is missing. Open the project in Android Studio once, or create it with sdk.dir=/path/to/Android/sdk. |
Permission denied: ./gradlew | See Building from the command line. |
INSTALL_FAILED_UPDATE_INCOMPATIBLE | A build signed with a different key is installed. Uninstall it first. |
| App opens but no listings load | The device cannot reach BASE_URL. Check internet access and that the server in build.gradle.kts is up. |