#!/usr/bin/env bash
# Build (and optionally install) the Pad Android APK for the local emulator.
#
# Usage:
# ./scripts/build_emu.sh # build + install to the connected device
# ./scripts/build_emu.sh --no-install # build only
#
# Output: cmd/pad/pad-emu.apk
#
# Prereqs on this workstation (the script checks each and explains what is
# missing):
# - JDK 17 (java on PATH)
# - Go + gogio v0.10.0 (~/go/bin)
# - Android SDK at ~/android-sdk (platform-tools, build-tools 35.0.0)
# - debug keystore at ~/.android/debug.keystore
# apktool is not a prerequisite: if it is missing, the script downloads
# v3.0.3 to the stable location ~/android-sdk/tools/apktool.jar.
#
# Why the apktool detour: gogio does not offer a way to add
# MANAGE_EXTERNAL_STORAGE to the manifest, and Android 11+ blocks the app's
# directory listing without it. So we decode the gogio APK, inject the
# permission, rebuild, and re-sign with the debug key.
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: auto-download to a stable location if missing (never /tmp, which
# gets wiped between sessions).
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) ==="
(cd "$REPO/cmd/pad" && gogio -target android -targetsdk 35 -arch amd64 -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-emu.apk" "$WORK/pad-unsigned.apk"
if [ "$INSTALL" = "1" ]; then
echo "=== install ==="
adb get-state >/dev/null 2>&1 || die "no adb device (start the emulator or plug in a phone)"
adb install -r "$REPO/cmd/pad/pad-emu.apk"
fi
echo "=== DONE: $REPO/cmd/pad/pad-emu.apk ==="