Files
airdisplay/build.codespace.sh
yuqianhe 8a095eecc3 fix: 适配 Codespaces SDKMAN! 环境,不碰系统默认 java
- 移除 update-alternatives(对 SDKMAN! 无效)
- 纯 JAVA_HOME 方案:安装 JDK 17 到 /usr/lib/jvm,设置 JAVA_HOME
- 构建前用 /bin/java -version 硬性验证
- Gradle 通过 -Dorg.gradle.java.home 强制使用 JDK 17
- PATH 首位放 /bin 确保 gradlew 找到正确 JDK
2026-05-30 03:48:59 +00:00

277 lines
9.3 KiB
Bash
Executable File
Raw Permalink 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
#
# build.codespace.sh — 在 GitHub Codespaces 中构建 AirDisplay APK
#
# 用法:
# chmod +x build.codespace.sh && ./build.codespace.sh
#
# 原理:
# GitHub Codespaces 通过 SDKMAN! 管理默认 JDK当前为 JDK 25
# Android Gradle Plugin 8.2.2 不支持 JDK > 21因此需要 JDK 17。
# 脚本不做 update-alternatives对 SDKMAN! 无效),而是直接安装 JDK 17、
# 设置 JAVA_HOME 指向它,并通过 -Dorg.gradle.java.home= 强递给 Gradle。
#
# 环境变量(可选):
# ANDROID_SDK_ROOT — SDK 安装路径,默认 $HOME/android-sdk
# BUILD_TYPE — debug 或 release默认 debug
#
# ──────────────────────────────────────────────
# 颜色
# ──────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
log() { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
err() { echo -e "${RED}[✗]${NC} $1"; }
info() { echo -e "${CYAN}[i]${NC} $1"; }
# ──────────────────────────────────────────────
# 配置
# ──────────────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$SCRIPT_DIR"
ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT:-$HOME/android-sdk}"
BUILD_TYPE="${BUILD_TYPE:-debug}"
CMDLINE_TOOLS_URL="https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip"
SDK_MANAGER="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager"
SDK_COMPONENTS=(
"platforms;android-34"
"build-tools;34.0.0"
"platform-tools"
)
# 运行中会填充
JAVA17_HOME=""
# ──────────────────────────────────────────────
# 阶段 1找到或安装 JDK 17
# ──────────────────────────────────────────────
install_jdk() {
info "查找/安装 JDK 17 ..."
# 扫描 apt 安装的标准路径
local found=""
for dir in /usr/lib/jvm/java-17-openjdk-*; do
if [ -d "$dir" ] && [ -x "$dir/bin/java" ]; then
found="$dir"
break
fi
done
if [ -n "$found" ]; then
JAVA17_HOME="$found"
log "JDK 17 已安装: $JAVA17_HOME"
return
fi
# 还没装,用 apt 装
warn "安装 openjdk-17-jdk-headless ..."
sudo apt-get update -qq
sudo apt-get install -y -qq openjdk-17-jdk-headless
# 装完再扫一次
for dir in /usr/lib/jvm/java-17-openjdk-*; do
if [ -d "$dir" ] && [ -x "$dir/bin/java" ]; then
JAVA17_HOME="$dir"
break
fi
done
if [ -z "$JAVA17_HOME" ]; then
err "JDK 17 安装失败,未在 /usr/lib/jvm/ 下找到"
err "手动安装: sudo apt-get install openjdk-17-jdk-headless"
exit 1
fi
log "JDK 17 安装完成: $JAVA17_HOME"
}
# ──────────────────────────────────────────────
# 阶段 2安装 Android SDK
# ──────────────────────────────────────────────
install_sdk() {
info "检查 Android SDK ..."
if [ -x "$SDK_MANAGER" ]; then
log "命令行工具已安装"
else
warn "下载 Android 命令行工具 ..."
mkdir -p "$ANDROID_SDK_ROOT"
cd "$ANDROID_SDK_ROOT"
curl -fsSL "$CMDLINE_TOOLS_URL" -o cmdline-tools.zip
unzip -q cmdline-tools.zip
rm -f cmdline-tools.zip
mkdir -p cmdline-tools/latest
if [ -d cmdline-tools/bin ]; then
mv cmdline-tools/bin cmdline-tools/latest/
mv cmdline-tools/lib cmdline-tools/latest/
mv cmdline-tools/NOTICE.txt cmdline-tools/latest/ 2>/dev/null || true
mv cmdline-tools/source.properties cmdline-tools/latest/ 2>/dev/null || true
fi
log "命令行工具已安装"
fi
info "接受 SDK licenses ..."
yes | "$SDK_MANAGER" --licenses 2>&1 | tail -1 || true
info "安装 SDK 组件(首次需 1-2 分钟)..."
for comp in "${SDK_COMPONENTS[@]}"; do
local dir_path="${comp/;/\/}"
if [ -d "$ANDROID_SDK_ROOT/$dir_path" ]; then
log " 已安装: $comp"
continue
fi
info " 安装: $comp ..."
yes | "$SDK_MANAGER" "$comp" 2>&1 | tail -1 || true
done
log "Android SDK 就绪"
}
# ──────────────────────────────────────────────
# 阶段 3local.properties
# ──────────────────────────────────────────────
setup_local_properties() {
info "配置 local.properties ..."
local props="$PROJECT_DIR/local.properties"
if [ -f "$props" ] && grep -q "sdk.dir" "$props" 2>/dev/null; then
log "已存在"
return
fi
rm -f "$props"
{
echo "# Auto-generated by build.codespace.sh"
echo "# $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "sdk.dir=$ANDROID_SDK_ROOT"
echo "org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m"
} > "$props"
log "已生成"
}
# ──────────────────────────────────────────────
# 阶段 4Gradle Wrapper
# ──────────────────────────────────────────────
setup_gradle_wrapper() {
if [ -x "$PROJECT_DIR/gradlew" ]; then
log "Gradle Wrapper 已存在"
return
fi
info "生成 Gradle Wrapper (v8.5) ..."
if ! command -v gradle &>/dev/null; then
sudo apt-get install -y -qq gradle > /dev/null 2>&1
fi
cd "$PROJECT_DIR"
gradle wrapper --gradle-version 8.5 > /dev/null 2>&1
chmod +x gradlew
log "完成"
}
# ──────────────────────────────────────────────
# 阶段 5构建 APK
# ──────────────────────────────────────────────
build_apk() {
# ---- 验证 JAVA_HOME ----
if [ -z "$JAVA17_HOME" ] || [ ! -x "$JAVA17_HOME/bin/java" ]; then
err "JAVA17_HOME 无效: $JAVA17_HOME"
exit 1
fi
local ver
ver=$("$JAVA17_HOME/bin/java" -version 2>&1 | head -1)
if ! echo "$ver" | grep -q 'version "17'; then
err "JAVA17_HOME 下不是 JDK 17: $ver"
exit 1
fi
log "JDK 17 确认: $ver"
# ---- 导出 ----
export JAVA_HOME="$JAVA17_HOME"
export ANDROID_SDK_ROOT
# 把 JDK 17 的 bin 放 PATH 首位,同时加入 platform-tools
export PATH="$JAVA_HOME/bin:$ANDROID_SDK_ROOT/platform-tools:$PATH"
# ---- 检查 gradlew ----
cd "$PROJECT_DIR"
if [ ! -f gradlew ]; then
setup_gradle_wrapper
fi
# ---- 构建 ----
info "开始构建 $BUILD_TYPE APK ..."
# 关键: -Dorg.gradle.java.home 强制 Gradle 使用 JDK 17
local gradle_args=(
"-Dorg.gradle.java.home=$JAVA_HOME"
"--no-daemon"
)
if [ "$BUILD_TYPE" = "release" ]; then
warn "Release 需要 keystore尝试构建 ..."
./gradlew "${gradle_args[@]}" assembleRelease 2>&1 || true
else
./gradlew "${gradle_args[@]}" assembleDebug 2>&1
fi
local rc=$?
echo ""
if [ $rc -ne 0 ]; then
warn "构建失败 (exit=$rc)"
warn "常见原因:"
warn " - 网络超时 → 重试"
warn " - 内存不足 → 加 --no-daemon 重试"
warn "重试: cd $PROJECT_DIR && JAVA_HOME=$JAVA_HOME ./gradlew -Dorg.gradle.java.home=\$JAVA_HOME --no-daemon assembleDebug"
return
fi
local apks
apks=$(find "$PROJECT_DIR/app/build/outputs/apk" -name "*.apk" 2>/dev/null)
if [ -n "$apks" ]; then
log "构建成功!"
echo "$apks" | while read -r f; do
echo " $(ls -lh "$f" | awk '{print $5, $NF}')"
done
else
warn "未找到 APK 输出"
fi
}
# ──────────────────────────────────────────────
# 主流程
# ──────────────────────────────────────────────
echo ""
echo -e "${CYAN}══════════════════════════════════════════════${NC}"
echo -e "${CYAN} AirDisplay -- Codespaces APK 构建脚本${NC}"
echo -e "${CYAN}══════════════════════════════════════════════${NC}"
echo ""
echo " 项目目录: $PROJECT_DIR"
echo " SDK 路径: $ANDROID_SDK_ROOT"
echo " 构建类型: $BUILD_TYPE"
echo " 系统 java: $(java -version 2>&1 | head -1)"
echo ""
install_jdk
install_sdk
setup_local_properties
setup_gradle_wrapper
build_apk
echo ""
local_apk="$PROJECT_DIR/app/build/outputs/apk/debug/app-debug.apk"
if [ -f "$local_apk" ]; then
log "APK 已就绪: $local_apk"
echo " 安装: adb install -r $local_apk"
else
echo -e "${YELLOW}提示: 若因网络超时失败,重试即可${NC}"
echo -e "${YELLOW} cd $PROJECT_DIR && ./build.codespace.sh${NC}"
fi
echo ""