Files
edgeever/scripts/build-android-local.sh
T

150 lines
5.7 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MOBILE_DIR="$PROJECT_ROOT/apps/mobile"
ANDROID_DIR="$MOBILE_DIR/android"
MODE="${1:-fast}"
if [[ "$MODE" != "fast" && "$MODE" != "apk" && "$MODE" != "play" ]]; then
echo "用法: $0 [fast|apk|play]" >&2
exit 2
fi
if [[ -z "${JAVA_HOME:-}" && -d /opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home ]]; then
export JAVA_HOME=/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home
fi
if [[ -n "${JAVA_HOME:-}" ]]; then
export PATH="$JAVA_HOME/bin:$PATH"
fi
if ! command -v java >/dev/null 2>&1; then
echo "未找到 Java 17。请先执行: brew install openjdk@17" >&2
exit 1
fi
if [[ -z "${ANDROID_HOME:-}" && -d /opt/homebrew/share/android-commandlinetools ]]; then
export ANDROID_HOME=/opt/homebrew/share/android-commandlinetools
fi
export ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT:-${ANDROID_HOME:-}}"
export NODE_ENV="${NODE_ENV:-production}"
run_timed() {
local label="$1"
shift
local started_at=$SECONDS
echo "[$(date '+%H:%M:%S')] 开始:${label}"
"$@"
echo "[$(date '+%H:%M:%S')] 完成:${label}($((SECONDS - started_at)) 秒)"
}
if [[ -z "$ANDROID_SDK_ROOT" ]]; then
echo "未找到 Android SDK,请设置 ANDROID_HOME 或 ANDROID_SDK_ROOT。" >&2
exit 1
fi
cd "$PROJECT_ROOT"
run_timed "安装 JavaScript 依赖" bun install --frozen-lockfile
run_timed "准备移动端图标" bun run prepare:mobile:icons
PREBUILD_FINGERPRINT="$({
shasum \
apps/mobile/app.json \
apps/mobile/assets/adaptive-icon-transparent.svg \
apps/web/public/pwa-512x512.png \
bun.lock
} | shasum | awk '{print $1}')"
PREBUILD_STAMP="$ANDROID_DIR/.edgeever-prebuild-fingerprint"
PREVIOUS_FINGERPRINT="$(test -f "$PREBUILD_STAMP" && cat "$PREBUILD_STAMP" || true)"
if [[ ! -x "$ANDROID_DIR/gradlew" || "$PREBUILD_FINGERPRINT" != "$PREVIOUS_FINGERPRINT" ]]; then
echo "更新 Android 原生工程(保留已有编译缓存)..."
cd "$MOBILE_DIR"
run_timed "生成 Android 原生工程" bunx expo prebuild --platform android
printf '%s' "$PREBUILD_FINGERPRINT" > "$PREBUILD_STAMP"
else
echo "跳过 Android prebuild:原生配置未变化。"
fi
cd "$ANDROID_DIR"
COMMON_ARGS=(
--build-cache
--parallel
--daemon
-Dorg.gradle.jvmargs=-Xmx6g\ -XX:MaxMetaspaceSize=1g\ -Dfile.encoding=UTF-8
)
: "${ANDROID_KEYSTORE_FILE:?请设置 ANDROID_KEYSTORE_FILE(本地上传密钥路径)}"
: "${ANDROID_KEYSTORE_PASSWORD:?请设置 ANDROID_KEYSTORE_PASSWORD}"
: "${ANDROID_KEY_ALIAS:?请设置 ANDROID_KEY_ALIAS}"
: "${ANDROID_KEY_PASSWORD:?请设置 ANDROID_KEY_PASSWORD}"
PLAY_ARCHS="${EDGE_EVER_ANDROID_ARCHS:-armeabi-v7a,arm64-v8a,x86,x86_64}"
APK_ARCHS="${EDGE_EVER_ANDROID_APK_ARCHS:-arm64-v8a}"
KEYSTORE_FILE="$(cd "$(dirname "$ANDROID_KEYSTORE_FILE")" && pwd)/$(basename "$ANDROID_KEYSTORE_FILE")"
APK_PATH="$ANDROID_DIR/app/build/outputs/apk/release/app-release.apk"
APKSIGNER_PATH="$ANDROID_SDK_ROOT/build-tools/36.0.0/apksigner"
if [[ "$MODE" == "fast" ]]; then
echo "构建生产签名 arm64 快速 APK(关闭 R8、资源压缩和 PNG crunch)..."
run_timed "Gradle 快速 APK 构建" ./gradlew assembleRelease \
"${COMMON_ARGS[@]}" \
-PreactNativeArchitectures=arm64-v8a \
-Pandroid.enableMinifyInReleaseBuilds=false \
-Pandroid.enableShrinkResourcesInReleaseBuilds=false \
-Pandroid.enablePngCrunchInReleaseBuilds=false \
-Pandroid.injected.signing.store.file="$KEYSTORE_FILE" \
-Pandroid.injected.signing.store.password="$ANDROID_KEYSTORE_PASSWORD" \
-Pandroid.injected.signing.key.alias="$ANDROID_KEY_ALIAS" \
-Pandroid.injected.signing.key.password="$ANDROID_KEY_PASSWORD" \
-Pandroid.injected.signing.store.type=PKCS12
test -s "$APK_PATH"
test -x "$APKSIGNER_PATH"
run_timed "校验 APK 固定签名" \
node "$PROJECT_ROOT/scripts/verify-android-apk-signature.mjs" \
"$APK_PATH" "$APKSIGNER_PATH"
echo "完成: $APK_PATH"
exit 0
fi
if [[ "$MODE" == "apk" ]]; then
echo "构建生产签名 APK(${APK_ARCHS})..."
run_timed "Gradle 生产 APK 构建" ./gradlew assembleRelease \
"${COMMON_ARGS[@]}" \
-PreactNativeArchitectures="$APK_ARCHS" \
-Pandroid.injected.signing.store.file="$KEYSTORE_FILE" \
-Pandroid.injected.signing.store.password="$ANDROID_KEYSTORE_PASSWORD" \
-Pandroid.injected.signing.key.alias="$ANDROID_KEY_ALIAS" \
-Pandroid.injected.signing.key.password="$ANDROID_KEY_PASSWORD" \
-Pandroid.injected.signing.store.type=PKCS12
AAPT2_PATH="$ANDROID_SDK_ROOT/build-tools/36.0.0/aapt2"
test -s "$APK_PATH"
test -x "$APKSIGNER_PATH"
test -x "$AAPT2_PATH"
run_timed "校验 APK 固定签名" \
node "$PROJECT_ROOT/scripts/verify-android-apk-signature.mjs" \
"$APK_PATH" "$APKSIGNER_PATH"
run_timed "读取 APK 信息" bash -c '"$1" dump badging "$2" | sed -n "1p"' _ "$AAPT2_PATH" "$APK_PATH"
run_timed "计算 APK SHA-256" shasum -a 256 "$APK_PATH"
echo "完成: $APK_PATH"
exit 0
fi
echo "构建 Play 签名 AAB(${PLAY_ARCHS})..."
run_timed "Gradle 生产 AAB 构建" ./gradlew bundleRelease \
"${COMMON_ARGS[@]}" \
-PreactNativeArchitectures="$PLAY_ARCHS" \
-Pandroid.injected.signing.store.file="$KEYSTORE_FILE" \
-Pandroid.injected.signing.store.password="$ANDROID_KEYSTORE_PASSWORD" \
-Pandroid.injected.signing.key.alias="$ANDROID_KEY_ALIAS" \
-Pandroid.injected.signing.key.password="$ANDROID_KEY_PASSWORD" \
-Pandroid.injected.signing.store.type=PKCS12
run_timed "校验 AAB 签名" jarsigner -verify app/build/outputs/bundle/release/app-release.aab
test -s app/build/outputs/mapping/release/mapping.txt
echo "完成: $ANDROID_DIR/app/build/outputs/bundle/release/app-release.aab"
echo "反混淆文件: $ANDROID_DIR/app/build/outputs/mapping/release/mapping.txt"