From 95a2143e163680063afc7f83d00cd649558f6754 Mon Sep 17 00:00:00 2001 From: Greg Pomerantz Date: Mon, 17 Aug 2026 17:03:35 -0400 Subject: [PATCH] Add scripts/build_phone.sh: real-phone APK build (arm64+arm) Same pipeline as build_emu.sh (gogio -> apktool MANAGE_EXTERNAL_STORAGE injection -> debug-sign) for a real phone: -arch arm64,arm (covers any phone from the last decade; gogio accepts a comma-separated arch list) and output cmd/pad/pad-phone.apk. Notes in the header: on Android 11+ the user must grant 'All files access' in system settings after installing (MANAGE_EXTERNAL_STORAGE is app-restricted; the emulator AVD had it granted, phones do not). --- scripts/build_phone.sh | 73 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100755 scripts/build_phone.sh diff --git a/scripts/build_phone.sh b/scripts/build_phone.sh new file mode 100755 index 0000000..5e1bb7b --- /dev/null +++ b/scripts/build_phone.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# Build the Pad Android APK for a real phone (arm64 + arm), optionally +# installing it to a connected device. +# +# Usage: +# ./scripts/build_phone.sh # build + install to the connected device +# ./scripts/build_phone.sh --no-install # build only +# +# Output: cmd/pad/pad-phone.apk +# +# Same pipeline as build_emu.sh (gogio -> apktool permission injection -> +# debug-sign); the only differences are the architectures (arm64,arm covers +# any phone from the last decade) and the output name. On Android 11+ the +# user must grant the app "All files access" in system settings after +# installing (the MANAGE_EXTERNAL_STORAGE permission is a special +# app-restricted permission; the emulator AVD granted it, phones do not). +set -euo pipefail + +REPO=$(cd "$(dirname "$0")/.." && pwd) +export ANDROID_HOME=${ANDROID_HOME:-$HOME/android-sdk} +export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/35.0.0:$HOME/go/bin + +INSTALL=1 +[ "${1:-}" = "--no-install" ] && INSTALL=0 + +die() { echo "ERROR: $*" >&2; exit 1; } + +command -v java >/dev/null 2>&1 || die "java not found (need JDK 17)" +command -v gogio >/dev/null 2>&1 || die "gogio not found (need v0.10.0 in ~/go/bin)" +command -v apksigner >/dev/null 2>&1 || die "apksigner not found (need $ANDROID_HOME/build-tools/35.0.0)" +command -v adb >/dev/null 2>&1 || die "adb not found (need $ANDROID_HOME/platform-tools)" +[ -f "$HOME/.android/debug.keystore" ] || die "debug keystore missing: $HOME/.android/debug.keystore" + +APKTOOL="$ANDROID_HOME/tools/apktool.jar" +if [ ! -f "$APKTOOL" ]; then + echo "=== apktool missing; downloading v3.0.3 to $APKTOOL ===" + mkdir -p "$ANDROID_HOME/tools" + curl -fsSL -o "$APKTOOL" \ + https://github.com/iBotPeaches/Apktool/releases/download/v3.0.3/apktool_3.0.3.jar \ + || die "apktool download failed" +fi + +WORK=$(mktemp -d) +trap 'rm -rf "$WORK"' EXIT + +echo "=== gogio (Go -> APK, arm64+arm) ===" +(cd "$REPO/cmd/pad" && gogio -target android -targetsdk 35 -arch arm64,arm -o "$WORK/pad-raw.apk" .) + +echo "=== apktool decode ===" +java -jar "$APKTOOL" d "$WORK/pad-raw.apk" -o "$WORK/decoded" -f >/dev/null + +echo "=== inject MANAGE_EXTERNAL_STORAGE ===" +grep -q "MANAGE_EXTERNAL_STORAGE" "$WORK/decoded/AndroidManifest.xml" || \ + sed -i '0,/\n /dev/null + +echo "=== sign ===" +apksigner sign \ + --ks "$HOME/.android/debug.keystore" --ks-pass pass:android \ + --key-pass pass:android --ks-key-alias androiddebugkey \ + --out "$REPO/cmd/pad/pad-phone.apk" "$WORK/pad-unsigned.apk" + +if [ "$INSTALL" = "1" ]; then + echo "=== install ===" + adb get-state >/dev/null 2>&1 || die "no adb device (plug in the phone with USB debugging, or use --no-install)" + adb install -r "$REPO/cmd/pad/pad-phone.apk" +fi + +echo "=== DONE: $REPO/cmd/pad/pad-phone.apk ==="