Code is not a literal. Green is what this palette colours a literal, so painting a whole fenced block green said the block *was* one -- and it disagreed with the syntax highlighter a tool call's input already gets, where green means a string and peach means a number. Code blocks and inline spans now take the ordinary text colour; the monospace face and the tinted background are what say "this is code", which is the part colour was not doing. `codeColor` goes with it, since nothing else wanted a colour for code. Where a literal really does appear inside code, the thing that should colour it is a highlighter reading the code, not a rule about the container. `run-android.sh` derives its AVD name from the checkout instead of defaulting to a machine-wide `tdep`. That default made the emulator the one thing here that cannot be worked on in parallel: two clones of this repo meant asking whoever had it, waiting, and handing it back, and installing onto a running one takes the foreground from whatever they were looking at. Derived rather than written down, so neither clone names the other's, and `AVD_NAME=` still overrides for sharing one deliberately. Also: two things reported as markdown defects yesterday were not defects, and are worth recording so nobody fixes them twice. The table is not clipped -- it scrolls horizontally, which the renderer does whenever the columns are wider than the screen; a screenshot of one looks exactly like a clipped table, and swiping it shows the rest. The paragraph that appeared to break around an inline code span was an artifact of how the test text was sent through the echo driver, not of the renderer: sent as one message it flows correctly.
114 lines
4.1 KiB
Bash
Executable File
114 lines
4.1 KiB
Bash
Executable File
#!/bin/sh
|
|
# Builds and runs this app on an emulator, creating/booting the AVD first if
|
|
# it isn't already up. Same flow as dev-updater's run-android.sh; see that
|
|
# script for the reasoning behind the avd handling.
|
|
#
|
|
# Environment setup (SDK location, PATH, ...) lives in ./android-env.sh,
|
|
# which can also be sourced directly for one-off commands.
|
|
set -eu
|
|
|
|
APP_ID="com.example.aiapp"
|
|
|
|
DEVICE_PROFILE="${DEVICE_PROFILE:-pixel_10}"
|
|
SYSTEM_IMAGE="${SYSTEM_IMAGE:-system-images;android-36;google_apis;x86_64}"
|
|
|
|
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
cd "$SCRIPT_DIR"
|
|
|
|
# One AVD per checkout, named after it -- so two clones of this repo, or a
|
|
# clone and a worktree, each get their own rather than fighting over one.
|
|
# This used to default to a machine-wide "tdep", which made the emulator the
|
|
# one thing here that could not be worked on in parallel: taking it meant
|
|
# asking whoever had it, waiting, and handing it back, and installing onto a
|
|
# running one steals the foreground from whatever they were looking at.
|
|
# Derived rather than written down, so neither clone names the other's.
|
|
# Override with AVD_NAME=... to share one deliberately.
|
|
AVD_NAME="${AVD_NAME:-$(basename "$(dirname "$SCRIPT_DIR")")}"
|
|
|
|
# shellcheck source=./android-env.sh
|
|
. ./android-env.sh
|
|
|
|
# Prints the adb serial of a running instance of AVD "$1", or nothing.
|
|
avd_serial() {
|
|
for s in $(adb devices | awk '$2 == "device" {print $1}'); do
|
|
if [ "$(adb -s "$s" emu avd name 2>/dev/null | head -n1 | tr -d '\r')" = "$1" ]; then
|
|
echo "$s"
|
|
return 0
|
|
fi
|
|
done
|
|
}
|
|
|
|
echo "==> Ensuring emulator system image is installed"
|
|
android sdk install emulator "$SYSTEM_IMAGE" || echo " (non-fatal: see above)"
|
|
|
|
if [ ! -f "$ANDROID_AVD_HOME/$AVD_NAME.ini" ]; then
|
|
echo "==> Creating AVD '$AVD_NAME' ($DEVICE_PROFILE, $SYSTEM_IMAGE)"
|
|
echo no | avdmanager create avd \
|
|
-n "$AVD_NAME" \
|
|
-k "$SYSTEM_IMAGE" \
|
|
--device "$DEVICE_PROFILE" \
|
|
--sdcard 512M
|
|
else
|
|
echo "==> Reusing existing AVD '$AVD_NAME'"
|
|
fi
|
|
|
|
# Host keyboard into the emulator -- this app has text fields.
|
|
CONFIG_INI="$ANDROID_AVD_HOME/$AVD_NAME.avd/config.ini"
|
|
if [ -f "$CONFIG_INI" ]; then
|
|
grep -v '^hw\.keyboard=' "$CONFIG_INI" >"$CONFIG_INI.tmp"
|
|
echo "hw.keyboard=yes" >>"$CONFIG_INI.tmp"
|
|
mv "$CONFIG_INI.tmp" "$CONFIG_INI"
|
|
fi
|
|
|
|
SERIAL=$(avd_serial "$AVD_NAME")
|
|
if [ -n "$SERIAL" ]; then
|
|
echo "==> Emulator '$AVD_NAME' already running ($SERIAL)"
|
|
else
|
|
# Clean up a stray/crashed process for this AVD, if any. The bracketed
|
|
# first character keeps the pattern from matching the shell running
|
|
# this script -- unbracketed, this kills that shell mid-run.
|
|
pkill -f "[e]mulator.*-avd $AVD_NAME" >/dev/null 2>&1 || true
|
|
|
|
EMU_LOG="/tmp/$AVD_NAME-emulator.log"
|
|
: >"$EMU_LOG"
|
|
if [ -n "${DISPLAY:-}" ] || [ -n "${WAYLAND_DISPLAY:-}" ]; then
|
|
echo "==> Starting emulator '$AVD_NAME' with GPU acceleration (-gpu host)"
|
|
emulator -avd "$AVD_NAME" -gpu host -no-audio >"$EMU_LOG" 2>&1 &
|
|
else
|
|
echo "==> No display -- starting emulator '$AVD_NAME' headless (-gpu swiftshader_indirect)"
|
|
emulator -avd "$AVD_NAME" -gpu swiftshader_indirect -no-audio -no-window \
|
|
>"$EMU_LOG" 2>&1 &
|
|
fi
|
|
EMU_PID=$!
|
|
|
|
i=0
|
|
booted=""
|
|
while [ "$i" -lt 150 ]; do
|
|
if ! kill -0 "$EMU_PID" 2>/dev/null; then
|
|
echo "Emulator process exited unexpectedly. Log output:" >&2
|
|
cat "$EMU_LOG" >&2
|
|
exit 1
|
|
fi
|
|
SERIAL=$(avd_serial "$AVD_NAME")
|
|
if [ -n "$SERIAL" ]; then
|
|
booted=$(adb -s "$SERIAL" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')
|
|
[ "$booted" = "1" ] && break
|
|
fi
|
|
i=$((i + 1))
|
|
sleep 2
|
|
done
|
|
if [ "$booted" != "1" ]; then
|
|
echo "Emulator did not finish booting in time. Log output:" >&2
|
|
cat "$EMU_LOG" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "==> Building debug APK"
|
|
./gradlew :androidApp:assembleDebug
|
|
|
|
APK="androidApp/build/outputs/apk/debug/androidApp-debug.apk"
|
|
echo "==> Installing and launching $APK"
|
|
adb -s "$SERIAL" install -r "$APK"
|
|
adb -s "$SERIAL" shell am start -n "$APP_ID/.MainActivity"
|