All checks were successful
Docker Build and Push / build-image (push) Successful in 2m45s
144 lines
5.0 KiB
Bash
144 lines
5.0 KiB
Bash
#!/usr/bin/env bash
|
|
# iBoard Android APK 打包
|
|
# 用法: bash scripts/wsl/build-apk.sh [debug|release]
|
|
# release 模式自动构建 4 个 ABI 并出 universal APK
|
|
set -euo pipefail
|
|
|
|
WIN_PROJECT='/mnt/d/workbench/iboard'
|
|
cd "$WIN_PROJECT"
|
|
|
|
VARIANT="${1:-debug}"
|
|
echo "构建变体: $VARIANT"
|
|
|
|
# 环境变量
|
|
export ANDROID_HOME="${ANDROID_HOME:-$HOME/android-sdk}"
|
|
export ANDROID_NDK_HOME="${ANDROID_NDK_HOME:-$ANDROID_HOME/ndk/27.2.12479018}"
|
|
# 关键: 把 NDK toolchain bin 加进 PATH, .cargo/config.toml 里
|
|
# linker = "aarch64-linux-android24-clang" 这种短名才能被解析到
|
|
NDK_TOOLCHAIN_BIN="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
|
|
if [ ! -d "$NDK_TOOLCHAIN_BIN" ]; then
|
|
echo "ERROR: NDK toolchain bin 不存在: $NDK_TOOLCHAIN_BIN"
|
|
echo "请确认 ANDROID_NDK_HOME 正确指向 NDK 27.2.x 目录"
|
|
exit 1
|
|
fi
|
|
export PATH="$NDK_TOOLCHAIN_BIN:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$HOME/.cargo/bin:$PATH"
|
|
|
|
# 0. 首次需要 android 工程
|
|
cd src-tauri
|
|
if [ ! -d "gen/android" ]; then
|
|
echo "=== 0. 初始化 Android 工程 (一次性) ==="
|
|
npx tauri android init
|
|
fi
|
|
cd "$WIN_PROJECT"
|
|
|
|
# Android 后端地址, 写到前端 bundle 里 (覆盖默认的 /api 相对路径)
|
|
export VITE_API_BASE="${VITE_API_BASE:-http://bh.vps.honor3.com:3001}"
|
|
echo "VITE_API_BASE=$VITE_API_BASE"
|
|
|
|
# 1. 先构建前端, 让 Tauri android 工程能拿到 dist/
|
|
echo "=== 1. 构建前端 ==="
|
|
npm run build
|
|
|
|
# 1.5 拷贝 dist/ 到 Android 工程 assets/, 绕过 Tauri CLI 时这步要做
|
|
# Tauri CLI 默认在 android build 前会干这事, 我们走直 gradle 要自己补上
|
|
ANDROID_ASSETS="$WIN_PROJECT/src-tauri/gen/android/app/src/main/assets"
|
|
mkdir -p "$ANDROID_ASSETS"
|
|
# 清空旧的 (避免上次的残余)
|
|
find "$ANDROID_ASSETS" -mindepth 1 -maxdepth 1 ! -name dexopt ! -name tauri.conf.json -exec rm -rf {} +
|
|
cp -r dist/. "$ANDROID_ASSETS/"
|
|
echo "前端 bundle 已拷贝到 $ANDROID_ASSETS"
|
|
ls -la "$ANDROID_ASSETS" | head -10
|
|
|
|
# 2. 走不同路径
|
|
cd src-tauri
|
|
|
|
# 全部 4 个 Android 架构的 rustBuild 任务 (Tauri 2 默认会编 4 个)
|
|
RUST_BUILD_TASKS=(
|
|
":app:rustBuildArm64Release"
|
|
":app:rustBuildArmRelease"
|
|
":app:rustBuildX86_64Release"
|
|
":app:rustBuildX86Release"
|
|
)
|
|
SKIP_ARGS=()
|
|
for t in "${RUST_BUILD_TASKS[@]}"; do SKIP_ARGS+=(-x "${t#:}"); done
|
|
|
|
# 4 个 Android 目标的 cargo target triple
|
|
ANDROID_TARGETS=(
|
|
"aarch64-linux-android"
|
|
"armv7-linux-androideabi"
|
|
"x86_64-linux-android"
|
|
"i686-linux-android"
|
|
)
|
|
|
|
if [ "$VARIANT" = "release" ]; then
|
|
echo "[release] 手工 cargo 编 lib (4 个 ABI), gradle 只跑 packaging (跳过 rustBuild* 避免 --release 重复 bug)"
|
|
|
|
for target in "${ANDROID_TARGETS[@]}"; do
|
|
echo " [cargo] build lib release for $target ..."
|
|
cargo build \
|
|
--target "$target" \
|
|
--features custom-protocol \
|
|
--lib \
|
|
--release
|
|
done
|
|
|
|
echo " [gradle] assembleRelease -x rustBuild* ..."
|
|
cd gen/android
|
|
./gradlew --no-daemon assembleRelease "${SKIP_ARGS[@]}"
|
|
|
|
APK_DIR="$WIN_PROJECT/src-tauri/gen/android/app/build/outputs/apk/universal/release"
|
|
# Gradle 配了 signingConfig 就输出 app-universal-release.apk,
|
|
# 否则输出 app-universal-release-unsigned.apk, 按文件名判断是否已签名
|
|
SIGNED_APK="$APK_DIR/app-universal-release.apk"
|
|
UNSIGNED_APK="$APK_DIR/app-universal-release-unsigned.apk"
|
|
|
|
if [ -f "$SIGNED_APK" ]; then
|
|
APK_PATH="$SIGNED_APK"
|
|
APK_STATUS="已签名"
|
|
elif [ -f "$UNSIGNED_APK" ]; then
|
|
APK_PATH="$UNSIGNED_APK"
|
|
APK_STATUS="未签名"
|
|
else
|
|
APK_PATH=""
|
|
APK_STATUS="未找到"
|
|
fi
|
|
|
|
echo
|
|
echo "=== 产物 ($APK_STATUS) ==="
|
|
if [ -n "$APK_PATH" ]; then
|
|
ls -lh "$APK_PATH"
|
|
else
|
|
ls -lh "$APK_DIR"/*.apk 2>/dev/null || echo "(未找到 APK)"
|
|
fi
|
|
|
|
if [ "$APK_STATUS" = "已签名" ]; then
|
|
echo
|
|
echo "=== 安装到设备 ==="
|
|
echo " adb install -r $APK_PATH"
|
|
elif [ "$APK_STATUS" = "未签名" ]; then
|
|
echo
|
|
echo "=== Release 签名 (按需) ==="
|
|
echo "1. 生成 keystore (一次性):"
|
|
echo " keytool -genkey -v -keystore ~/iboard-release.keystore -alias iboard -keyalg RSA -keysize 2048 -validity 10000"
|
|
echo "2. 在 ~/.gradle/gradle.properties 写:"
|
|
echo " IBOARD_UPLOAD_STORE_FILE=/home/$(whoami)/iboard-release.keystore"
|
|
echo " IBOARD_UPLOAD_KEY_ALIAS=iboard"
|
|
echo " IBOARD_UPLOAD_STORE_PASSWORD=..."
|
|
echo " IBOARD_UPLOAD_KEY_PASSWORD=..."
|
|
echo "3. 重跑本脚本 (Gradle 读 gradle.properties 里的 IBOARD_UPLOAD_* 自动用 releaseSigning)"
|
|
echo
|
|
echo "=== 临时用 debug keystore 手动签 (仅测试) ==="
|
|
echo " \$ANDROID_HOME/build-tools/*/apksigner sign --ks ~/.android/debug.keystore \"
|
|
echo " --ks-pass pass:android --key-pass pass:android \"
|
|
echo " $APK_PATH"
|
|
fi
|
|
else
|
|
echo "[debug] Tauri CLI debug 路径 (不传 --release 不会触发 bug), 直接走"
|
|
npx tauri android build --apk
|
|
|
|
APK_DIR="$WIN_PROJECT/src-tauri/target/debug/bundle/android/app/build/outputs/apk/debug"
|
|
echo
|
|
echo "=== 产物 ==="
|
|
ls -lh "$APK_DIR"/*.apk 2>/dev/null || echo "(未找到 APK)"
|
|
fi
|