Files
SoulStream/src-tauri/android/dev.sh
T
KeelrLeek 4ebc38d5f3 android: the falcon on the launcher — a real adaptive icon, with the monochrome layer
The phone has been wearing tauri's logo. `tauri android init` writes the
generated project's `res/` from its own template and never reads
`src-tauri/icons/android/`, which has carried the falcon since 50afa6a, and the
detour build runs cargo and Gradle directly — so nothing ever copied it across:
the two dominant colours in the packaged `mipmap-xxxhdpi/ic_launcher.png` are
`#24c8db` and `#ffc131`, tauri's own brand cyan and amber. `src-tauri/android/res/`
is the app module's res now, tracked, and `build.sh` and `dev.sh` copy the whole
tree into `gen/android` before Gradle, because that project is regenerated and
gitignored and an asset that only lives there is an asset that disappears.

It is a real adaptive icon: the kit's foreground and its **monochrome** layer at
five densities, the legacy mipmaps under it, and the background as one
`#FF05080B` colour resource rather than five identical flat PNGs, so the gradient
being mocked separately replaces one file. The kit's own XML could not ship — it
points every layer at `@drawable/` while shipping them as PNGs under `mipmap-*`,
and in the generated project two of those three references resolve to Android
Studio's template robot rather than failing — so the overlay's XML says
`@mipmap/` and `@color/`, and its colour file takes the same name tauri's does,
because two files declaring one colour is a hard aapt2 error.

Losing the copy would be silent — the APK still builds, still installs, and wears
the old logo with nothing in the log — so `verify-icon.sh` opens every APK both
scripts make and reads the resources back out: the two `mipmap-anydpi-v26` XMLs
present, and four PNG names at five densities byte for byte from the overlay. A
release APK keeps neither the bytes nor the names — AGP re-encodes every PNG and
shortens every resource path — so that path asks `aapt2 dump resources` what each
name points at and compares pixel dimensions instead; 72×72 at hdpi still tells
the kit's icon from tauri's 49×49. No walk step: a launcher icon is not reachable
from inside the app, and the masking and the themed layer want a minute with the
phone's home screen.
2026-09-15 07:22:00 -05:00

64 lines
3.5 KiB
Bash

#!/usr/bin/env bash
# The DEV flavour (ANDROID.md → "Iterating without cargo"): the detour build
# WITHOUT tauri's custom-protocol feature, so the library embeds the dev URL
# (http://localhost:1421) instead of dist/. On the phone, `adb reverse` makes
# the phone's localhost:1421 THIS machine's Vite dev server over the USB
# cable — no LAN address, no firewall hole, hot reload — and cargo runs only
# when Rust changes. Both flavours share target/: switching flavours
# recompiles tauri and the app crate once (~3 min), the leaf crates stay
# fresh — cheaper than a second 15 GB cache on this drive.
#
# bash src-tauri/android/dev.sh # build (when Rust changed) + install + tunnel + launch
# bash src-tauri/android/dev.sh --no-build # reinstall the last dev library, re-tunnel, launch
# bash src-tauri/android/dev.sh --build-only # just the library (the phone is busy or absent)
# bash src-tauri/android/deploy.sh # the embedded build again (what the phone keeps)
#
# Then start the "frontend" dev server (npm run dev / the Browser pane's
# "frontend" launch config). The phone needs it running — and the cable.
set -euo pipefail
cd /f/Coding/SoulStream
export MSYS_NO_PATHCONV=1
source src-tauri/android/env.sh
if [ "${1:-}" != "--no-build" ]; then
echo "== cargo (dev flavour) $(date +%T)"
cargo build --lib -p app --target aarch64-linux-android 2>&1 | grep -v "^\s*Compiling\|^\s*Fresh"
test "${PIPESTATUS[0]}" -eq 0 || { echo "cargo failed — not packaging"; exit 1; }
[ "${1:-}" = "--build-only" ] && { echo "== built $(date +%T)"; exit 0; }
fi
SO=target/aarch64-linux-android/debug/libapp_lib.so
test -f "$SO" || { echo "no dev .so built"; exit 1; }
echo "== strip $(date +%T)"
DEST=src-tauri/gen/android/app/src/main/jniLibs/arm64-v8a
mkdir -p "$DEST"
cp "$SO" "$DEST/libapp_lib.so"
"$BIN/llvm-strip.exe" --strip-debug "$DEST/libapp_lib.so"
# The launcher identity, into a project that cannot keep it: gen/android is
# regenerated by the tauri CLI and gitignored, and the detour build never runs
# that CLI, so the res it holds is still the one `android init` wrote — tauri's
# own logo. Everything under src-tauri/android/res/ is copied over it on every
# build. The whole tree, not a file list: a later round adding a resource adds
# a file there and this line does not change.
echo "== res overlay $(date +%T)"
test -d src-tauri/android/res || { echo "src-tauri/android/res is gone — the APK would wear tauri's logo and say nothing"; exit 1; }
cp -r src-tauri/android/res/. src-tauri/gen/android/app/src/main/res/
echo "== gradle $(date +%T)"
cd src-tauri/gen/android
./gradlew.bat assembleArm64Debug -x rustBuildArm64Debug -q 2>&1 | grep -v "^$" | tail -20 || true
cd /f/Coding/SoulStream
APK=src-tauri/gen/android/app/build/outputs/apk/arm64/debug/app-arm64-debug.apk
bash src-tauri/android/verify-icon.sh "$APK"
echo "== install $(date +%T)"
"$ADB" install -r "$APK" 2>&1 | tail -1
"$ADB" shell pm grant com.soulstream.app android.permission.POST_NOTIFICATIONS 2>/dev/null || true
# the tunnel: the phone's localhost:1421 → this machine's 1421 (Vite)
"$ADB" reverse tcp:1421 tcp:1421
"$ADB" shell am force-stop com.soulstream.app
FOCUS=$("$ADB" shell dumpsys window 2>/dev/null | grep -a "mCurrentFocus" | head -1)
if echo "$FOCUS" | grep -qi "soulstream\|launcher"; then
"$ADB" shell am start -n com.soulstream.app/.MainActivity >/dev/null
echo "== launched $(date +%T) — serve the frontend on 1421 (npm run dev) if it is not up"
else
echo "== installed; not launched (the phone is in use: $FOCUS)"
fi